为什么像C++和Java这样的语言有一个内置的LinkedList数据结构



许多编程语言都提供内置的数据结构,尽管一些数据结构(例如链表)非常容易实现,因此,语言通常不包括它作为内置数据结构。 一些语言,如C++有(如std::list,双链接),以及Java(如LinkedList<T>,双链接)。

例如,Python 的库中已经内置了几个数据结构,包括列表、元组、集合、字典(甚至不需要导入)以及来自collections库的数据结构。它没有内置的LinkedList数据结构,因为在Python中已经很容易实现自己的LinkedList。

请注意,Python 列表的底层数据结构实际上是一个数组,如"Python 列表的底层数据结构是什么?"中所述。此外,collections中的deque是一个双端队列,它应该缺少功能,因为它通常不支持索引或在中间插入(但是,从 3.5 开始添加了索引功能,具有indexinsert,但在 Python 2 中不存在)。

似乎提供内置LinkedList数据结构是冗余且不必要的。为什么其他一些编程语言库(如C++和Java库)包含LinkedList数据结构,即使它们很容易实现?如果是这样,在这些语言中实现自己的链表有什么风险?

我搜索了Guido的Python History博客,因为我确信他写过这个,但显然这不是他这样做的地方。因此,这是基于推理(又名有根据的猜测)和记忆(可能是错误的)的组合。

让我们从最后开始:在不知道为什么Guido没有在Python 0.x中添加链表的情况下,我们至少知道为什么核心开发人员从那时起就没有添加它们,即使他们已经添加了一堆从OrderedDictset的其他类型的方法?

是的,我们愿意。简短的版本是:二十多年来没有人要求它。多年来添加到内置或标准库中的几乎都是(变体)在 PyPI 或 ActiveState 配方上被证明是有用和流行的。例如,这就是OrderedDictdefaultdict的来源,以及enumdataclass(基于attrs)。还有一些其他容器类型的流行库 - 排序字典/集合,OrderedSet,树和尝试等的各种排列,并且SortedContainersblist都被提议包含在stdlib中,但被拒绝。

但是没有流行的链表库,这就是为什么永远不会添加它们的原因。

因此,这就把问题带回了一步:为什么没有流行的链表库?

首先,"链表"并不是真正的一种类型,而是一整套类型——单链接与双链接、节点即列表与句柄即列表、尾部共享与否、懒惰(大概是通过@property式触发器)或严格......以及循环列表等变体。当然,这些中的每一个都远远不如整个家庭有用。而且你不能在接口或实现之间共享那么多东西——一个处理 Lisp 风格的cons列表的接口对于像 C++std::list这样的东西根本没有意义。

其次,所有不同的变体都很容易构建。OrderedDict把它变成语言的原因是人们能够证明它实际上是非常棘手的。集合很容易正确,但如果不从字典中借用幕后实现细节,就不可能优化空间。链表很容易正确和优化。如果你想要一个,任何品种,你在几分钟内建立一个,你就完成了。(事实上,OrderedDict在引擎盖下使用一个...

同时,自 Python 2.3 以来,尤其是 3.0 以来,迭代器协议已成为一切的中心范式。其他语言借用Python的生成器是有原因的 - 但在大多数这些语言中,它们并没有提供同样的好处,因为整个语言不是围绕它们构建的。能够转发任何集合(包括甚至不存在的"虚拟"集合)已经为您提供了懒惰尾部共享缺点列表的大部分优势,而无需一个。另一方面,它缺少的主要内容是方便的恒定时间(突变)拼接 - 但缺少的东西实际上很难适应迭代器范式。(请参阅itertools了解如何做到这一点 - 毕竟这只是teechain- 以及这样做的感觉是多么笨拙。

(当然,更复杂的迭代协议也有好处,比如C++使用的协议,甚至更好的是 Swift。对于双向和可变与不可变的迭代,双向链表可能更有用。但是在功能和简单性之间有一个权衡,Python很久以前就做出了选择。

最后但并非最不重要的一点是,链表,尤其是 cons-style tail 共享链表,本质上是一种递归数据结构。Python 的理念是,只有当你有固有的递归问题时,才使用递归。Guido认为这些很少,这就是为什么Python不这样做,例如,尾递归消除。他不想用他的语言mapreduce,但是一旦他想出了如何迭代而不是递归地做它们,他愿意让它们留下来。存储线性数据本质上不是一个递归问题。树?当然,它们几乎必须是递归的。但是列表呢?不。

相关内容

  • 没有找到相关文章

最新更新