链表

作者: TomGui | 来源:发表于2019-11-27 22:33 被阅读0次

    定义

    链表不需要一块连续的内存空间,它通过“指针”将一组零散的内存块串联起来使用。

    链表通过指针将一组零散的内存块串联在一起。其中,我们把内存块称为链表的“结点”。为了将所有的结点串起来,每个链表的结点除了存储数据之外,还需要记录链上的下一个结点的地址。如图所示,我们把这个记录下个结点地址的指针叫作后继指针next

    常用链表

    单链表、双向链表和循环链表

    单链表

    我们习惯性地把第一个结点叫作头结点,把最后一个结点叫作尾结点。其中,头结点用来记录链表的基地址。有了它,我们就可以遍历得到整条链表。而尾结点特殊的地方是:指针不是指向下一个结点,而是指向一个空地址NULL,表示这是链表上最后一个结点。

    循环链表

    和单链表相比,循环链表的优点是从链尾到链头比较方便。当要处理的数据具有环型结构特点时,就特别适合采用循环链表。比如著名的约瑟夫问题。

    双向链表

    单向链表只有一个方向,结点只有一个后继指针next指向后面的结点。而双向链表,顾名思义,它支持两个方向,每个结点不止有一个后继指针next指向后面的结点,还有一个前驱指针prev指向前面的结点。

    删除操作

    在实际的软件开发中,从链表中删除一个数据无外乎这两种情况:

    • 删除结点中“值等于某个给定值”的结点
    • 删除给定指针指向的结点

    对于第一种情况,不管是单链表还是双向链表,为了查找到值等于给定值的结点,都需要从头结点开始一个一个依次遍历对比,直到找到值等于给定值的结点,然后再通过我前面讲的指针操作将其删除。

    尽管单纯的删除操作时间复杂度是O(1),但遍历查找的时间是主要的耗时点,对应的时间复杂度为O(n)。据时间复杂度分析中的加法法则,删除值等于给定值的结点对应的链表操作的总时间复杂度为O(n)。

    对于第二种情况,我们已经找到了要删除的结点,但是删除某个结点 q 需要知道其前驱结点,而单链表并不支持直接获取前驱结点,所以,为了找到前驱结点,我们还是要从头结点开始遍历链表,直到 p->next=q,说明 p 是 q 的前驱结点。

    但是对于双向链表来说,这种情况就比较有优势了。因为双向链表中的结点已经保存了前驱结点的指针,不需要像单链表那样遍历。所以,针对第二种情况,单链表删除操作需要O(n)的时间复杂度,而双向链表只需要在 O(1) 的时间复杂度内就搞定了!

    链表 VS 数组性能大比拼

    时间复杂度 数组 链表
    插入/删除 O(n) O(1)
    随机访问 O(1) O(n)

    相关文章

      网友评论

        本文标题:链表

        本文链接:https://www.haomeiwen.com/subject/pkomwctx.html