【问题标题】:ordered doubly linked list search有序双向链表搜索
【发布时间】:2011-07-10 15:43:17
【问题描述】:

假设我们有一个按整数排序的双向链表:

struct ListItem
{
  int value;
  ListItem *prev, *next;
};

struct List
{
  ListItem *first, *last;
  int count;
};

我们是否可以使用更快的搜索算法(例如二分搜索)在 List 中定位 ListItem 以及如何定位?

【问题讨论】:

  • 听起来像是功课。请在标题中添加作业标签和/或单词“作业”。
  • 编写多语言源文件很难。我建议你坚持使用 C 或 C++ 之一。

标签: c++ c linked-list html-lists


【解决方案1】:

对于大多数实际用途,不。如果你想要更快的搜索,链表是一个糟糕的数据结构选择。请考虑使用向量、双端队列、集合或多重集合。

编辑:也许最好提供一些指导,说明哪些是有意义的。如果您有两个基本独立的阶段,则向量最有意义:要么按顺序插入所有数据,要么插入并排序,然后在数据排序后,数据保持静态,您只需在其中搜索即可。双端队列几乎是一样的,除了你可以在任一端插入,所以如果你可能得到数据乱序,但新数据总是属于集合的一端或另一端,它可能是一个不错的选择。

如果您要将插入/删除与查找混合使用,setmultiset 效果会更好。它始终保持排序,因此搜索总是相当快。在两者之间(set vs. multiset),选择非常简单:如果您需要确保集合中的每个项目都是唯一的,那么您需要设置。如果您可能有多个具有相同键的项目,则需要一个多重集。

【讨论】:

  • 我正在为大数据集编写一个哈希表,该哈希表使用分离链方法,由于内存重新分配,使用向量将是一个不好的选择
  • @Muhammad:我不确定我是否遵循在这种情况下内存重新分配应该如何产生重大影响。无论如何,对于哈希表,您搜索冲突链的方法应该很少有太大的不同。缺少一个病态的散列函数或对整体大小的严重错误猜测,您应该很少搜索超过几个项目(通常为 ~3 个)。只需搜索这么小的集合,线性搜索与二分搜索几乎没有区别。
【解决方案2】:

如果节点之间没有基于这些值的排序,那么除了单独检查所有节点之外别无选择。因此 O(n)。

【讨论】:

    【解决方案3】:

    是的,你可以,但除非“比较值”的操作比“移动指针”的成本高得多,否则它完全没有意义。由于通常“移动”的成本与“比较”的成本差不多,因此使用普通搜索:

    • O(N) 次移动
    • O(N) 次比较

    二进制:

    • O(N) 次移动以确定列表的大小
    • O(N) 移动以定位元素
    • O(log(N)) 次比较。

    在你的例子中,值是“int”,这意味着比较比移动更便宜,所以二进制算法会更昂贵。

    如果您知道列表的大小,二进制可能(可以说)变得更便宜,但是双向逻辑旅行和元素计数增加的复杂性将扼杀减少值比较次数带来的任何好处。

    当然,如果您需要多次搜索,最简单的方法是将链表转换为数组或创建索引 - 指针数组。如果该值比int 复杂得多并且更难以比较,当然最需要更快的算法。

    【讨论】:

      【解决方案4】:

      好吧,您仍然需要循环遍历所有元素,直到中间元素。我不确定二进制搜索是否会因此加快通过链表的搜索速度。例如,您的元素位于中间元素之前,从逻辑上讲,循环浏览这些元素似乎更快。否则,你只会走到中间,看看你的元素与那个相关的位置,然后再次循环,是的……循环才是真正杀死它的原因。我想这也取决于你的元素在列表中的确切位置。

      【讨论】:

        【解决方案5】:

        如果您只需要执行几次搜索,我怀疑从头到尾搜索列表将是最佳选择。可能有一些算法可以更有效,但只会稍微好一点。

        但是,如果您必须执行多次搜索,则可以将列表复制到支持二进制搜索的有序、随机访问容器中。

        【讨论】:

          猜你喜欢
          • 2012-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-13
          • 2012-07-15
          • 2019-06-23
          • 1970-01-01
          相关资源
          最近更新 更多