认识链表
·链表是可以动态地按需进行存储分配的一种结构。
·与数组相比较链表更加灵活,数组需要事先定义固定长度,而链表不需要。
·链表由数据域和指针域组成。数据域用来存放所需要的数据,指针域用来存放下一个结点的位置(地址)。
例子:创建一个关于学生信息的结构体,把此结构体当作链表的结点。
struct student
{
char name[10];//姓名
int weight;//体重
int height;//身高
int sex;//性别
struct student* next;//用于存放下一结点的地址
};
形象点说就是每个结点都是一个岛屿,而你想去到下个岛屿时你得先知道下一个岛屿的位置。数据域是岛上的内容,指针域是岛上的路标,告诉你下一个岛屿的位置。
创建单向链表
单向链表的结构:
·头指针是链表的入口。
·每个结点通过其本身的指针访问下一个结点,因为其本身的指针存放着下一个结点的地址。
·头指针可不存放信息只记录下一结点地址。
·罗列一下我们要怎么创建一个链表。
- 为每个结点分配内存空间,创建一个结点。
- 记录链表的入口。
- 连接前后两个结点。
- 创建链表模块化
详细操作与解释如下:
struct student 这是链表结点的样子
{
char name[10];//姓名
int weight;//体重
int height;//身高
int sex;//性别
struct student* next;//用于存放下一结点的地址
};
struct student* creatstu() 创建链表的函数
{
struct student* head=NULL;//用来记录链表入口,创建完成后返回此指针
struct student* p1;//用来创建新结点
struct student* p2;//记录p1前一个结点
int n = 0;//记录是否需要把结点地址赋予头指针
p1 = p2 = (struct student*)malloc(sizeof(struct student));//为结点分配内存
scanf("%s %d %d %d", p1->name,&p1->height, &p1->weight, &p1->sex);
while (p1->height != 0)//停止创建的条件可自行调整
{
n++;
if (n == 1)head = p1;//如果是第一个结点,他的地址要给到头指针
else p2->next = p1;//如果不是便让p2得到p1结点的位置并连接,这样p1这个指针可以继续开辟新结点
p2 = p1;//p2每次都走到p1结点,p1结点此时为最后结点
p1= (struct student*)malloc(sizeof(struct student));//分配一个新的内存空间给p1,开创新结点
scanf("%s %d %d %d",p1->name, &p1->height, &p1->weight, &p1->sex);
}
p2->next=NULL;//循环结束说明输入结束,此时p2为最后一个结点
return head;//返回头指针
}
链表创建完成后返回头指针给调用该函数的函数,此时便可以通过访问头指针来访问整个链表。
·寻找时与数组的区别:链表的时间复杂度为O(n)(通过指针寻址一个一个寻找),数组为O(1)(知道下标直接访问)。
链表的增删改查
- 增
如何往已经创建好的链表中继续加入结点呢?有两种方法:头插法和尾插法。
struct student* stu()//创建学生结点
{
struct student* p;
p = (struct student*)malloc(sizeof(struct student));
p->next = NULL;
return p;
}
头插法:使头指针指向新结点,新结点的指针指向原本第一个结点。
struct student* newstu=stu();//得到该新结点的地址
newstu->next=head->next;//先把新结点与原本的第一个结点连接
head->next=newstu;//再把头指针与新结点连接
为什么不能调转顺序?因为调转后无法连接原来的旧结点
尾插法:找到最后一个结点并连接
struct student* newstu=stu();//得到该新结点的地址
struct student* search=head;//设置一个用于搜索的指针
while(search->next!=NULL)search=search->next;//遍历链表,当其退出循环时便找到了最后一个
search->next-newstu;//连接两个结点
- 删
删除一个结点要先找到该节点,然后连接前后两个结点。
struct student* search=head,follow=head;//设置一个用于搜索的指针
while(search!=`````)//自行定义需删除结点的信息
{
follow=search;//记录当前位置
search=search->next;//寻找新位置
}
找到后:
follow->next=search->next;//连接两个结点
free(search)//释放该内存空间
- 改
同样设置一个用于搜索的指针,找到需要修改的信息即可。 - 查
设置用于搜索的指针进行遍历便可。
//只做一个粗略的介绍,具体的边界情况请自行讨论