写在单向链表前:注意这段内容务必浏览,确保你能看懂后续
什么是结构体?这一点得清楚。
通俗的讲:结构体是一种自定义的结构类型。即你可以根据自己的需求来创造一个想要的类型。
举个例子:某天,你要做一个存储器,里面存储人的名字、身高、体重;我们知道名字是字符型,身高可以用浮点型,体重可以用整型。那么问题是怎么用一个容器存储这三种类型?
这时候,我们可以自己设计一个类型,这个类型里面可以存储三种类型的数据,这就是结构体。
如果上面的内容还是看不太懂,那么结合以下代码来搞懂什么是结构体吧。
int Weight; //这一行声明了名为Weight的整型变量,Weight可以用来存储整型数据了
float Height; //同理,Height可以用来存储浮点型变量了
char Name[10]; //这里声明了名为Name的字符型数组,Name可以用来存字符型数据了
/*以上三个变量(Weight、Height、Name[10])的类型都不同,只能存储各自对应的数据类型
为此,我们根据需要创造一个结构体类型的变量,来存储这三种类型*/
struct Person{
int W;
float H;
char N[10];
};
/*这一行,struct是一个关键字,告诉计算机你在创造结构体,Person是你给结构体的名字
第一行和最好一行的花括号里,是你自定义结构体的存储类型
花括号中间三行,分别声明了整型、浮点型、字符型变量,意味着结构体可以存这三种类型
*/
实际上,你可以简单认为:先创造一个名为Person的结构体类型(当然名字自定义);
再把这个结构体Person划分成三部分空间,一部分存整型,一部分存浮点型,一部分存字符型
相信你已经搞懂了什么是结构体。然后你再只需要搞懂什么是指针;然后就能轻而易举地搞懂什么是单向链表了。
指针
指针即地址,地址即指针。
为什么地址要叫指针,你可以这样理解:地址是有意义的,地址指向某个确定地点,因为指向,所以叫指针。
如果你还是不太理解什么是指针,那么通过下面代码来理解一下。
int *p;
上面这一行定义了一个指针,“ * ”这个符号称为指针运算符。
对于第一行代码,随着理解加深,会发现
程度浅:根据定义,* 告诉计算机p是指针,即p现在是一个空地址,因为你没有给p传入地址
指针p被规定只能指向整型,我们一般称为整型指针。
程度深:在这里,我们把地址称为指针,把地点称为指针指向的内容;
p是指针,*p表示对指针p进行指针运算,
所以*p表示指针指向的内容,也就是地点
而我们可以看到 int *p
若把*p视为整体,则*p被规定为整型,也即所指内容规定为整型
看到这里,你会发现,和程度浅表述结果是一样的,但是程度深浅只有自行体会。
既然你已经知道了什么是结构体,什么是指针,接下来就是单向链表,当然单向链表的操作这里不介绍,感兴趣可以去看《数据结构》一书。
什么是单向链表?
通俗的讲:结构体1通过指针指向结构体2,再由上一个结构体指向下一个结构体,这一系列单向的东西就叫单向链表。
如果感觉不太明白,我们图片和代码结合一下;
先上图片:
有一点我想要特别说明,那就是概念问题。
什么是头指针?什么是结点?什么是头结点?什么是第一个结点?
这些概念我会逐一说明,先分析上面的图:
我们可以看到这个:;这就是我们之前说的结构体,图中它分两部分空间,一部分空白,该部分一般用来存储数据(没有传入数据);另一部分里面存储了一个指针,它指向下一个结构体。
那么什么是结点,如你所见,这样一个像结点的结构体 称为结点。
图中的指针h是头指针。
头结点一般不用来存数据,它里面只有一个指针。看下图:
多出来的 为头结点,我特意把前一部分画满斜线来表示它不用来存储数据。
如果你碰到题目说带头结点的链表,请你注意,头结点是不存数据的。
一般所言第一个结点,指第一个用来存数据的结点。
头指针一直在头部,指向头结点或第一个结点。即上面两幅图情况。
这里是单向链表代码:
struct PolyNode{
int Data;
PolyNode *p;
};
上面定义了结构体类型,有Data和指针p组成;
注意:p被规定指向PolyNode类型;
我们之前讲了结构体,一些点我再这里补上
点1:PolyNode是自定义的名字,这个名字代表了结构体类型;
点2:PolyNode A表示定义了结构体类型的变量A;
点3:A.Data表示调用A里面的Data变量。
总之,定义了结构体,给了它名字。把这个名字当作新类型处理就行
像整型:我们是int M;
结构体型:我们是PolyNode M;
言归正传
PolyNode A,B,C,D; //定义了ABCD四个结构体型变量。
A.p=&B; //这里我们往A的指针输入B的地址,&是取地址的符号。
B.p=&C; //同理,下面重复操作就不写了。
按照上面代码,我们把A,B,C,D四个结点链接起来了,还应该要让最后一个结点指向NULL,即指向空,也就是什么都不指向。
再加一个头指针,就形成了完整的单向链表,只需调动头指针就可以用它。
动态分配利用malloc函数我就不讲了,感兴趣的可以看一下《C语言程序设计》一书。