资讯专栏INFORMATION COLUMN

python双向链表的疑问(Question)

Turbo / 3226人阅读

摘要:然而对于它为什么要这样实现我还不是很清楚,留待以后继续探究。这里是我在上关于这个问题的提问。

问题

在看 collections.OrderedDict 的源码时,对于它如何构造有序的结构这一部分不是很理解,代码如下:

</>复制代码

  1. class OrderedDict(dict):
  2. "Dictionary that remembers insertion order"
  3. # An inherited dict maps keys to values.
  4. # The inherited dict provides __getitem__, __len__, __contains__, and get.
  5. # The remaining methods are order-aware.
  6. # Big-O running times for all methods are the same as regular dictionaries.
  7. # The internal self.__map dict maps keys to links in a doubly linked list.
  8. # The circular doubly linked list starts and ends with a sentinel element.
  9. # The sentinel element never gets deleted (this simplifies the algorithm).
  10. # Each link is stored as a list of length three: [PREV, NEXT, KEY].
  11. def __init__(*args, **kwds):
  12. """Initialize an ordered dictionary. The signature is the same as
  13. regular dictionaries, but keyword arguments are not recommended because
  14. their insertion order is arbitrary.
  15. """
  16. if not args:
  17. raise TypeError("descriptor "__init__" of "OrderedDict" object "
  18. "needs an argument")
  19. self = args[0]
  20. args = args[1:]
  21. if len(args) > 1:
  22. raise TypeError("expected at most 1 arguments, got %d" % len(args))
  23. try:
  24. self.__root
  25. except AttributeError:
  26. self.__root = root = [] # sentinel node
  27. root[:] = [root, root, None]
  28. self.__map = {}
  29. self.__update(*args, **kwds)
  30. def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
  31. "od.__setitem__(i, y) <==> od[i]=y"
  32. # Setting a new item creates a new link at the end of the linked list,
  33. # and the inherited dictionary is updated with the new key/value pair.
  34. if key not in self:
  35. root = self.__root
  36. last = root[0]
  37. last[1] = root[0] = self.__map[key] = [last, root, key]
  38. return dict_setitem(self, key, value)
  39. def __delitem__(self, key, dict_delitem=dict.__delitem__):
  40. "od.__delitem__(y) <==> del od[y]"
  41. # Deleting an existing item uses self.__map to find the link which gets
  42. # removed by updating the links in the predecessor and successor nodes.
  43. dict_delitem(self, key)
  44. link_prev, link_next, _ = self.__map.pop(key)
  45. link_prev[1] = link_next # update link_prev[NEXT]
  46. link_next[0] = link_prev # update link_next[PREV]
  47. def __iter__(self):
  48. "od.__iter__() <==> iter(od)"
  49. # Traverse the linked list in order.
  50. root = self.__root
  51. curr = root[1] # start at the first node
  52. while curr is not root:
  53. yield curr[2] # yield the curr[KEY]
  54. curr = curr[1] # move to next node
  55. def __reversed__(self):
  56. "od.__reversed__() <==> reversed(od)"
  57. # Traverse the linked list in reverse order.
  58. root = self.__root
  59. curr = root[0] # start at the last node
  60. while curr is not root:
  61. yield curr[2] # yield the curr[KEY]
  62. curr = curr[0] # move to previous node
  63. def clear(self):
  64. "od.clear() -> None. Remove all items from od."
  65. root = self.__root
  66. root[:] = [root, root, None]
  67. self.__map.clear()
  68. dict.clear(self)

主要是对于初始化里和set方法里的做法不清楚, wtf doing here…:

</>复制代码

  1. self.__root = root = [] # sentinel node
  2. root[:] = [root, root, None]
  3. self.__map = {}
  4. # 和
  5. root = self.__root
  6. last = root[0]
  7. last[1] = root[0] = self.__map[key] = [last, root, key]

后来在网上提问并且自己查询了相关资料后明白这是个带哨兵的双向链表的实现,关于双向链表的知识自己补了下,可以参见这里 和 这里。

然而对于它为什么要这样实现我还不是很清楚,留待以后继续探究。

这里 是我在v2ex上关于这个问题的提问。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44296.html

相关文章

  • List集合就这么简单【源码剖析】

    摘要:线程不安全底层数据结构是链表。的默认初始化容量是,每次扩容时候增加原先容量的一半,也就是变为原来的倍删除元素时不会减少容量,若希望减少容量则调用它不是线程安全的。 前言 声明,本文用得是jdk1.8 前一篇已经讲了Collection的总览:Collection总览,介绍了一些基础知识。 现在这篇主要讲List集合的三个子类: ArrayList 底层数据结构是数组。线程不安全 ...

    cpupro 评论0 收藏0
  • 线性结构 数组与链表

    摘要:线性结构数组与链表线性结构线性数据结构有两端,有时被称为左右,某些情况被称为前后。将两个线性数据结构区分开的方法是添加和移除项的方式,特别是添加和移除项的位置。相对于数组,链表的好处在于,添加或移除元素的时候不需要移动其他元素。 线性结构 数组与链表 线性结构 线性数据结构有两端,有时被称为左右,某些情况被称为前后。你也可以称为顶部和底部,名字都不重要。将两个线性数据结构区分开的方法...

    xi4oh4o 评论0 收藏0
  • 线性结构 数组与链表

    摘要:线性结构数组与链表线性结构线性数据结构有两端,有时被称为左右,某些情况被称为前后。将两个线性数据结构区分开的方法是添加和移除项的方式,特别是添加和移除项的位置。相对于数组,链表的好处在于,添加或移除元素的时候不需要移动其他元素。 线性结构 数组与链表 线性结构 线性数据结构有两端,有时被称为左右,某些情况被称为前后。你也可以称为顶部和底部,名字都不重要。将两个线性数据结构区分开的方法...

    edagarli 评论0 收藏0
  • LinkedHashMap就这么简单【源码剖析】

    摘要:习惯在微信看技术文章,想要获取更多的资源的同学,可以关注微信公众号。为了大家方便,刚新建了一下群,大家也可以去交流交流。谢谢支持了希望能多介绍给其他有需要的朋友 前言 声明,本文用得是jdk1.8 前面已经讲了Collection的总览和剖析List集合以及散列表、Map集合、红黑树还有HashMap基础了: Collection总览 List集合就这么简单【源码剖析】 Map集合、...

    avwu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<