【问题标题】:which data structure should i choose and why我应该选择哪种数据结构以及为什么
【发布时间】:2011-09-05 11:32:51
【问题描述】:

我正在用 C 语言编写计时器管理器,其中涉及:

  • 创建新计时器
  • 删除计时器
  • 删除死定时器
  • 冻结计时器
  • 以及所有其他我还没有想到的东西。

关键是 - 内存量应该尽可能小。 起初我考虑链表,但如果我删除一些中间部分,我应该重建链表,这可能需要一些时间。典型的动态数组是相同的 - 当我重新构建该结构时,我应该小心使用指针,以免错过其中的一些。

有什么想法吗?

谢谢大家的回答

【问题讨论】:

  • 嗯,通常情况下,在中间修改它是(双)链表的优势之一。

标签: c data-structures


【解决方案1】:

从链表中删除时不需要重建任何东西。这是O(1) 操作。无论您选择哪种结构,您都可能必须小心指针。

【讨论】:

  • 这具有误导性 - 如果您要从任一端移除,或者您已经拥有对该项目的引用,这只是一个 O(1) 操作。如果你必须在列表中找到一个项目来删除它,它不是 O(1)。从问题来看,删除计时器似乎可能发生在列表中的任何地方。
  • @PFHayes 我假设了一个双向链表。如果您不知道如何在恒定时间内从双向链表中删除元素,请提出问题 - 我会帮助您:-)。像这样表达它:“我不知道如何在恒定时间内从列表中删除元素”。
  • 我的意思是,从问题中不清楚该列表是否用于查找计时器,或者只是维护该列表。如果您正在遍历列表并删除所有死定时器,那么删除每个定时器都是 O(1)。如果您尝试从列表中删除任意计时器,则必须首先找到它,这是线性的。
  • @PFHayes 您可以使用计时器保留指向列表节点的链接。我的意思是,在计时器结构中保留一个struct node *link。然后你将跳过搜索部分。
  • @PFHayes:如果这是一个计时器 API,那么大概当用户创建计时器时,它会为用户提供某种可用于取消计时器的句柄。如果此句柄是指向列表节点的指针,则无需进行线性搜索来删除它。因此,虽然您是对的,有时删除需要先进行搜索,但删除任意计时器并不总是需要线性搜索 - 您只会根据与存储的属性的某些匹配项删除计时器进行搜索在节点中。
【解决方案2】:

通常,数组使用最少的内存。单块,因此分配开销更少,并且没有像链表中的下一个/上一个指针那样的管理开销。

当然,从足够大的数组的开头/中间删除比从链表中删除给定节点的时间效率要低,而且数组中的任何指针/索引都将不再引用一旦你完成了相同的元素,所以你必须小心你为定时器 API 的用户提供什么句柄,以及如何找到特定句柄的定时器数据。但如果内存使用真的是唯一重要的问题,那么数组就赢了。

我以前做过类似的事情,我个人会从一个链表开始,除非它显然会失败一些特定的约束。指向“timerdata”结构的指针数组也可以很好地工作,前提是您可以防止活动计时器列表变得太大。

【讨论】:

    【解决方案3】:

    如果内存量必须尽可能小,我会选择一个数组,使用数组的唯一缺点是调整数组的大小很昂贵(很多 cpu 周期),但是如果你可以设置一个上限限制计时器的数量,然后使用大小为该最大值的单个数组将是有效的。如果计时器的数量是非常动态的,那么列表(向量集合)就是要走的路。

    【讨论】:

      【解决方案4】:

      您可以使用堆/优先级队列。这与数组具有相同的内存要求,但插入和删除是 O(lg n) 操作。队列中的项目可以按每个计时器对象的剩余触发时间排序。当真正的计时器触发时,您必须调整列表中每个其他计时器的触发时间。因此,如果 timer1 设置为在 1 秒后关闭,而 timer2 设置为在 1.5 秒后关闭,则当 timer1 触发时,您必须将 timer2 调整为在 0.5 秒后关闭。大概是这样的吧?

      【讨论】:

        【解决方案5】:

        什么是计时器元素?这里面是什么?它只是一个被某个定时器中断或某个复杂类不断倒计时的值,也许是用自己的线程来计时?

        最常执行哪些操作? - 优先优化对这些内容的访问。

        排序列表有什么好处,例如。按到期时间升序排列,因此下次超时的计时器始终位于列表的开头(即 delta-queue)。

        Rgds, 马丁

        【讨论】:

          猜你喜欢
          • 2013-11-12
          • 1970-01-01
          • 2019-11-20
          • 1970-01-01
          • 1970-01-01
          • 2012-05-15
          • 2013-07-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多