文章目录
学习完链表首先要明确几个点
1.指针
2.内存泄漏和指针丢失
3.利用哨兵简化编程难度
4.养成留意边界的习惯(不止链表所有结构你都要考虑边界)
5.结点
链表是由一个个结点构成的,而结点包括两部分:数据和指针,数据大家都知道,指针是干什么用的呢,是为了指向下一个结点的,因为我们说数组是在定义的时候系统分配一个连续的空间,当没有足够大的连续空间时,我们用链表这种结构就可以将分散的空间连接起来存储数据,而指针的作用很明显了,就是为了指向下一个结点保证数据能有效连接而不会找不到。
结点的结构很简单:
class NODE{
T data; //T是数据类型 就像int char等
NODE next;
};
常用链表有单链表、双链表、循环链表(为什么会有这几种结构呢?请往下看)
- 单向链表结构如下,空间上存储值和下一个结点的指针(叫后继指针)
- 双向链表结构如下:
相对于单链表多了个前驱指针
- 循环链表结构如下:
就是单链表的最后一个结点的后继指针不指向NULL结点,而指向头结点
那么为什么会出现这几种结构的链表呢,只有单链表不行吗?
当然不是只有单链表不行,要知道每种数据结构和算法都是为了做性能优化,单链表在某种情况下不够快所有衍生出其他结构,比如我们说链表插入,删除操作的时间复杂度为O(1),但是实际上真的是O(1)吗?并不是,当你要在p结点前插入一个q结点(p的前一个结点是f),首先你要从头开始一个结点一个结点的找,找到那个f结点,将q的指针先指向p,然后将f的指针指向p。可查找的时间复杂度就是O(n)了,但是如果你用双向链表,它有前驱结点,直接就可以指向f那就省去了查找的步骤,典型的用空间换时间的想法
q->next = f->next;
f->next = q;
有人会问上面的两步反过来写行不;不行,为啥呢,一旦你写成这样
f->next = q;
q->next = f->next;
f 的next已经不是p 了所以写结点一定不要想当然。
关注我,会定期更新数据结构与算法,开发中的感悟,共同学习。加油!!!