链表
知识点摘于b站教程视频: https://www.bilibili.com/video/av16869217?from=search&seid=12191125613016121321
b站教程视频有些繁琐。。。只看这篇文章链表入门应该可以理解接受
1.链表是存在于堆内存,存放在不连续的存储空间,在这些不连续的存储空间使用指针去作为一个索引。
a) 链表的结构体
struct Student{
int num;//学号 数据域
char name[10];//姓名 数据域
struct Student *pnext;//表示这个指针指向下一个节点(即下一个结构体) 指针域
};
p是指针 不断用这个结构体的指针去指向下一个结构体,这就是一个链表。
b)节点是什么?
链表是由节点组成的,上图中每个结构体就是链表的节点。
小tips:
typedef struct Student{
int num;//学号
char name[10];//姓名
struct Student *pnext;//表示这个指针指向下一个节点(即下一个结构体)
}STU;
//c语言中,如果加上了第一句的typedef ,STU就是一种数据类型(相当于struct Student、
)若没有加typedef ,STU只是一个变量
//在c++中 ,Student可以直接作为数据类型。
2.两种链表
3.动态内存的使用(链表)
STU *pStu=NULL; //相当于struct Student *pStu
pStu =(STU*)malloc(sizeof(STU)); //就是开辟一个节点
free(pStu);
4.创建链表头结点:
STU* CreateList()
{
STU *P=(STU*)malloc(sizeof(STU));
P->pnext=NULL; //头结点指向为空 (此时还不知道头结点的下一个指向谁) 为保证安全性,赋值为空
return P;
//不需要给num和name赋值,因为是头结点。
}
5.添加节点(按输入顺序添加节点)
添加一个节点
#include<stdio.h>
#include<stdlib.h>
typedef struct Student{
int num;//学号
char name[10];//姓名
struct Student *pnext;//表示这个指针指向下一个节点(即下一个结构体)
}STU;
//创建链表的头结点
STU* CreateList()
{
STU *P=(STU*)malloc(sizeof(STU));
P->pnext=NULL;
return P;
}
//添加节点
void addNode(STU *P )
{
STU *pNew=NULL;//重新定义一个指针
pNew=(STU*)malloc(sizeof(STU));//为新的指针开辟一块内存
printf("请输入学号:");
scanf("%d",&pNew->num);
printf("请输入姓名:");
scanf("%s",pNew->name);
pNew->pnext=NULL;//为了安全,把指针指向定为空
P->pnext=pNew;//连接起来
}
int main(){
STU* pStu = NULL;//定义一个指针,接受链表的首地址
pStu=CreateList();//头结点
addNode(pStu);//添加一个节点 只添加了一个
printf("%d\t%s\n",pStu->pnext->num,pStu->pnext->name);//打印添加的节点
return 0;
}
添加n个节点(人为控制添加的数量)
这个是初始状态,形参指针P指向头结点。
创建临时变量pNew,赋值后,此时令pNew=P->pNext,完成结点之间的连接
再令P指向新的节点
再往下举一个例子。
在for循环内创建一个新的pNew
给pNew赋值后,此时P指向第二个结点,令此时的pNew=P->pNext,完成结点之间的链接。
再令P指向新创建的节点。往后以此类推,形成链表。
实现代码如下:
其中,addNode不一定非要输入n个,可以自己添加限制条件,例如num==0时结束输入
1 #include<stdio.h>
2 #include<stdlib.h>
3
4 typedef struct Student
5 {
6 int num;//学号
7 char name[10];//姓名
8 struct Student *pnext;//表示这个指针指向下一个节点(即下一个结构体)
9 } STU;
10
11 //创建链表的头结点
12 STU* CreateList()
13 {
14 STU *P=(STU*)malloc(sizeof(STU));
15 P->pnext=NULL;
16 return P;
17 }
18
19 //添加节点 人为控制添加的个数
20 void addNode(STU *P )
21 {
22 STU * pNew=NULL;
23 int n;//当前要加入的节点的数量
24 scanf("%d",&n);
25 for(int i=0; i<n; i++)
26 {
27 pNew=(STU*)malloc(sizeof(STU));
28 printf("请输入学号:");
29 scanf("%d",&pNew->num);
30 printf("请输入姓名:");
31 scanf("%s",pNew->name);
32 pNew->pnext=NULL;//尾节点设置为空 这个非常重要
33
34 P->pnext=pNew;//连接起来
35 P=P->pnext;
36 }
37 }
38
39 int main()
40 {
41 STU* pStu = NULL;//定义一个指针,接受链表的首地址
42 pStu=CreateList();//头结点
43
44 addNode(pStu);//添加n个节点
45
46 printf("%d\t%s\n",pStu->pnext->num,pStu->pnext->name);//打印第二个节点的内容
47
48
49 return 0;
50 }
6.遍历 打印出所有的信息
代码如下:
1 void PrintAll(STU *P)
2 {
3 P=P->pnext;//P指向第一个有数据的节点
4 while(P!=NULL)
5 {
6 printf("%d\t%s\n",P->num,P->name);
7 P=P->pnext;
8 }
9 }
下面讲,按输入顺序的逆序插入节点(即从中间插入节点)
这里头结点用head代替比较明显,前面头结点用的是pStu,但是懒得重新再画图了。。。。
创建新节点pNew
第一步
再进行一步相同的操作。
由于head->pnext指向先创建的pNew,那么令第二次创建的pNew->pnext=head->pnext,而head->pnext又指向先创建的pNew,于是先创建的pNew和后创建的pNew就连接起来了。
然后令head->pnext=pNew,指向后创建的pNew。
那么这三个就形成了如下的链表:
练习题见随笔---链表简单练习题2
来源:oschina
链接:https://my.oschina.net/u/4330950/blog/3426361