鏈表知識1:
數(shù)組的特點(diǎn):
空間連續(xù),方便訪問,只要知道首元素地址,就可以訪問每個(gè)元素
數(shù)組的缺點(diǎn):
需要提前分配固定大小的空間,一旦分配大小就不能改變 ,空間分配小了不夠用,空間分配大了浪費(fèi)空間
鏈表的概念:
由一個(gè)一個(gè)的結(jié)點(diǎn)組成,可以通過第一個(gè)節(jié)點(diǎn)就能訪問所有節(jié)點(diǎn)(節(jié)點(diǎn)存儲的是數(shù)據(jù)信息)每個(gè)節(jié)點(diǎn)是動(dòng)態(tài)分配的,但是動(dòng)態(tài)分配的空間不連續(xù),通過一些方式來將每個(gè)節(jié)點(diǎn)連接起來就構(gòu)成了鏈表
鏈表的節(jié)點(diǎn):
節(jié)點(diǎn)空間是不連續(xù),每個(gè)節(jié)點(diǎn)都存儲下一個(gè)節(jié)點(diǎn)的地址要求每個(gè)節(jié)點(diǎn)可以存地址,還可以存需要存的數(shù)據(jù),所以節(jié)點(diǎn)的類型一定是結(jié)構(gòu)體類型
節(jié)點(diǎn)結(jié)構(gòu)體:
至少要包含兩個(gè)部分,一部分用于存儲下一個(gè)節(jié)點(diǎn)的數(shù)據(jù),一個(gè)用于存儲下一個(gè)節(jié)點(diǎn)的地址。
定義一個(gè)節(jié)點(diǎn)數(shù)據(jù)結(jié)構(gòu)體:
typedefstruct List Node_t;
struct List
{
/*數(shù)據(jù)區(qū)域有兩個(gè)變量*/
int a;
float b;
/*地址區(qū)域有一個(gè)指針*/
Node_t *pNext;
};
這里容易犯一個(gè)錯(cuò)誤,有掛結(jié)構(gòu)體的嵌套可以參閱這篇博客。
結(jié)構(gòu)體的嵌套問題 - 任智康 - 博客園 (cnblogs.com)
定義3個(gè)節(jié)點(diǎn)變量:
Node_t Head_Node; //表頭變量
Node_t Body_Node; //表身變量
Node_t Tail_Node; //表尾變量
給每個(gè)節(jié)點(diǎn)變量賦值:
模擬鏈表操作把每個(gè)節(jié)點(diǎn)串聯(lián)起來
Head_Node.a = 1;
Head_Node.b = 1.0;
Head_Node.pNext = &Body_Node; //頭節(jié)點(diǎn)下一節(jié)點(diǎn)地址
Body_Node.a = 2;
Body_Node.b = 2.0;
Body_Node.pNext = &Tail_Node;//身體節(jié)點(diǎn)下一節(jié)點(diǎn)地址
Tail_Node.a = 3;
Tail_Node.b = 3.0;
Tail_Node.pNext =NULL;//尾節(jié)點(diǎn)后面沒有節(jié)點(diǎn) 地址賦值NULL
通過給每個(gè)節(jié)點(diǎn)的數(shù)據(jù)賦值、然后把每個(gè)節(jié)點(diǎn)的地址指針賦值成下一節(jié)點(diǎn)的地址;最后一個(gè)節(jié)點(diǎn)的地址域賦值成空指針;
模擬鏈表操作訪問每個(gè)節(jié)點(diǎn):
Node_t *pTemp = &Head_Node;
while(pTemp != NULL)
{
Node_Count++;
printf("節(jié)點(diǎn) %d 的信息:rn",Node_Count);
printf(" int %drn float %frn Node_t* %prn",pTemp- >a,pTemp- >b,pTemp- >pNext);
pTemp = pTemp- >pNext;
}
節(jié)點(diǎn)信息如下:
如何插入1個(gè)節(jié)點(diǎn):
用malloc函數(shù)開辟一段空間 把這個(gè)節(jié)點(diǎn)信息進(jìn)行填充 根據(jù)添加的位置把他的
//插入一個(gè)節(jié)點(diǎn)插入到身體節(jié)點(diǎn)之后 尾巴節(jié)點(diǎn)之前
qTemp = (Node_t *)malloc(sizeof(Node_t)) ;
qTemp- >a = 4;
qTemp- >b = 4.0;
//qTemp- >pNext = &Tail_Node;
qTemp- >pNext = Body_Node.pNext;//插入的位置是尾巴節(jié)點(diǎn)之前 把尾巴節(jié)點(diǎn)的地址給當(dāng)前節(jié)點(diǎn)
Body_Node.pNext = qTemp; //把當(dāng)前節(jié)點(diǎn)的地址給身體節(jié)點(diǎn)的下一節(jié)點(diǎn) (插入到身體節(jié)點(diǎn)之后)
插入1個(gè)新的節(jié)點(diǎn)后的信息:
printf("rn===============第2次鏈表信息===============rn");
pTemp = &Head_Node;
while(pTemp != NULL)
{
Node_Count++;
printf("節(jié)點(diǎn) %d 的信息:rn",Node_Count);
printf(" int %drn float %frn Node_t* %prn",pTemp- >a,pTemp- >b,pTemp- >pNext);
pTemp = pTemp- >pNext;
}
Node_Count = 0;
printf("rn===============第2次鏈表信息===============rn");
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-DIceA5SJ-1688555989623)(C:Users23206AppDataRoamingTyporatypora-user-imagesimage-20230704205520015.png)]
如何把剛才插入的1個(gè)節(jié)點(diǎn)刪除:
把身體節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)地址改成尾部節(jié)點(diǎn),并且把開辟的空間給釋放掉
Body_Node.pNext = &Tail_Node;
free(qTemp);
刪除掉這個(gè)節(jié)點(diǎn)后代碼及運(yùn)行效果
===============第1次鏈表信息===============
節(jié)點(diǎn) 1 的信息:
int1
float1.000000
Node_t* 00007FF62E50D920
節(jié)點(diǎn) 2 的信息:
int2
float2.000000
Node_t* 00007FF62E50D8F0
節(jié)點(diǎn) 3 的信息:
int3
float3.000000
Node_t* 0000000000000000
===============第1次鏈表信息===============
第一次是三個(gè)節(jié)點(diǎn)
===============第2次鏈表信息===============
節(jié)點(diǎn) 1 的信息:
int1
float1.000000
Node_t* 00007FF62E50D920
節(jié)點(diǎn) 2 的信息:
int2
float2.000000
Node_t* 000001DCA6B3F540
節(jié)點(diǎn) 3 的信息:
int4
float4.000000
Node_t* 00007FF62E50D8F0
節(jié)點(diǎn) 4 的信息:
int3
float3.000000
Node_t* 0000000000000000
===============第2次鏈表信息===============
第二次是四個(gè)節(jié)點(diǎn)(添加了一個(gè))
===============第3次鏈表信息===============
節(jié)點(diǎn) 1 的信息:
int1
float1.000000
Node_t* 00007FF62E50D920
節(jié)點(diǎn) 2 的信息:
int2
float2.000000
Node_t* 00007FF62E50D8F0
節(jié)點(diǎn) 3 的信息:
int3
float3.000000
Node_t* 0000000000000000
===============第3次鏈表信息===============
第三次是三個(gè)節(jié)點(diǎn)(添加的節(jié)點(diǎn)又被刪除了)
完整代碼如下:
#include < stdio.h >
#include < stdlib.h >
typedefstruct List Node_t;
struct List
{
/*數(shù)據(jù)區(qū)域有兩個(gè)變量*/
int a;
float b;
/*地址區(qū)域有一個(gè)指針*/
Node_t* pNext;
};
Node_t Head_Node; //表頭變量
Node_t Body_Node; //表身變量
Node_t Tail_Node; //表尾變量
Node_t* qTemp = NULL;
int Node_Count = 0;
int main(void)
{
Head_Node.a = 1;
Head_Node.b = 1.0;
Head_Node.pNext = &Body_Node; //頭節(jié)點(diǎn)下一節(jié)點(diǎn)地址
Body_Node.a = 2;
Body_Node.b = 2.0;
Body_Node.pNext = &Tail_Node;//身體節(jié)點(diǎn)下一節(jié)點(diǎn)地址
Tail_Node.a = 3;
Tail_Node.b = 3.0;
Tail_Node.pNext = NULL;//尾節(jié)點(diǎn)后面沒有節(jié)點(diǎn) 地址賦值NULL
printf("rn===============第1次鏈表信息===============rn");
Node_t* pTemp = &Head_Node;
while (pTemp != NULL)
{
Node_Count++;
printf("節(jié)點(diǎn) %d 的信息:rn", Node_Count);
printf(" int %drn float %frn Node_t* %prn", pTemp- >a, pTemp- >b, pTemp- >pNext);
pTemp = pTemp- >pNext;
}
Node_Count = 0;
printf("rn===============第1次鏈表信息===============rn");
//插入1個(gè)節(jié)點(diǎn)插入到身體節(jié)點(diǎn)之后 尾巴節(jié)點(diǎn)之前
qTemp = (Node_t*)malloc(sizeof(Node_t));
qTemp- >a = 4;
qTemp- >b = 4.0;
//qTemp- >pNext = &Tail_Node;
qTemp- >pNext = Body_Node.pNext;
Body_Node.pNext = qTemp;
printf("rn===============第2次鏈表信息===============rn");
pTemp = &Head_Node;
while (pTemp != NULL)
{
Node_Count++;
printf("節(jié)點(diǎn) %d 的信息:rn", Node_Count);
printf(" int %drn float %frn Node_t* %prn", pTemp- >a, pTemp- >b, pTemp- >pNext);
pTemp = pTemp- >pNext;
}
Node_Count = 0;
printf("rn===============第2次鏈表信息===============rn");
Body_Node.pNext = &Tail_Node;
free(qTemp);
printf("rn===============第3次鏈表信息===============rn");
pTemp = &Head_Node;
while (pTemp != NULL)
{
Node_Count++;
printf("節(jié)點(diǎn) %d 的信息:rn", Node_Count);
printf(" int %drn float %frn Node_t* %prn", pTemp- >a, pTemp- >b, pTemp- >pNext);
pTemp = pTemp- >pNext;
}
Node_Count = 0;
printf("rn===============第3次鏈表信息===============rn");
return0;
}
while (pTemp != NULL)
{
Node_Count++;
printf("節(jié)點(diǎn) %d 的信息:rn", Node_Count);
printf(" int %drn float %frn Node_t* %prn", pTemp- >a, pTemp- >b, pTemp- >pNext);
pTemp = pTemp- >pNext;
}
Node_Count = 0;
printf("rn===============第3次鏈表信息===============rn");
return0;
}
評論