- 链表的概念
通俗来讲,链表就是将动态申请的结构体类型相同的数据结构连接成类似一个表的形式,由于动态申请的内存是系统随机分配的,为了能够找到这些结构体,因此结构体中除了必要的数据外,还有一个结构体类型的指针用来保存下一个结构体的地址。链表的基本原理如图所示。
指针next用来保存下一个结构体的地址,这样只要知道一个结构体的地址,就可以通过指针来找到其他的结构体。
- 链表的定义
以学生的姓名学号为例,定义一个结构体,在结构体中加入指向地址的指针,因为指针指向的是下一个结构体,因此,指针的类型必须是结构体。
实际就是一个结构体的定义,接下来对结构体成员进行赋值。
再给字符数组赋值时不能直接使用“=”,指针指向的内存不能改写,只能使用strcpy进行赋值。将结构体指针指向NULL,就得到了一个只有一个结构体的链表。可以打印输出链表的内容。
- 链表的遍历输出
当链表中不只有一个结构体时,只需要知道其中的一个地址,就可以访问整个链表。
p.next保存p1的地址,p1.next保存p2的地址。访问时p->next指向p1,p->next->next就可以指向p2。但是重复出现的next显然不符合使用的习惯,循环就可以解决这个问题。
将循环的过程封装成函数,方便以后调用。
- 链表的创建
创建链表首先就需要申请动态内存,因为创建的链表有很多,动态内存的申请可以放进for循环中解决。链表的创建从第一个节点开始依次创建,然而顺序创建比较困难,因为头节点只能找到下一个节点,因此,我们可以让每一次新创建的节点成为头节点,这样就可以完成链表的创建。
STU *link_insert(STU *head,STU *pnew)
{
if (head==NULL)
{
head = pnew;
pnew->next=NULL;
}
else if (pnew != NULL)
{
pnew->next= head;
head = pnew;
}
return head;
}
- 链表的释放
释放链表同样需要一个一个释放,因为链表中的指针保存了下一个节点的地址,因此在释放之前需要找一个中间变量先保存将要释放的节点保存起来。
STU *link_free(STU *head){
STU *ps;
ps=head;
while(head!=NULL)
{
ps = head->next;
free(head);
head=ps;
}
}
- 链表的查询
查询就是将整个链表遍历,从而找到符合条件的输出。
STU *link_find(STU *head)
{
char name[10];
scanf("%s",name);
while(head!=NULL)
{
if (strcmp(head->name,name)==0 )
break;
head = head->next;
}
return head;
}
- 链表节点的删除
删除一个链表的节点首先应该考虑的问题是删除后还是一个链表,只是少了这一个节点,其次,删除节点必须要先找到节点,因此可以在查询的基础上加上删除的逻辑。以三节点链表为例,假设要删除中间节点 ,因为节点中的指针保存着下一个节点的地址,所以找一个中间变量来保存头节点。
要删除中间的节点,先要建立第一个和第三个节点的关系。然后释放掉第二个节点
但是要删除头节点就又出了问题,因为单向链表只能找到下一个节点,并不能找到他的上一个节点,其实只需要删除的时候去判断一下,如果是头节点,直接去释放就好了,另外,因为函数返回值是head,因此,有必要找一个其他变量来代替头节点所以完整的删除代码如下。
STU *link_delete(STU *head,char name[])
{
STU *pf,*ps;
pf = head;
ps = head;
while(head!=NULL)
{
if (strcmp(head->name,name)==0)
{
if (pf==head)
head = head->next;
else
ps->next=pf->next;
free(pf);
break;
}
ps = pf;
pf = pf->next;
}
return head;
}
当然可以在主函数中使用死循环来测试节点的删除,看是否存在有漏洞。
本文参考b站视频所写,视频地址:Java视频教程-Java视频资源-海量下载-千锋教育