鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。 相比於線性表順序結構,操作復雜。由於不必須按順序存儲,鏈表在插入的時候可以達到O(1)的復雜度,比另一種線性表順序表快得多,但是查找一個節點或者訪問特定編號的節點則需要O(n)的時間,而線性表和順序表相應的時間復雜度分別是O(logn)和O(1)。
使用鏈表結構可以克服數組鏈表需要預先知道數據大小的缺點,鏈表結構可以充分利用計算機內存空間,實現靈活的內存動態管理。但是鏈表失去了數組隨機讀取的優點,同時鏈表由於增加了結點的指針域,空間開銷比較大。鏈表最明顯的好處就是,常規數組排列關聯項目的方式可能不同於這些數據項目在記憶體或磁盤上順序,數據的存取往往要在不同的排列順序中轉換。鏈表允許插入和移除表上任意位置上的節點,但是不允許隨機存取。鏈表有很多種不同的類型:單向鏈表,雙向鏈表以及循環鏈表。鏈表可以在多種編程語言中實現。像Lisp和Scheme這樣的語言的內建數據類型中就包含了鏈表的存取和操作。程序語言或面向對象語言,如C,C++和Java依靠易變工具來生成鏈表。

一.聲明鏈表
每個結點包括兩個部分:一個是存儲數據元素的數據域(data),另一個是存儲下一個結點地址的指針域(next)。
typedef struct Node { int data; struct Node *next; } node;
二.初始化鏈表
1.頭插法創建鏈表,頭插法顧名思義就是從把新添加的元素放在鏈表的頭部,例如新添加的S元素作為鏈表的頭節點,放在第一位
node * head_insert(int n){ node *head=(node *)malloc(sizeof(node)); //創建頭節點 head->data=0; head->next=NULL; for (int i = 0; i < n; i++) { node *body=(node *)malloc(sizeof(node)); //創建一個新的節點 body->data=i+1; body->next=head->next; //與尾插法的區別就在這里,新插入元素的next指向head的next head->next=body; } return head; }
///打印的數據為0->5->4->3->2->1->null //新添加的元素最后輸出
2.尾插法,就是常規的操作,新添加的元素放在鏈表的最后
node * tail_insert(int n){ node *head=(node *)malloc(sizeof(node)); //創建頭節點 head->data=0; head->next=NULL; node *p=head; //聲明一個指針指向頭結點,用於遍歷鏈表(這里是單個的節點) for (int i = 0; i < n; i++) { node *body=(node *)malloc(sizeof(node)); body->data=i+1; p->next=body; p=p->next; //指針后移,移動到下一個節點 } return head; //head為整個鏈表 }
///0->1->2->3->4->5->null //新添加的元素在鏈表的尾部
總結:頭插和尾插的根本區別在於頭節點,頭節點不變化的為尾插法,頭節點變動的(變為新插入的節點)為尾插法
三.打印鏈表
void print_list(node *head){ while (head) { printf("%d->",head->data); head=head->next; //后移指針,完成切換 } printf("null\n"); }
四.查找節點
//查找節點 node * find_list(node *head,int x){ while (head&&head->data!=x) { head=head->next; //如果不是最后的節點或節點的值不相等,則指針后移 } if (head) return head; return NULL; }
五.刪除元素
//刪除根據索引位置刪除鏈表的位置 void delete_list(node *head,int i){ int j=0; while (head&&j<i-1) { head=head->next; j++; } //head->next=head->next->next; node *p=(node *)malloc(sizeof(node)); p=head->next; head->next=p->next; free(p); }
六.插入元素
//向鏈表中插入值為n的元素 node * insert_list(node *head,int n,int i){ int j=0; while (head&&j<i-1) { head=head->next; j++; } if (!head) { return NULL; } node *p=(node *)malloc(sizeof(node)); //創建一個新的節點 p->data=n; p->next=head->next; head->next=p; return p; }
整體代碼
#include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node *next; } node; //創建一個頭節點 node * create_list(int x){ node *p=(node *)malloc(sizeof(node)); p->data=x; p->next=NULL; return p; } node * init_list(int n){ node *head=(node *)malloc(sizeof(node)); //創建頭節點 head->data=0; head->next=NULL; node *p=head; //聲明一個指針指向頭結點,用於遍歷鏈表(這里是單個的節點) for (int i = 0; i < n; i++) { node *body=(node *)malloc(sizeof(node)); body->data=i+1; p->next=body; p=p->next; //指針后移,移動到下一個節點 } return head; //head為整個鏈表 } //鏈表添加節點 void add_list(node *head,int x){ if(!head)return; while (head->next) { head=head->next; //當指針不為空時,表明不是最后的節點,向后移動 } node *p=(node *)malloc(sizeof(node)); //創建一個新的節點 p->data=x; p->next=NULL; head->next=p; //關聯鏈表 } //查找節點 node * find_list(node *head,int x){ while (head&&head->data!=x) { head=head->next; //如果不是最后的節點或節點的值不相等,則指針后移 } if (head) return head; return NULL; } //打印鏈表的值 void print_list(node *head){ while (head) { printf("%d->",head->data); head=head->next; //后移指針,完成切換 } printf("null\n"); } //向鏈表中插入值為n的元素 node * insert_list(node *head,int n,int i){ int j=0; while (head&&j<i-1) { head=head->next; j++; } if (!head) { return NULL; } node *p=(node *)malloc(sizeof(node)); //創建一個新的節點 p->data=n; p->next=head->next; head->next=p; return p; } //頭插法 node * head_insert(int n){ node *head=(node *)malloc(sizeof(node)); //創建頭節點 head->data=0; head->next=NULL; for (int i = 0; i < n; i++) { node *body=(node *)malloc(sizeof(node)); //創建一個新的節點 body->data=i+1; body->next=head->next; head->next=body; } return head; } //刪除根據索引位置刪除鏈表的位置 void delete_list(node *head,int i){ int j=0; while (head&&j<i-1) { head=head->next; j++; } //head->next=head->next->next; node *p=(node *)malloc(sizeof(node)); p=head->next; head->next=p->next; free(p); } //獲取鏈表中的某一元素 node * get_elem(node *head,int i){ int j=0; while (head&&j<i-1) { head=head->next; j++; } if (j!=i-1) { return NULL; } printf("%d->",head->data); return head; } //刪除鏈表中所有的值為key的節點 void deleteAllKey_list(node *head,int key){ node *p,*q; p=head; q=head->next; while (q!=NULL) { if (q->data==key) { p->next=q->next; free(q); q=p->next; }else { p=p->next; q=q->next; } } } void deleteAllSameKey_list(node *head){ node *p=head->next,*q,*r; while (p!=NULL) { q=p; while (q->next) { if (q->next->data==p->data) { r=q->next; q->next=r->next; free(r); }else { q=q->next; } } p=p->next; } } void main(){ // node *head =create_list(1); // add_list(head,5); // add_list(head,3); // add_list(head,7); // add_list(head,8); // insert_list(head,8,2); // add_list(head,7); // print_list(head); // // deleteAllKey_list(head,7); // deleteAllSameKey_list(head); // print_list(head); node *list=init_list(5); // node *list=head_insert(5); print_list(list); }