数据结构学习笔记——单链表

文章详细介绍了realloc函数的两种扩容方式,强调原地扩容的低代价和异地扩容的高代价。顺序表因其空间连续性而便于访问,而链表虽然不连续但灵活。在链表操作中,如尾插、头插、删除等,文章讨论了指针传递和内存管理的问题,特别指出尾删时需避免产生野指针。同时,文章提到了栈和堆的区别,并讨论了单链表的局限性和插入删除操作的注意事项,包括内存释放和防止内存泄漏的方法。
摘要由CSDN通过智能技术生成

realloc有两种方式,第一种是原地扩容,第二种方式是异地扩容。

要括的时候看后面的空间够不够,够就原地括,这样返回的指针还是原来的指针

如果后面没有足够的空间,会去其他地方找更大的内存,然后再拷贝数据下来,然后释放旧空间,返回新空间地址

注意:原地括代价低(不需要拷贝数组什么的),异地括代价高

顺序表好处:连续的空间只需要知道第一个位置的地址,有顺序,就可以访问所有的数据

链表(物理上不是连续的):有一个指针找到第一个(这种存一个数据的叫节点),第一个节点和第二个节点通过一个指针链接起来,第一个存第二个的地址,到最后存NULL

代价:不连续的话,每存一个数据就要伴随一个指针去把后面存数据的内存块(节点)链接起来。不支持随机访问。

箭头是想象出来的,用形象的方式来表示

如果phead里面存的是空,空指针不能解引用,解引用程序就会出问题

反正都要尾插,我们先开空间,把节点搞出来,然后看phead为不为空,如果为空说明链表里一个节点都没有,那就不找尾,直接让phead指向新节点地址

节点给了phead,plist没有改变

虽然这是传指针,phead是一块空间,把plist的值拷贝给phead,phead的改变就不会影响plist

要改变int就要传int*,要改变int*也要传递int*的地址int**

传一级指针地址用二级指针接收,链表就可以插入数据了。尾插要改变实参所以传地址

打印不传是因为不需要改变实参就不传地址了

总结:想通过指针去改变指向空间的内容,传一级指针,想改变指针的指向,传二级指针

也可以不传二级指针传一级指针,但要使用返回值接收,这样我们就不需要改变plist中存的地址,而是拷贝plist中的地址存放到新开辟的指针中,最后返回开辟的指针

头插

栈比堆小,栈一般只有8M,大概八百多万字节,32位下堆一般有2G

1M=1024KB=1024*1024Byte

头删、尾删都要传二级指针。尾删平时不需要用二级指针,但删到最后还是需要的。把节点删完了,要把plist中存的地址置成空指针

这里的尾删是存在问题的。tail只是这个函数里的局部变量

tail原来是指向最后的,tail=NULL之后:

出了作用域tail也就销毁了。d2后面有一个指针,指向下一个空间的地址。这个指针就是经典的野指针,指针指向非法的空间(比如:被释放了的空间)。所以不仅要释放最后一个节点,还要把最后一个节点的前一个节点中存的地址置空

单链表缺陷:有一个节点可以找下一个节点但找不到它的上一个节点

那就再定义一个指针变量,每次tail往前走之前先赋值给prev。当tail走到尾,prev就是tail的前一个,把prev赋成空。

但删最后一个的时候有问题

以下写法在多个节点的时候是可行的,在删最后一个的时候也存在问题

对空指针解引用,不仅有这个问题plist里面也没置空

所以我们应该分类讨论:

一个节点进if,两个或两个以上节点进else

进行了分类讨论之后,对省一个指针变量的另一种方式也是可行的

想重复查找的话:找到第一个2之后可以从第一个2之后的后一个位置开始找,就不用从头开始了

不仅有找同时也有修改的作用,因为它返回的是下标

如果找第一个节点(pos位置)前一个想插入会发现在pos前找不到

那么判断pos是不是*pphead,是不是第一个节点,是就特殊处理

单链表在pos前插入有点复杂,可以在pos后插,这样就不需要pphead参数,这样实现简单而且效率更高一些。

free之后pos置不置空都可以,pos只是一个形参,pos置空但要删的那个节点不会被置空,因为pos只是一个拷贝,形参的改变不影响实参,所以可以不置空,从好的习惯来说置空了也挺好。

函数进去之后可以看情况加断言。也是一个好习惯,比如打印函数,打印空链表是合理的我们就不加断言。逻辑走代码的时候认为它不可能为空就加断言。

链表不连续,所以不能只free一次,这样会内存泄漏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值