數據結構--線性表(單鏈表)

正在學習數據結構,第一步是線性表,寫一個bookLinkList.ios

同時開始用vianal studio. 固然不是很熟悉這個IDE,但感受挺厲害的。算法

下面的這個booklist 不是本人寫的,感謝Liu老師。數據結構

 

鏈表是一種動態結構,整個可用存儲空間可爲多個鏈表共同享用。函數

每一個鏈表佔用的空間不須要預先分配劃定,而是系統按需及時生成。
學習

創建線性表的鏈式存儲結構的過程是一個動態生成鏈表的過程。測試

從空表的初始狀態起,依次創建各元素節點,並逐個插入鏈表。spa


// BookLinkList.cpp : This file contains the 'main' function. Program execution begins and ends there. // by lyj.
 #include <iostream>
using namespace std; #define OK 1
#define ERROR 0
#define OVERFLOW -2 typedef int Status; typedef struct Book { char no[20]; char name[50]; float price;
  //符號重載
bool operator==(const Book& anotherbook) { return (!strcmp(no, anotherbook.no)); } bool operator!=(const Book& anotherbook) { return(strcmp(no, anotherbook.no)); } friend istream &operator >> (istream &i, Book& b)//輸入流 { cout << "請輸入書號:"; i >> b.no; cout << "請輸入書名:"; i >> b.name; cout << "請輸入價格:"; i >> b.price; cout << "\n"; return i; } }Book; typedef struct LNode//(1)LNode是結構類型名 { Book data; struct LNode *next;//(2)第二個LNode是用的(1)定義了一個LNode類型的指針 }LNode, *LinkList;//(3)第三個LNode是(1)結構體的別名,這裏用了相同的名字。LinkList=LNode *; //通常用LinkList定義單鏈表頭指針,用LNode*定義某個節點指針

*** 注意區分頭結點,首元結點,頭指針。指針

    初始化鏈表(只有一個頭節點的空鏈表)code

Status InitList(LinkList &L) { L = new LNode; L->next = NULL; return OK; }

 

——下面的函數是假定鏈表已經存在多個節點:blog


一、取值   用指針p指向首元結點,用 j 作計數器初值賦1 。從首元結點開始依次順着鏈域next向下訪問,只要指向當前節點的指針p不爲NULL,並無達到序號爲 i 的節點,則循環操做:p指向下一個節點,計時器 j 相應加1 。取值算法的時間複雜度爲:O(n)

tatus GetElem(LinkList L, int i, Book &e) { LNode *p; int j; p = L->next; j = 1; while (p && j < i) { p = p->next; j++; } if (!p || j > i) return ERROR; e = p->data; return OK; }

 二、查找 從鏈表的首元結點出發,依次將節點值和給定值e進行比較,返回查找結果。查找算法時間複雜度也爲:O(n)

LNode *LocateElem(LinkList L, Book e) { LNode *p; p = L->next; while (p && p->data != e) p = p->next; return p; }

 三、插入 (可插入位置爲n+1個)時間複雜度也爲:O(n)

