【数据结构】单链表——增删查改

链表

链表属于一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,成存储单元的一个 节点

链表分为:有/无头结点的、有/无环的、单/双链表;由此可以排列组合出:无头结点无环的单链表、无头结点有环的单链表、有头结点无环的单链表、有头结点有环的单链表、无头结点无环的双链表、无头结点有环的双链表、有头结点无环的双链表、有头结点有环的双链表 8种链表

本篇主要讨论 无头结点无环的单链表

在这里,head不只是节点,同时也是链表身份的标识。

创建头文件
在此基础上建立函数,

1、需要初始化链表——LinkListInit
需要注意的一点是:这里的要用ListNode** head而不是ListNode* head ,因为如果用后者的话,head是形参,只是实参的拷贝,对外不生效,所以在这里要用二级指针。
2、在链表末尾插入一个节点——LinkListPushBack
思路:
  • 是空链表,则直接使头结点指向该节点就好。
  • 不是空链表,先遍历至尾节点(下一个节点指向NULL的节点),然后在使该节点指向新的节点,新节点指向NULL。

在写尾插函数之前,需要先完成另一个函数
void LinkListCreateNode(LinkType value);
该函数的作用是, 给一个新的值创建新的节点

从图里可以看到,我们选用了malloc而没有用被注释掉的代码来开辟空间,原因是:
malloc出的空间是在堆上的,除了手动free之外,是会一直存在的,但是第二种方法中开辟出的node是在栈上的,出了该函数就会被自动释放,ptr就会变为野指针。

代码:

从上面代码可以发现,在最后并没有使新的节点指向NULL,这是因为在Create函数中,已经使ptr->next=NULL了,所以在尾插函数中,可以不做该操作。

测试,得到如下结果:
由结果可以看出,abcd的地址不连续,这也是链表的特点之一。

测试中,需要用到的一个函数
void LinkListPrint(LinkNode* head, const char *msg);
该函数的作用是 打印函数的功能("%s")、链表中节点的值("%c")和节点的地址("%s"),最后指向NULL
有了这个函数,测试会方便很多,结果也清楚很多。
3、从链表尾部删除一个节点——void LinkListPopBack
思路:
  • 空链表直接返回。
  • 只有一个节点的链表,直接删除头结点。
  • 有两个及两个以上节点的链表,①使倒数第二个指针下一个指向NULL,②将原本的最后一个指针释放,防止内存泄漏。
  • 注意:为了能够释放最后一个节点,需要先把最后的节点保存起来,然后让倒数第二个指针指向NULL,这样才可以释放最后的节点。
画图表示更清晰:

这里也需要写一个函数
void LinkListDestory(LinkNode ptr)){
free(ptr);
}
该函数的功能是删除节点
为什么free(ptr)而不是head,看下图:

代码:

测试结果:
可以看到两个元素以上的链表尾删失败

4、在链表前端插入一个节点——LinkListPushFront
思路:
  • 空链表,直接插入。
  • 非空链表的话,①新建一个指针cur存储新插入的值,②cur->next指向原本的头节点,③头指针指向新的指针cur。

画图解释会更清晰, 假如刚开始是这样的链表,新插入的值为value,新建的指针为cur:

则变为:
代码:

测试结果:

5、在链表前端删除一个节点——LinkListPopFront

思路:
  • 空链表,直接返回。
  • 非空链表,①将头结点存储在新建的指针中(delete),②头指针指向原来头结点的下一个节点,③删除原本的头结点。

画图表示:
代码:
测试结果:
6、在链表前端查找某元素的坐标——LinkListFind

思路:
  • 空链表直接返回。
  • 新建一个指针cur指向头结点,比较cur对应的元素和要寻找的元素value,相同的话就返回cur,不同则cur指向cur->next,直到cur指向NULL。
画图如下:

代码:
细心一点会发现,这里和前面有两点不同:
  1. 用了LinkNode* 而不是void,这是因为找到之后返回值为指针cur。
  2. 定义时用了LinkNode* head而不是LinkNode** head,这是因为本函数只需要找到并返回坐标,不会对头指针做出修改,所以只需要传形参即可。
测试结果:



















  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值