【问题标题】:Data structure name: combination array/linked list数据结构名称:组合数组/链表
【发布时间】:2011-02-26 18:25:41
【问题描述】:

我提出了一种数据结构,它结合了链表的一些优点和固定大小数组的一些优点。这对我来说似乎很明显,所以我希望有人已经想到并命名了它。有谁知道这叫什么:

取一个固定大小的小数组。如果要放入数组的元素数量大于数组的大小,请添加一个新数组,并在新旧数组之间添加任何您喜欢的指针。

这样你就有了:

Static array
—————————————————————————
|1|2|3|4|5|6|7|8|9|a|b|c|
—————————————————————————

Linked list
————  ————  ————  ————  ————
|1|*->|2|*->|3|*->|4|*->|5|*->NULL
————  ————  ————  ————  ————

My thing:
————————————  ————————————
|1|2|3|4|5|*->|6|7|8|9|a|*->NULL
————————————  ————————————

编辑:作为参考,这个算法提供了非常差的最坏情况添加/删除性能,并且没有更好的平均情况。我的方案的最大优势是提高了读取操作的缓存性能。

Edit re bounty:Antal S-Z 的答案是如此完整且经过充分研究,以至于我想为他们提供赏金。显然,一旦我提供了赏金,Stack Overflow 不会让我立即接受答案,所以我将不得不等待(诚然,我在某种程度上滥用了意图赏金系统,尽管它是以奖励某人为名回答)。当然,如果有人确实设法提供了更好的答案,给他们更多的权力,他们当然可以得到赏金!

编辑重新命名:我对你会如何称呼它不感兴趣,除非你会这样称呼它,因为这是有关该主题的权威人士会这样称呼它它。如果这是你刚想出来的名字,我不感兴趣。我想要的是一个我可以在教科书和谷歌中查找的名字。 (另外,这里有一个提示:Antal 的答案正是我想要的。如果你的答案不是“展开的链表”而没有非常充分的理由,那就大错特错了。)

【问题讨论】:

  • 从算法复杂性的角度来看很有趣 - 从技术上讲,你几乎所有基本操作都是 O(n) (这很糟糕),但你得到一个非常低的恒定比例因子(这很好,其他的都是平等的!)。如果这适用于您的应用程序,对您有好处,但我仍然建议您进行一些仔细的基准测试:-)
  • 如果我错了,请纠正我。我使用过 C、C++ 和 Java,所有这些都只允许您存储一种类型的数据。在上述情况下,有些数组元素是 int,有些是 char,有些是指针。您的数组将如何实际声明?您是否使用某种结构来表示这一点?
  • srikfreak:这个想法是,在链表中,你有(在 C++ 中)template <typename T> struct ll_node { T value; ll_node<T>* next; },在这里你会有类似template <typename T> struct ull_node { T value[MAX]; size_t n_elements; ull_node<T>* next; } 的东西。我不认为“静态数组”案例中的数组元素应该表示文字值,但如果你愿意,我敢打赌你可以将它们视为十六进制数字而不是字符。
  • 我们缺乏有关您执行插入和删除方式的信息,即您可以在列表中间放置半填充数组吗?如果不是,C++ STL 称它为deque
  • 我很好奇为什么你不会只有一个数组的 LinkedList

标签: algorithm language-agnostic data-structures


【解决方案1】:

我称之为遗愿清单。