Status ListInsert(LinkList &L, int i, Book e) { LNode *s, *p; int j; p = L; j = 0; while (p && j < i - 1) { p = p->next; j++; }//查找第i-1個節點,p指向該節點 if (!p || j > i - 1) return ERROR; s = new LNode; s->data = e;//將e存入*s的數據域 s->next = p->next;//把p的下一個節點的地址給*s的指針域,即將p後面的節點連入s的尾部 p->next = s;//將s自己的地址(理解爲s的頭)放入p的尾部 return OK; }

 刪除節點(按序號刪除 和 按節點中數據項關鍵字刪除)

Status ListDelete(LinkList &L, int i)   //按序號刪除元素(結點)
{ LNode *p, *q; int j; p = L; j = 0; while (p->next && j < i - 1) { p = p->next; j++; } if (!p->next || j > i - 1) return ERROR; q = p->next; p->next = q->next; delete q; return OK; }
Status DelElem(LinkList &L, Book e)  //按結點中數據項的關鍵字值刪除結點
{ LNode *p, *q; p = L; while (p->next && strcmp(p->next->data.no, e.no)) { p = p->next; } if (!p->next) return ERROR; q = p->next; p->next = q->next; delete q; return OK; }

四、鏈表銷燬

Status DestroyList(LinkList &L) { LNode *p; while (L->next != NULL) { p = L; L = L->next; delete p; } delete L; return OK; }

五、鏈表顯示

 

void ListDisplay(LinkList L) { cout << "書號\t書名\t價格\n"; while (L->next != NULL) { L = L->next; cout << L->data.no << "\t" << L->data.name << "\t" << L->data.price << "\n"; } }

 

 

 

前面只建立了有一個頭結點的空鏈表,下面將創建一個包含若干個節點的鏈表

根據節點插入位置不一樣,鏈表的建立能夠分爲:前插 和 後插

 

void CreateList_H(LinkList &L, int n)  //前插法
{ LNode *p; L = new LNode; L->next = NULL; for (int i = 0; i < n; i++) { p = new LNode; cin >> p->data; p->next = L->next; L->next = p; } }
void CreateList_R(LinkList &L, int n)  //後插法
{ LNode *r, *p; L = new LNode; L->next = NULL; r = L; for (int i = 0; i < n; i++) { p = new LNode; cin >> p->data; p->next = NULL; r->next = p; r = p; } }

差很少就是這樣,而後來一個main測試一下

int main() { LinkList bookLinkList; char ch; int n; cout << "\n+-------------------------------------------------------+\n"; cout << "+ 請選擇要進行的操做:\t\t\t\t\t+\n"; cout << "+\t<按數字鍵1> 建立一個只含頭結點的空的單鏈表\t+\n"; cout << "+\t<按數字鍵2> 建立一個包含頭結點和n個元素的單鏈表\t+\n"; cout << "+\t<按其餘任意鍵> 退出程序\t\t\t\t+\n"; cout << "+-------------------------------------------------------+\n"; ch = _getwch(); if (ch == '1') { InitList(bookLinkList); } else if (ch == '2') { cout << "\n請輸入單鏈表中要包含的元素個數:"; cin >> n; cout << "請選擇:<a>使用前插法\t<b>使用後插法\n"; while (1) { ch = _getwch(); if (ch == 'a') { CreateList_H(bookLinkList, n); break; } else if (ch == 'b') { CreateList_R(bookLinkList, n); break; } } } else { exit(0); } while (1) { cout << "\n\n------------------------------------------------------------------------------------\n"; cout << "+請選擇要進行的操做:<a>顯示 <b>插入元素 <c>刪除元素 <d>查找 <x>退出+\n"; cout << "------------------------------------------------------------------------------------\n"; ch = _getwch(); if (ch == 'x') break; else if (ch == 'a') ListDisplay(bookLinkList); else if (ch == 'b') { int i; cout << "請輸入插入的位置:"; cin >> i; Book b; cin >> b; if (ListInsert(bookLinkList, i, b) == OK) cout << "元素插入第" << i << "個位置成功。\n"; else cout << "元素插入第" << i << "個位置失敗。\n"; } else if (ch == 'c') { cout << "請選擇:<a>按位置序號刪除元素\t<b>按元素中數據項的關鍵字值刪除元素\n"; while (1) { ch = _getwch(); if (ch == 'a') { cout << "請輸入要刪除的元素的位置序號:"; int i; cin >> i; if (ListDelete(bookLinkList, i) == OK) cout << "刪除成功!\n"; else cout << "刪除失敗!\n"; break; } else if (ch == 'b') { cout << "請輸入要刪除的書籍的書號:"; Book b; cin >> b.no; if (DelElem(bookLinkList, b) == OK) cout << "刪除成功!\n"; else cout << "刪除失敗!\n"; break; } } } else if (ch == 'd') { cout << "請輸入要查找的書籍的書號:"; Book t; cin >> t.no; LNode *p = LocateElem(bookLinkList, t); if (p == NULL) cout << "查找失敗!\n"; else { cout << "查找成功! 找到的書籍爲:\n"; cout << "書號\t書名\t價格\n"; cout << p->data.no << "\t" << p->data.name << "\t" << p->data.price << "\n"; } } } DestroyList(bookLinkList); }
相關文章
相關標籤/搜索