鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。相比于線性表順序結構,操作復雜。由于不必須按順序存儲,鏈表在插入的時候可以達到O(1)的復雜度,比另一種線性表順序表快得多,但是查找一個節點或者訪問特定編號的節點則需要O(n)的時間,而線性表和順序表相應的時間復雜度分別是O(logn)和O(1)。
使用鏈表結構可以克服數組鏈表需要預先知道數據大小的缺點,鏈表結構可以充分利用計算機內存空間,實現靈活的內存動態管理。但是鏈表失去了數組隨機讀取的優點,同時鏈表由于增加了結點的指針域,空間開銷比較大。鏈表明顯的好處就是,常規數組排列關聯項目的方式可能不同于這些數據項目在記憶體或磁盤上順序,數據的存取往往要在不同的排列順序中轉換。鏈表允許插入和移除表上任意位置上的節點,但是不允許隨機存取。鏈表有很多種不同的類型:單向鏈表,雙向鏈表以及循環鏈表。鏈表可以在多種編程語言中實現。像Lisp和Scheme這樣的語言的內建數據類型中就包含了鏈表的存取和操作。程序語言或面向對象語言,如C,C++和Java依靠易變工具來生成鏈表。
其中存儲數據元素信息的域稱作數據域(設域名為data),存儲直接后繼存儲位置的域稱為指針域(設域名為next)。指針域中存儲的信息又稱做指針或鏈。
由分別表示,,…,的N 個結點依次相鏈構成的鏈表,稱為線性表的鏈式存儲表示,由于此類鏈表的每個結點中只包含一個指針域,故又稱單鏈表或線性鏈表。
linkedlist.h ?//頭文件,定義節點和鏈表信息及聲明創建、插入、刪除等基本函數
/*鏈表的實現,實現創建、插入、刪除等操作*/ #include <string> using namespace std; struct StuInfo { int id; //學號 string name; //姓名 }; struct Node { StuInfo info; Node *next; Node(){} Node(StuInfo x){ info = x; next = NULL; } }; class LinkedList { public: LinkedList(); //構造函數 ~LinkedList(); //析構函數 void insert(StuInfo info, int pos); void remove(int id); //根據學生學號進行刪除 int find(int id); //根據學號進行查找,返回節點位置 int getLength(); //獲得鏈表長度 void print(); //打印鏈表信息 private: Node *head; int length; };
下面繼續編寫對應的源文件,linkedlist.cpp ?//實現具體函數內容
#include <iostream> #include "linkedlist.h" using namespace std; //構造函數 LinkedList::LinkedList() { head = NULL; length = 0; } //析構函數 LinkedList::~LinkedList() { Node* temp; for (int i = 0; i < length; i++) { temp = head; head = head->next; delete temp; } } void LinkedList::insert(StuInfo info, int pos) { if (pos < 0) { cout << "節點位置必須是正整數" << endl; } int index = 1; Node *temp = head; Node *node = new Node(info); if (pos == 0) { node->next = temp; head = node; length++; return; } while (index < pos && temp != NULL) { temp = temp->next; index++; } if (temp == NULL) { cout << "插入失敗,位置序號超過鏈表長度" << endl; return; } node->next = temp->next; temp->next = node; length++; return; } void LinkedList::remove(int id) { int pos = find(id); if (pos == -1) { cout << "鏈表中沒有該學號,無法刪除對應信息" << endl; return; } if (pos == 0) { head = head->next; length--; return; } int index = 1; Node *temp = head; while (index < pos) { temp = temp->next; } temp->next = temp->next->next; length--; return; } int LinkedList::find(int id) { Node *temp = head; int index = 0; while (temp != NULL) { if (temp->info.id == id) { return index; } temp = temp->next; index++; } return -1; } int LinkedList::getLength() { return length; } void LinkedList::print() { if (head == NULL) { cout << "鏈表為空,沒有信息" << endl; return; } Node *temp = head; while (temp != NULL) { cout << temp->info.id << "," << temp->info.name << endl; temp = temp->next; } cout << endl; return; }
,編寫測試用的main函數
#include <iostream> #include <string> #include "linkedlist.h" using namespace std; int main() { LinkedList head; StuInfo info1, info2, info3, info4, info5; info1.id = 1001, info1.name = "張三", info2.id = 1002, info2.name = "莉絲", info3.id = 1003, info3.name = "李武", info4.id = 1004, info4.name = "六南", info5.id = 1005, info5.name = "琪琪"; //測試插入數據 cout << "測試插入:" << endl; head.insert(info1, 0); head.print(); head.insert(info2, 1); head.print(); head.insert(info3, 4); head.print(); head.insert(info4, 0); head.print(); head.insert(info5, 2); head.print(); //測試刪除數據 cout << "測試刪除:" << endl; cout << "鏈表長度為:" << head.getLength() << endl; head.remove(1004); head.print(); cout << "鏈表長度為:" << head.getLength() << endl; head.remove(1004); head.print(); return 0; }