链表知识1:
数组的特点:
空间连续,方便访问,只要知道首元素地址,就可以访问每个元素
数组的缺点:
需要提前分配固定大小的空间,一旦分配大小就不能改变 ,空间分配小了不够用,空间分配大了浪费空间
链表的概念:
由一个一个的结点组成,可以通过第一个节点就能访问所有节点(节点存储的是数据信息)每个节点是动态分配的,但是动态分配的空间不连续,通过一些方式来将每个节点连接起来就构成了链表
链表的节点:
节点空间是不连续,每个节点都存储下一个节点的地址要求每个节点可以存地址,还存需要存的数据,所以节点的类型一定是结构体类型
节点结构体:
至少要包含两个部分,一部分用于存储下一个节点的数据,一个用于存储下一个节点的地址。
定义一个节点数据结构体:
typedef struct List Node_t;
struct List
{
/*数据区域有两个变量*/
int a;
float b;
/*地址区域有一个指针*/
Node_t *pNext;
};
这里容易犯一个错误,有挂结构体的嵌套可以参阅这篇博客。
结构体的嵌套问题 - 任智康 - 博客园 (cnblogs.com)
定义3个节点变量:
Node_t Head_Node; //表头变量
Node_t Body_Node; //表身变量
Node_t Tail_Node; //表尾变量
给每个节点变量赋值:
模拟链表操作把每个节点串联起来
Head_Node.a = 1;
Head_Node.b = 1.0;
Head_Node.pNext = &Body_Node; //头节点下一节点地址
Body_Node.a = 2;
Body_Node.b = 2.0;
Body_Node.pNext = &Tail_Node;//身体节点下一节点地址
Tail_Node.a = 3;
Tail_Node.b = 3.0;
Tail_Node.pNext =NULL;//尾节点后面没有节点 地址赋值NULL
通过给每个节点的数据赋值、然后把每个节点的地址指针赋值成下一节点的地址;最后一个节点的地址域赋值成空指针;
模拟链表操作访问每个节点:
Node_t *pTemp = &Head_Node;
while(pTemp != NULL)
{
Node_Count++;
printf("节点 %d 的信息:\r\n",Node_Count);
printf(" int %d\r\n float %f\r\n Node_t* %p\r\n",pTemp->a,pTemp->b,pTemp->pNext);
pTemp = pTemp->pNext;
}
节点信息如下:
如何插入1个节点:
用malloc函数开辟一段空间 把这个节点信息进行填充 根据添加的位置把他的
//插入一个节点插入到身体节点之后 尾巴节点之前
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; //把当前节点的地址给身体节点的下一节点 (插入到身体节点之后)
插入1个新的节点后的信息:
printf("\r\n===============第2次链表信息===============\r\n");
pTemp = &Head_Node;
while(pTemp != NULL)
{
Node_Count++;
printf("节点 %d 的信息:\r\n",Node_Count);
printf(" int %d\r\n float %f\r\n Node_t* %p\r\n",pTemp->a,pTemp->b,pTemp->pNext);
pTemp = pTemp->pNext;
}
Node_Count = 0;
printf("\r\n===============第2次链表信息===============\r\n");
如何把刚才插入的1个节点删除:
把身体节点的下一个节点地址改成尾部节点,并且把开辟的空间给释放掉
Body_Node.pNext = &Tail_Node;
free(qTemp);
删除掉这个节点后代码及运行效果
===============第1次链表信息===============
节点 1 的信息:
int 1
float 1.000000
Node_t* 00007FF62E50D920
节点 2 的信息:
int 2
float 2.000000
Node_t* 00007FF62E50D8F0
节点 3 的信息:
int 3
float 3.000000
Node_t* 0000000000000000
===============第1次链表信息===============
第一次是三个节点
===============第2次链表信息===============
节点 1 的信息:
int 1
float 1.000000
Node_t* 00007FF62E50D920
节点 2 的信息:
int 2
float 2.000000
Node_t* 000001DCA6B3F540
节点 3 的信息:
int 4
float 4.000000
Node_t* 00007FF62E50D8F0
节点 4 的信息:
int 3
float 3.000000
Node_t* 0000000000000000
===============第2次链表信息===============
第二次是四个节点(添加了一个)
===============第3次链表信息===============
节点 1 的信息:
int 1
float 1.000000
Node_t* 00007FF62E50D920
节点 2 的信息:
int 2
float 2.000000
Node_t* 00007FF62E50D8F0
节点 3 的信息:
int 3
float 3.000000
Node_t* 0000000000000000
===============第3次链表信息===============
第三次是三个节点(添加的节点又被删除了)
完整代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct List Node_t;
struct List
{
/*数据区域有两个变量*/
int a;
float b;
/*地址区域有一个指针*/
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; //头节点下一节点地址
Body_Node.a = 2;
Body_Node.b = 2.0;
Body_Node.pNext = &Tail_Node;//身体节点下一节点地址
Tail_Node.a = 3;
Tail_Node.b = 3.0;
Tail_Node.pNext = NULL;//尾节点后面没有节点 地址赋值NULL
printf("\r\n===============第1次链表信息===============\r\n");
Node_t* pTemp = &Head_Node;
while (pTemp != NULL)
{
Node_Count++;
printf("节点 %d 的信息:\r\n", Node_Count);
printf(" int %d\r\n float %f\r\n Node_t* %p\r\n", pTemp->a, pTemp->b, pTemp->pNext);
pTemp = pTemp->pNext;
}
Node_Count = 0;
printf("\r\n===============第1次链表信息===============\r\n");
//插入1个节点插入到身体节点之后 尾巴节点之前
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("\r\n===============第2次链表信息===============\r\n");
pTemp = &Head_Node;
while (pTemp != NULL)
{
Node_Count++;
printf("节点 %d 的信息:\r\n", Node_Count);
printf(" int %d\r\n float %f\r\n Node_t* %p\r\n", pTemp->a, pTemp->b, pTemp->pNext);
pTemp = pTemp->pNext;
}
Node_Count = 0;
printf("\r\n===============第2次链表信息===============\r\n");
Body_Node.pNext = &Tail_Node;
free(qTemp);
printf("\r\n===============第3次链表信息===============\r\n");
pTemp = &Head_Node;
while (pTemp != NULL)
{
Node_Count++;
printf("节点 %d 的信息:\r\n", Node_Count);
printf(" int %d\r\n float %f\r\n Node_t* %p\r\n", pTemp->a, pTemp->b, pTemp->pNext);
pTemp = pTemp->pNext;
}
Node_Count = 0;
printf("\r\n===============第3次链表信息===============\r\n");
return 0;
}
while (pTemp != NULL)
{
Node_Count++;
printf("节点 %d 的信息:\r\n", Node_Count);
printf(" int %d\r\n float %f\r\n Node_t* %p\r\n", pTemp->a, pTemp->b, pTemp->pNext);
pTemp = pTemp->pNext;
}
Node_Count = 0;
printf("\r\n===============第3次链表信息===============\r\n");
return 0;
}