【问题标题】:Queue-like data structure with fast search and insertion具有快速搜索和插入的类似队列的数据结构
【发布时间】:2010-04-15 21:43:49
【问题描述】:

我需要一个具有以下属性的数据结构:

  1. 它包含整数。
  2. 不允许重复(也就是说,它最多存储任何整数中的一个)。
  3. 在达到最大尺寸后,第一个元素被删除。 因此,如果容量为 3,那么这就是将其放入序列号时的样子: {}、{1}、{1、2}、{1、2、3}、{2、3、4}、{3、4、5} 等
  4. 只需要两个操作:将数字插入此容器 (INSERT) 并检查该数字是否已在容器中 (EXISTS)。 EXISTS 操作的数量预计约为 2 * INSERT 操作的数量。
  5. 我需要这些操作尽可能快。

对于这种情况,最快的数据结构或数据结构组合是什么?

【问题讨论】:

  • 第一个元素是指最小元素还是最旧元素?

标签: performance data-structures


【解决方案1】:

听起来像是使用环形缓冲区进行存储的哈希表。

【讨论】:

  • +1 快速、可靠的响应。听起来结构也需要知道哪个元素是“第一个”,但这是一个很小的变化。
【解决方案2】:

O(1) 用于插入和查找 (如果最终需要,可以删除)

数据结构:

包含整数的节点队列,实现为链表 (queue)

HashMap 将整数映射到 Queue 的链表节点 (hashmap)

插入:

if (queue.size >= MAX_SIZE) {
    // Remove oldest int from queue and hashmap
    hashmap.remove(queue.pop());
} else if (!hashmap.exists(newInt)) { // remove condition to allow dupes.
    // add new int to queue and hashmap if not already there
    Node n = new Node(newInt);
    queue.push(n);
    hashmap.add(newInt, n);
}

查找:

return hashmap.exists(lookupInt);

注意:使用此实现,您还可以在 O(1) 中删除整数,因为您所要做的就是在哈希图中查找节点,并将其从链表中删除(通过将其邻居链接在一起)。

【讨论】:

    【解决方案3】:

    你想要一个环形缓冲区,最好的方法是定义一个你想要的大小的数组,然后维护它的开始和结束位置的索引。

    int *buffer = {0,0,0};
    int start = 0;
    int end = 0;
    #define LAST_INDEX 2;
    
    void insert(int data)
    {
       buffer[end] = data;
       end = (end == LAST_INDEX) ? 0 : end++;
    }
    void remove_oldest()
    {
       start = (start == LAST_INDEX) ? 0 : start++;    
    }
    void exists(int data)
    {
       // search through with code to jump around the end if needed
    }
    

    start 总是指向第一项 end 总是指向最近的项目 列表可能会覆盖数组的末尾

    搜索 n 登录 插入 1 删除 1

    通过构建 Bloom 过滤器获得真正的极客标记 http://en.wikipedia.org/wiki/Bloom_filter 不保证 100% 准确,但比任何东西都快。

    【讨论】:

    • Exists 耗时太长。它可以在 O(1) 而不是 O(nlogn) 中完成
    • 似乎存在这种情况需要 O(n) - 我错过了什么吗?他的描述只是线性搜索……
    【解决方案4】:

    如果要删除最低值,请使用排序列表,如果元素数量过多,请删除最低值。

    如果要删除最旧的值,请使用集合和队列。集合和队列都包含每个值的副本。如果值在集合中,则无操作。如果该值不在集合中,则将该值附加到队列中并将其添加到集合中。如果您超出了您的大小,请弹出队列并从集合中删除该值。

    如果您需要将重复的值移到队列的后面,您需要从一个集合切换到一个哈希表,将值映射到稳定的迭代器到队列中,并能够从队列的中间移除。

    或者,您可以使用排序列表和哈希表。您可以将 (id, value) 成对放入,然后将哈希表从 value 映射到 (id, value),而不是仅仅将您的值放入排序列表中。 id 只会在每次插入后递增。当您在哈希表中找到匹配项时,您从列表中删除该 (id, value) 并在列表末尾添加一个新的 (id, value) 对。否则,您只需添加到列表的末尾,如果它太长,则从开头弹出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-10
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-22
      • 2014-01-16
      • 2018-10-12
      相关资源
      最近更新 更多