最好的算法从随机ID中检索元素

时间:2014-06-16 12:07:00

标签: c algorithm data-structures

我目前正在尝试找到适合我案例的最佳数据结构/算法:

我收到单个唯一的随机ID(uint32_t),并创建一个与每个新ID相关联的元素。

  1. 我需要从id中检索元素。

  2. 我还需要按照创建顺序从任何元素(甚至id)访问下一个和前一个元素。创建的顺序主要取决于当前的元素,它总是可以放在一边,所以新元素应该是它的下一个元素。

  3. 以下是一个例子:

    (12) <-> (5) <-> (8) <-> (1)
     ^                        ^
     '------------------------'
    

    如果我假设当前元素为(8)并且创建了一个新元素(3),它应该如下所示:

    (12) <-> (5) <-> (8) <-> (3) <-> (1)
     ^                                ^
     '--------------------------------'
    

    要考虑的重要事项是插入,删除和搜索几乎以相同(高)频率发生。不完全确定有多少元素会同时存在,但我会说max~1000。

    知道了所有这些,我考虑使用带有id的AVL作为排序键,同时保留前一个和下一个元素。

    在C语言中,类似这样:

    struct element {
      uint32_t id;
      /* some other fields */
      struct element *prev;
      struct element *next;      
    }
    
    struct node {
       struct element *elt;
       struct node *left;
       struct node *right;
    };
    
    static struct element* current;
    

    另一个想法可能是使用哈希映射,但后来我需要找到正确的哈希函数。不完全确定它在实践中总是胜过AVL这个数量的元素。这取决于哈希函数。

    AVL是个好主意还是我应该考虑其他事情呢?

    谢谢!

    PS:我不是一个试图让你做作业的学生,​​我只是想开发一个简单的窗口管理器(只是为了好玩)。

3 个答案:

答案 0 :(得分:2)

您正在寻找java LinkedHashMap

中所谓的变体

这基本上是hash-table和(双向)linked list组合。

链接列表具有所需顺序的元素。在O(1)中完成在已知位置插入元素(假设您有指向正确位置的指针)。同样适用于删除。链表包含所需顺序的所有元素。

第二个数据结构是哈希映射(或树映射)。此数据结构从密钥(您的唯一ID)映射到链接列表中的POINTER。这样,给定一个id - 你可以快速找到它在链表上的位置,从那里你可以轻松访问下一个和前一个元素。

用于插入的高级伪代码:

insert(x, v, y): //insert key=x value=v, after element with key=y
   if x is in hash-table:
        abort
   p = find(hash-table,y) //p is a pointer
   insert_to_list_after(x,v,p) //insert key=x,value=v right after p
   add(hash-table,x,p) //add x to the hash-table, and make it point to p.

用于搜索的高级伪代码:

search(x):
    if x is not in hash-table:
        abort
    p = find(hash-table,x)
    return p->value;

删除应该与插入非常相似(并且同时复杂)。

请注意,找到x之后的元素

也相当容易
p = find(hash-table,x)
if (p != NULL && p->next != NULL):
    return p->next->value

答案 1 :(得分:0)

我的建议是你使用两种数据结构的组合 - 按照插入顺序存储元素的列表和用于在id和list节点之间实现关联数组(map)的哈希映射或二进制搜索树。您将使用关联数组执行搜索,并且可以使用列表访问相邻元素。删除也相对容易,但您需要从两个结构中删除。

如果使用二叉搜索树,则查找/插入/删除的复杂性将为log(n),如果使用哈希表,则预期复杂性是常量。

答案 2 :(得分:0)

您一定要考虑Skip List数据结构。

它似乎非常适合您的情况,因为它具有预期的O(log(n))插入/搜索/删除,如果您有指向节点的指针,则可以在O(1)中找到上一个和下一个元素只需移动指针即可。

结论是,如果你刚刚创建了一个节点,你有一个指向它的指针,你可以在O(1)时间内找到prev / next元素。