数据结构与算法学习之路3--链表

174 阅读3分钟

链表定义

链表也是一种线性的的数据结构,它和数组的不同点是它不需要连续的内存块来存储,它使用指针可以将零散的内存使用起来。

链表中的内存块称为链表的结点,每个结点除了保存数据之还需要保存地址信息

常见的三种链表

单向链表

通过上图我们可以分析出单向链表的特征:它只有一个方向;每个内存块中存储了下一个结点的地址。 其中有两个特殊的结点,第一个结点和最后一个结点。第一个结点叫作头结点,头结点用来记录链表的基地址。有了它,我们就可以遍历得到整条链表。最后一个结点叫作尾结点,他的指针不是指向下一个结点,而是指向一个空地址 NULL,表示这是链表上最后一个结点。

双向链表

通过上图我们可以分析出双向链表的特征:双向链表有两个方向;每个内存中包含两个指针,一个指向前一个结点的地址,另一个指向后一个节点的地址。其中首节点的前驱指针prev和尾节点的后继指针均指向空地址。

循环链表

通过上图我们可以看出循环链表和单向链表唯一区别就是它的尾结点的指针指向头结点。

链表分析

链表随机访问

因为链表使用内存不连续所以无法像数组一样通过首地址和下标计算出对应地址,只能遍历整个链表去找,因此时间复杂度为O(n)

链表插入

因为不需要连续的内存所以不牵扯数据的搬迁。

  • 在已知某个元素的前提下,在他的位置后面插入新数据只进行指针修改操作就可以了所以时间复杂度为O(1);
  • 当元素未知时需要先查找数据然后在插入,此时时间复杂度为O(n)

链表删除

  • 删除已知元素的后一个元素时,只需要修改指针就行了,时间复杂度为O(1)。
  • 删除已知元素的前一个元素时,单向链表需要找到前一个元素的地址,时间复杂度为O(n);双向链表存储了前驱指针所以时间复杂度为O(1)
  • 删除未知元素的前、后元素时需要先找到元素然后在进行删除操作,时间复杂度为O(n)

链表缺点

  • 内存空间消耗更大,因为需要额外的空间存储指针信息。
  • 对链表进行频繁的插入和删除操作,会导致频繁的内存申请和释放,容易造成内存碎片,如果是Java语言,还可能会造成频繁的GC(自动垃圾回收器)操作。