本篇仅谈谈,线性表中基础的两个表(链表、顺序表),且以画图为主,叙述为辅。
目录
(1)顺序表实现
①什么是顺序表?
顺序表是用一段 物理地址 连续的存储单元 依次存储数据元素 的 线性结构 ,一般情况下采用数组存
储。在数组上完成数据的增删查改。
②顺序表的分类:
1. 静态顺序表:使用定长数组存储。
2. 动态顺序表:使用动态开辟的数组存储。
静态表:
动态表:
③ 为什么更多时候用的是动态的顺序表?
1.静态表的数组容量往往是 固定的,难以适应环境需求的变化。容易造成 空间开多了浪费,开少了不够用 。
2.因此,动态表的优势就在于,申请多少用多少,有效的解决资源浪费或不够的困境。
④顺序表如何实现?
函数功能:打印出一个顺序表的三角形:
malloc与realloc进行动态空间的申请开辟:
注:realloc只需要得到 想要开辟空间的指向即可
结果:
(2)链表
链表是什么?
链表是一种线性表,线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。
概念:概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
①为什么会存在链表?
时间:顺序表不管是,增删查改,它的时间复杂度都为O(n)
空间:增容只能有个大概的内容扩充,仍然不能解决容量>使用量。
②链表形式:
实际中要实现的链表的结构非常多样,以下情况组合起来就有8种链表结构:
这里我们要使用到单链表和双向链表:
③链表如何实现?
效果:三角形的链表插入和删除形状。
单链表(带头):
创建链表内容:
图示标记处:增加和删除
什么是头插?
注:要让newnode指向下一个节点,则可以通过头节点找到那个节点。(phead->next)
什么尾插?
相较于头插,尾插要多一步:找到要插入的地方:
通过另定义指针,来查询要尾插的最后一个节点:
什么是头删?
如图所示:仅仅需要让上一个节点跳过,要删除的节点,并指向下下个节点。
什么是尾删?
同尾增一样,尾删也需要找到要删除的位置。
因为牵涉到要把删除节点的前一个next置位空,但链表为单向,无法找到上一个节点,因此要借助prev,把上一个next置位NULL。
效果:头插头删。
效果:尾插尾删。
双向链表带头:
效果:进行链表的增删查改。
注:头节点(哨兵位) 一定不用来存储有效数据。
且,定义初,哨兵位的几个指针最好指向自己~。
顾名思义:该链表 指向上一个链表的指针,也有指向下一个链表的指针
附:进行增删查改的时候,尽量形成三个指针的关系,而不用在意链接顺序的先后问题!!
头增与尾增:
头增:
尾增:
尾插的时候,也就比单向链表所用的时间要少。因为可以用前指针 指向最后一个尾节点。
这有一个疑问,如果没有节点的时候?
如图,尾增的时候,就是因为初始化哨兵位的时候,把前驱指针,后指指针指向了自己,因此结构上得到了一定的优化。 头插部分也是这样,不用在给以图示。
头删与尾删:
头删:
头删的处理有两种做法,对于新手而言,最好用双指针,因为不用考虑先后的问题。
尾删:
同样,如果链表没有节点呢?
这样会连带哨兵位一起“干掉”,这是我们不想要的。
因此会断言(assert),删除的前提是:
效果
头增与头删:
尾插与尾删:
总结:
①两表:顺序表、链表
②链表的创建,最好有头节点(哨兵位)
别的也就没啦。