【讨论】:

    【解决方案2】:

    你可以叫它LinkedArrays

    另外,我想看看removeIndex 操作的伪代码。

    【讨论】:

    • 请阅读这个问题(特别是现在我添加了一个附录)。我对你怎么称呼它不感兴趣。我对它叫什么很感兴趣。您可能会称猫为 waffleopalus,但如果您想谈论您的宠物,只有使用“猫”这个词谈论它才会对其他人有用。
    【解决方案3】:

    虽然我不知道你的任务,但我强烈建议你看看跳过列表。

    至于名字,我想一个桶列表可能是最合适的

    【讨论】:

    • 请阅读这个问题(特别是现在我添加了一个附录)。我对你怎么称呼它不感兴趣。我对它叫什么很感兴趣。您可能会称猫为 waffleopalus,但如果您想谈论您的宠物,只有使用“猫”这个词谈论它才会对其他人有用。
    【解决方案4】:

    CDR coding(如果您的年龄足以记住 Lisp 机器)。

    另请参阅ropes,这是字符串列表/数组概念的概括。

    【讨论】:

    • CDR 编码似乎与我所追求的有所不同。正如 Antal 所指出的(以及该文章末尾的 Wikipedia 链接),展开的链表是我所追求的。
    【解决方案5】:

    这种数据结构在插入和删除方面有什么优势? 前任: 如果你想在 3 和 4 之间添加一个元素怎么办?仍然需要换班,需要 O(N) 您如何找到 elementAt 的正确存储桶?

    我同意 jer,你必须看看 skip list。它带来了链表和数组的优点。 大部分操作都在 O(log N) 内完成

    【讨论】:

      【解决方案6】:

      它被称为unrolled linked list。似乎有几个优势,一个是速度,一个是空间。首先,如果每个节点中的元素数量大小合适(例如,最多为一个缓存行的大小),您可以从改进的内存局部性中获得明显更好的缓存性能。其次,由于您有 O(n/m) 个链接,其中 n 是展开的链表中的元素数,而 m 是您可以在任何节点中存储的元素数量,您还可以节省大量空间,如果每个元素都很小,这一点尤其明显。在构建展开的链表时,显然实现通常会尝试在节点中留出空间;当您尝试插入完整节点时,会将一半元素移出。因此,最多一个节点将少于半满。根据我能找到的(我自己没有做任何分析),如果你随机插入东西,节点实际上往往是四分之三左右,如果操作往往在列表的末尾,甚至更满。

      正如其他所有人(包括维基百科)所说,您可能想查看skip lists。跳过列表是一种漂亮的概率数据结构,用于存储有序数据,插入、删除和查找的预期运行时间为 O(log n)。它由链表的“塔”实现,每一层的元素越少,越高。在底部,有一个普通的链表,包含所有元素。在每个连续的层中,元素的数量会减少 p 倍(通常为 1/2 或 1/4)。它的构建方式如下。每次将一个元素添加到列表中时,它都会插入到底部行的适当位置(这使用“查找”操作,也可以使其快速)。然后,以 p 的概率将它插入到链表“上方”的适当位置,如果需要,则创建该链表;如果它被放置在更高的列表中,那么它将再次以概率p出现在上面。要查询此数据结构中的某些内容,您总是检查顶部通道,看看是否可以找到它。如果您看到的元素太大,您会下降到下一个最低的车道并重新开始查看。这有点像二分搜索。 Wikipedia 很好地解释了它,并带有漂亮的图表。当然,内存使用率会变差,而且缓存性能不会得到改善,但通常会更快。

      参考文献

      【讨论】:

      • 根据您的描述,我认为跳过列表不会起作用;我想使用展开链表的主要原因是缓存性能。
      • 如果你以节点为中心的方式实现它,你只会失去缓存性能。看看从缓存友好的方式考虑,就可以实现缓存友好的跳过列表。
      • jer:有趣。你有关于如何做到这一点的任何提示,或任何链接/论文吗?我对这种设计不是很熟悉,所以我不知道如何立即。
      • 这个想法是将节点真正存储在单线程平台上的连续空间中。并不是说您可以像访问数组或其他任何东西一样访问它,但是您通常可以(在具有多个内核等的现代平台上可以很好地看到这一点)将列表的只读副本存储在每个内核的缓存中(如果它们是)同时处理一个列表,他们很乐意这样做,而且我们只需要交出改变的数据,如果它影响其他数据,它通常不会(即,最坏的情况下,我们必须使数据无效在双重列表更新中另一个核心的一个缓存行中)
      猜你喜欢
      • 2015-07-28
      • 2013-06-03
      • 2013-09-15
      • 2021-01-09
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      • 2020-02-21
      • 2017-08-31
      相关资源
      最近更新 更多