前言:每週儘量寫一篇博客,貴在堅持,同時也是一次很好的複習和鞏固;本篇博客主要總結線性表的鏈式存儲結構,在理解概念的同時我參照CSDN論壇大佬的程序寫了“自己”的第一個單鏈表,實踐一遍真的會搞懂蠻多的細節,下面開始正文(筆記來源小甲魚視頻):
一、線性鏈表的特點和邏輯結構
1、特點:考慮到順序表插入和刪除操作需要移動大量的元素,線性鏈表可以不連續存儲,原本由數組相對存儲空間所規定的兩個元素的關係,現在由鏈表的指針所代替,理解這裏指針所起的關鍵作用至關重要。
2、邏輯結構
如上圖,一個鏈表由不必在內存中相連的結構構成;每一個結構包含表元素和指向該元素後繼結構的指針。該指針被稱爲Next指針,最後一個Next指針指向NULL;
該結構叫做結點(Node):由數據域和指針域構成
- 數據域:存儲數據元素信息的域;
- 指針域:存儲後繼位置的域;
3、頭節點和頭指針
如圖,L指向的結點即爲頭結點,L即爲頭指針:
- 頭指針是鏈表指向第一個結點的指針;
- 頭指針具有標識作用;(常用頭指針來命名鏈表)
- 無論鏈表是否爲空,頭指針均不爲空;
- 頭指針是鏈表的必要元素;
頭節點:
- 爲了操作的統一和方便設立,放在第一個元素的結點之前,數據域無意義;
- 有了頭節點,對在第一個元素結點前插入結點和刪除第一個結點,其操作就統一了;
- 頭結點不一定是鏈表要求;
- 其數據域一般存儲鏈表的長度N;
二、線性鏈表的常見操作
1、線性鏈表用結構指針描述
typedef int ElemType;
//定義結點類型
typedef struct Node
{
ElemType data; //單鏈表中的數據域
struct Node *next; //單鏈表的指針域
}Node,*LinkedList;
2、單鏈表的初始化
//1、單鏈表的初始化
LinkedList Init_Linklist()
{
Node *L;
L = (Node *)malloc(sizeof(Node)); //申請結點空間
if(L == NULL) //判斷是否有足夠的內存空間
printf("申請內存空間失敗\n");
L->next = NULL; //將next設置爲NULL,初始長度爲0的單鏈表
}
2、單鏈表的建立,包含頭插法和尾插法
//2、單鏈表的建立,頭插法建立單鏈表
LinkedList Create_head_Linklist()
{
Node *L;
L = (Node *)malloc(sizeof(Node)); //申請頭結點空間
L->next = NULL; //初始化一個空鏈表
ElemType x; //x爲鏈表數據域中的數據
while(scanf("%d",&x))
{
if(x == 0)
break; //設置0爲中止符
Node *p;
p = (Node *)malloc(sizeof(Node)); //申請新的結點
p->data = x; //結點數據域賦值
p->next = L->next; //將結點插入到表頭
L->next = p;
}
return L;
}
//3、單鏈表的建立,尾插法建立單鏈表
LinkedList Create_tail_Linklist()
{
Node *L;
L = (Node *)malloc(sizeof(Node)); //申請頭結點空間
L->next = NULL; //初始化一個空鏈表
Node *r;
r = L; //r始終指向終端結點,開始時指向頭結點
ElemType x; //x爲鏈表數據域中的數據
while(scanf("%d",&x))
{
if(x == 0)
break;
Node *p;
p = (Node *)malloc(sizeof(Node)); //申請新的結點
p->data = x; //結點數據域賦值
r->next = p; //將結點插入到表尾
r = p;
}
r->next = NULL;
return L;
}
3、單鏈表的插入,在鏈表的第i個位置插入x的元素
關鍵操作:
p->next = pre->next;//把pre所指向的傳遞給p
pre->next = p;//把指向p的指針給pre,即pre現在指向了新結點p
LinkedList Insert_Linklist(LinkedList L,int i,ElemType x)
{
Node *pre; //pre爲前驅結點
pre = L;
int temp = 0;
for (temp = 1; tempi < i; temp++)
pre = pre->next; //查找第i個位置的前驅結點
Node *p; //插入的結點爲p
p = (Node *)malloc(sizeof(Node));
p->data = x;
p->next = pre->next;
pre->next = p;
return L;
}
4、單鏈表的刪除,在鏈表中刪除值爲x的元素
關鍵操作:
pre-next = p->next;//即pre->next = pre->next->next;逃過了pre-next,x相當於刪除了
LinkedList Delete_Linklist(LinkedList L,ElemType x)
{
Node *p,*pre; //pre爲前驅結點,p爲查找的結點。
p = L->next;
while(p->data != x) //查找值爲x的元素
{
pre = p;
p = p->next;
}
pre->next = p->next; //刪除操作,將其前驅next指向其後繼。
free(p);
return L;
}
5、整表刪除
/*單鏈表的整表刪除*/
Clear_LinkList(LinkedList *L)
{
Node *p, *pre; //pre爲前驅,p爲中轉
pre = L->next;
while(pre)
{
p = pre->next;
free(pre);
pre = p;
}
L->next =NULL;
return L;
}
抓住主要矛盾,搞清楚指針的操作原理是理解的關鍵;