我有一小组整数(大范围)。我需要能够在0(1)处查询此数据结构,并说明集合中是否存在整数。我目前正在使用Java& Colt OpenIntIntHashMap。 我有很多这些OpenIntIntHashMaps数据结构,每个包含5-15个整数。我大量查询。我只关心整数的存在 - 我不关心存储键的值。还有其他代表或更快的东西来帮助解决这个问题吗?
答案 0 :(得分:4)
我担心我不是专家,但我认为很难实现真正的O(1)查找。但是,您可能希望查看某种完美的散列。如果这些集合较小,那么您可能有机会为它们生成“完美”散列函数 - 即它在集合中的项目之间不会发生冲突。这应该允许你进行O(1)查找 - 你取整数,哈希它,哈希将你带到一个地方,然后你做一个比较来检查整数是在集合内还是外面。您只需要检查一次,因为与不完美的哈希不同,没有冲突(在集合中的任何内容之间,内部和外部的事物可能会发生冲突),因此您只需要检查表中的一个单元格以查看是否存在整数集合。这应该是O(1)查找,但是计算这样的散列函数的成本可能很高,并且散列函数本身可能比通用散列函数昂贵得多(尽管仍然是O(1))。我根本没有在Java中使用它们的经验,但JPerf似乎有方法为任何类型的Java对象生成它们,我想你可以修改它以专门化为原始的int(JPerf是GPLv2)。
http://www.anarres.org/projects/jperf/
http://en.wikipedia.org/wiki/Hash_function#Minimal_perfect_hashing
答案 1 :(得分:2)
有10个数字,哈希集和树集大致相同 - 在我的旧机器上大约10 ^ 7。
import java.util.*;
public class Main {
int n = 10;
Random random = new Random();
Set<Integer> hashSet = new HashSet<Integer>(n);
Set<Integer> treeSet = new HashSet<Integer>(n);
{
List<Integer> numbers = new LinkedList<Integer>();
for (int i = 0; i < n; i++)
numbers.add(random.nextInt());
System.out.println(numbers);
hashSet.addAll(numbers);
treeSet.addAll(numbers);
System.out.println(numbers);
}
int hits, misses;
void init() {
}
long time(Set<Integer> set, int n) {
long t0 = System.currentTimeMillis();
for (int i = 0; i < n; i++)
if (set.contains(random.nextInt())) hits++;
else
misses++;
return System.currentTimeMillis() - t0;
}
void print(long dt, int n, String set) {
System.out.println(set + " " + n + " trials in " + dt + " ms. = " + 1000. * n / dt + "trials/sec.");
}
public static void main(String[] args) {
int trials = 10000000;
long dt=0;
for (int i = 0; i < 10; i++) {
Main main = new Main();
dt = main.time(main.hashSet, trials);
main.print(dt, trials, "hashSet");
dt = main.time(main.treeSet, trials);
main.print(dt, trials, "treeSet");
}
}
}
答案 2 :(得分:1)
如此小的“n”,我不会根据结构的复杂性做出决定;我会介绍一下,看看实际上最快的是什么。
Ο(log(n))算法可以比Ο(1)算法快,直到某个n值。 Ο符号只是告诉你算法如何缩放。事实上,如果你有很多这些地图,你可能会更担心空间效率。