zoukankan      html  css  js  c++  java
  • 【数据结构】链表

    链表和数组:

    链表是一个相对简单的数据结构,与数组不同的是,它并不需要一块连续的内存空间,而是通过指针将一组零散的内存块串联起来使用。


    单链表:

    我们吧内存块称为链表的结点,为了将所有的结点串起来,每个链表的结点除了存储数据意外,还需要记录链上的下一个结点的地址。这个记录下个结点的指针叫做后继指针next。

    我们习惯吧的第一个结点称为头结点,把最后一个结点叫做尾结点。其中,头系欸但用来记录链表的基地址,而尾结点指向一个空地址Null,表示这是链表上的最后一个结点。


    单链表的查找、插入,删除操作:

    在进行数组的插入、删除操作时,为了保持内存数据的连续性,需要做大量的数据搬移,所以时间复杂度为o(n),而链表插入或者删除数据,由于本身链表的存储空间本身不是连续的,只需要考虑相邻结点的指针改变,其对应的时间复杂度为o(1)。

    相对的,链表不能通过下标的随机访问高效访问第K个元素,只能根据指指针一个结点一个结点地依次遍历。其时间复杂度为o(n)。


    循环链表和双向链表:

    循环链表是一种特殊地单链表,其唯一区别在于循环链表指针指向头结点,适合处理具有环形结的数据,比如约瑟夫问题。

    单向链表只有一个方向,结点只有一个后继指针next指向后面的结点,而双向链表多了一个前驱指针prev指向前面的结点。由于双向链表需要额外的空间来存储前驱结点的地址,所以双向链表要比单链表占用更多的内存空间,而且支持在o(1)时间复杂度下找到前驱结点。


    关于双向链表的操作:

    双向链表和单向链表都支持o(1)的时间复杂度下进行删除操作,但是双向链表会更快一些。这是由于在实际的软件开发中,从链表中删除一个数据一般是这俩种情况:

    1.删除结点中“值为某个定值”的结点

    2.删除给定指针指向的结点

    对于第一种情况,不管是单链表还是双向链表,都要从头开始进行依次遍历对比,直到找到值等于给定值的结点,再通过指针操作进行删除。

    尽管单纯的删除时间复杂度是o(1),但是遍历的适合时间复杂度却为o(n)。

    对于第二种情况,我们已经找到了需要删除的结点,但是单链表还需要一个指针遍历一次,也可以通过前后指针进行遍历,不管怎么样,一个指针并不能完成删除操作,而双向链表只要一个指针就能完成操作。

    此外,对于有序链表,双向链表查找效率也要比单链表效率高一些。

    因此,虽然双向链表比较费内存,但是还是比单链表应用更加广泛。如Java中的LinkedHashMap容器。


    留意边界条件处理:

    链表为空时

    链表只包含一个结点时

    链表只包含俩个结点时

    代码逻辑再处理头节点和尾结点的时候


    如何理解指针:

    将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针,或者反过来说,指针中长长了这个变量的内存地址,指向了这个变量,通过指针就能找到这个变量。

  • 相关阅读:
    HDU 5835 Danganronpa(弹丸论破)
    HDU 5813 Elegant Construction(优雅建造)
    HDU 5831 Rikka with Parenthesis II(六花与括号II)
    HDU 5810 Balls and Boxes(盒子与球)
    HDU 5818 Joint Stacks(联合栈)
    Dream Team(最小生成树)
    带权并查集
    HDU 1495 非常可乐(BFS)
    I Hate It(线段树+更新)
    Just a Hook(线段树+区间更新)
  • 原文地址:https://www.cnblogs.com/guangluwutu/p/11685675.html
Copyright © 2011-2022 走看看