java - 具有快速查找功能的排序集(与 HashSet 一样快?)

标签 java algorithm data-structures hashmap treemap

我正在寻找某种可以满足这两个要求的集合数据结构:

  1. 已排序
  2. O(1) 查找

这就是我到目前为止所得到的,但我真的希望那里有一个现有的、不那么笨拙的数据结构。

/**
 * This MUST support both 
 * (1) Looking up by A - O(n)
 * (2) Iteration by sorted Foo<A, B>
 */
public class MySet<Foo<A, B>> extends TreeSet<Foo<A, B>>
{ 
    private Map<A, Foo<A, B>> temp = new HashMap<A, Foo<A, B>>();

    public Foo<A, B> getNode(A a)
    {
       return temp.get(a);
    }

    @Override
    public boolean add(Foo<A, B> foo)
    {
       temp.put(foo.getA(), foo);
       return super.add(foo);
    }
}

我的 Foo 类如下所示:

public class Foo<A, B>
{
    private A a; //Can NEVER be null
    private B b; //Can NEVER be null

    //... constructor and stuff omitted 

    public int compareTo(Foo<A, B> that)
    {
        if (this.equals(that))
           return 0;

        //Compare by a first
        int ret = this.a.compareTo(that);
        if (ret == 0)
            return 0;

        //Compare by b
        return this.b.compareTo(that.b);            
    }

    public boolean equals(Object obj)
    {
        if (!(obj instanceof Foo))
            return false;

        Foo rhs = (Foo) obj;

        return this.a.equals(rhs.a) && this.b.equals(rhs.b);
    }
}

更新:

这是我的集合的一个用例:

MySet<Foo<SomeA, SomeB>> mySet = getTheData(); //getTheData() returns a set with a bunch of Foo objects

SomeA a = getA(); //getA() returns some instance of SomeA that I'm interested in

我希望能够检查集合并检索 Foo 对象(如果存在),这样 Foo.getA() == a;

mySet.getNode(a); 

最佳答案

您可以使用一些额外的空间来获取它。所以你需要一个 HashSet。此外,每个元素将指向排序顺序中的下一个值。假设您有键 1、3、5、10,并且您正在使用线性探测。

value array   =  [3, 5, null, null, 10,   1];
pointer array =  [1, 4, null, null, null, 0];

因此值数组包含值。哈希函数决定值的去向。因此在上面的示例中,h(1) = 5(1 转到索引 5)、h(3) = 0、h(5) = 1 和 h(10) = 4。索引 2、3 具有空值( future 元素的开放空间)。指针数组表示哪个元素在排序顺序中跟在当前元素之后。假设我们正在执行 set.contains(3),它将导致计算 h(3)(将产生 0),并且我们知道该元素存在于集合中。如果我们想要根据排序顺序排列元素集中的下一个元素,我们会查看指针数组中的值。因此,对于值 3(在值数组中的位置 0),我们通过查找指针数组(pointer_array[0],即 1)中的索引,然后查找 value_array 来获取排序顺序中的下一个元素[1], 即 5.

这是一个非常常见的实现。 Java的LinkedHashMap通常用作LRU缓存,实现为 HashMap +键的双向链表。双向链表中的键按访问顺序排列。

在您的情况下,当您插入一个元素时,您需要调整非常慢的指针数组。你必须做一个线性扫描。 如果这不是只读的,您可以使用以下方法

在你的数据结构中,有一个 hashset 和一个 avl 树,一个红黑树或任何其他平衡二叉树。每当您进行 containsKey 测试时,它都是 O(1)。每当您进行枚举时,您都可以使用二叉树按排序顺序在线性时间内遍历它们。每当您插入一个新元素时,您也会将它同时插入到二叉树和 HashSet 中。当你删除时,你从哈希集和二叉树中删除元素。所以删除和插入变为 O(log n)

关于java - 具有快速查找功能的排序集(与 HashSet 一样快?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24922303/

相关文章:

java - 有绘制 B-TREE 的 API 吗?

java - 使用 Retrofit 从服务器接收数据

迭代随机排列的算法

c - 树数据结构(level_order)

java - 如果哈希码被重写以使其仅返回一个常数,Hashmap 键将如何表现?

java - Spring 4 TestNG +@Autowired

java - 如何在霍夫曼编码中使用伸展树(Splay Tree)数据结构进行数据压缩?

python - 对我的数组中的随机数进行排序

java - 如何比较两个泛型类型变量?

java - LinkedList 中的大负整数表示