一、鏈表的概念
鏈表是一種物理存儲結構上非連續,非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。
二、鏈表和數組的區別:
1、數組靜態分配內存,鏈表動態分配內存。
2、數組在內存中是連續的,鏈表是不連續的。
3、數組利用下標定位,查找的時間復雜度是O(1),鏈表通過遍歷定位元素,查找的時間復雜度是O(N)。
4、數組插入和刪除需要移動其他元素,時間復雜度是O(N),鏈表的插入或刪除不需要移動其他元素,時間復雜度是O(1)。
數組的優點
1、隨機訪問性比較強,可以通過下標進行快速定位。
2、查找速度快
數組的缺點
1、插入和刪除的效率低,需要移動其他元素。
2、會造成內存的浪費,因為內存是連續的,所以在申請數組的時候就必須規定七內存的大小,如果不合適,就會造成內存的浪費。
3、內存空間要求高,創建一個數組,必須要有足夠的連續內存空間。
4、數組的大小是固定的,在創建數組的時候就已經規定好,不能動態拓展。
鏈表的優點
1、插入和刪除的效率高,只需要改變指針的指向就可以進行插入和刪除。
2、內存利用率高,不會浪費內存,可以使用內存中細小的不連續的空間,只有在需要的時候才去創建空間。大小不固定,拓展很靈活。
鏈表的缺點
查找的效率低,因為鏈表是從第一個節點向后遍歷查找。
單鏈表和雙鏈表
三、鏈表環問題
判斷是否有環
定義一個快指針和一個慢指針,快指針一次走兩步,慢指針一次走兩步,會出現兩種情況,情況一指針走到了空的位置,那就說明這個鏈表不帶環。情況二兩個指針相遇,說明這個鏈表帶環。
獲得入環節點
如果不考慮空間復雜度,可以使用一個map來記錄走過的節點,這個指針一直向后遍歷如果遇到空,說明這個鏈表不帶環,也就沒有入環節點,如果沒有遇到空,如果遇到第一個在map中存在的節點,就說明回到了出發點,這個節點就是環的入口節點。如果不建立額外的空間,先使用快慢指針判斷這個鏈表是否有環,如果有環將相遇節點記錄,然后一個指針從鏈表的起始位置開始一次走一步,另一個指針從記錄的節點開始一次走一步,當兩個節點再次相遇,這個相遇節點就是環的入口節點。
以上轉載自https://blog.csdn.net/Shuffle_Ts/article/details/95055467
四、鏈表的使用
1、鏈表的創建(頭插法、尾插法)
#include<iostream> #include<stdlib.h> using namespace std; struct node { int x; node* next;//指向結構體的一個指針 }; node *Head, *End; void add(int m) { node *temp = (struct node*)malloc(sizeof(struct node));//強制類型轉換+分配地址空間 //節點賦值,m是一個整數型的值,要把它變成結構體類型才能放進鏈表里 temp->x = m; temp->next = NULL; if (Head== NULL)//頭指針為空,說明鏈表為空,那么temp即是頭指針,也是尾指針 { Head = temp; End = temp; } else { //鏈表不為空的情況,讓尾指針指向當前節點,同時尾指針后移,為下一次添加節點准備 End->next = temp; End = temp; //上面的是尾插,即在鏈表尾部加入節點 //如果在鏈表頭部加入節點,讓頭指針指向當前節點,同時頭指針前移就可以 //Head->next=temp; //Head=temp; } } int main() { Head = (struct node*)malloc(sizeof(struct node)); End = (struct node *)malloc(sizeof(struct node)); Head->next = NULL; End = Head; int n, m; cin>>n; for(int i=0;i<n;i++) { cin>>m; add(m); } node *temp = Head; while (temp->next!=NULL)//鏈表的遍歷 { temp = temp->next; cout << temp->x << ' '; } cout<<endl; return 0; }
#include<iostream> #include<stdlib.h> using namespace std; struct node { int x; node* next;//指向結構體的一個指針 }; node *Head, *End; int main() { Head = (struct node*)malloc(sizeof(struct node)); End = (struct node *)malloc(sizeof(struct node)); End = Head; int n, m; cin>>n; for(int i=0;i<n;i++) { cin>>m; node *temp=(struct node*)malloc(sizeof(struct node)); temp->x=m; temp->next=NULL; End->next=temp; End=temp; } node *temp = Head; while (temp->next!=NULL)//鏈表的遍歷 { temp = temp->next; cout << temp->x << ' '; } cout<<endl; return 0; }
2、鏈表的刪除、插入和清空
void clear()//清空鏈表 { node *now=Head; while(now!=NULL) { node *temp=now; now=now->next; free(temp); } Head=NULL; End=NULL; } void insert(int pos,int num)//在第pos個位置增加一個節點 { node *now=Head; for(int i=0;i<pos-1;i++) now=now->next; node *temp=(struct node*)malloc(sizeof(struct node));//創建一個新節點保存數字num temp->x=num; temp->next=now->next; now->next=temp; } void del(int num)//在鏈表中刪除數據域為num的節點 { node *now=Head; while(now->next!=NULL) { node *temp=now;//保存num所在節點的前一個節點 now=now->next; if(now->x==num) { temp->next=now->next; free(now); now=temp; } } }
完整代碼

#include<iostream> #include<stdlib.h> using namespace std; struct node { int x; node* next;//指向結構體的一個指針 }; node *Head, *End; void add(int m) { node *temp = (struct node*)malloc(sizeof(struct node));//強制類型轉換+分配地址空間 //節點賦值,m是一個整數型的值,要把它變成結構體類型才能放進鏈表里 temp->x = m; temp->next = NULL; if (Head== NULL)//頭指針為空,說明鏈表為空,那么temp即是頭指針,也是尾指針 { Head = temp; End = temp; } else { //鏈表不為空的情況,讓尾指針指向當前節點,同時尾指針后移,為下一次添加節點准備 End->next = temp; End = temp; //上面的是尾插,即在鏈表尾部加入節點 //如果在鏈表頭部加入節點,讓頭指針指向當前節點,同時頭指針前移就可以 //Head->next=temp; //Head=temp; } } void clear()//清空鏈表 { node *now=Head; while(now!=NULL) { node *temp=now; now=now->next; free(temp); } Head=NULL; End=NULL; } void insert(int pos,int num)//在第pos個位置增加一個節點 { node *now=Head; for(int i=0;i<pos-1;i++) now=now->next; node *temp=(struct node*)malloc(sizeof(struct node));//創建一個新節點保存數字num temp->x=num; temp->next=now->next; now->next=temp; } void del(int num)//在鏈表中刪除數據域為num的節點 { node *now=Head; while(now->next!=NULL) { node *temp=now;//保存num所在節點的前一個節點 now=now->next; if(now->x==num) { temp->next=now->next; free(now); now=temp; } } } int main() { Head = (struct node*)malloc(sizeof(struct node)); End = (struct node *)malloc(sizeof(struct node)); Head->next = NULL; End = Head; int n, m; cin>>n; for(int i=0;i<n;i++) { cin>>m; add(m); } del(2); del(3); node *temp = Head; while (temp->next!=NULL)//鏈表的遍歷 { temp = temp->next; cout << temp->x << ' '; } cout<<endl; return 0; }