堆叠和哈希关节

时间:2010-05-07 10:59:06

标签: java algorithm hash stack

我正在尝试编写一个数据结构,它是Stack和HashSet的组合,具有快速推送/弹出/成员资格(我正在寻找恒定时间操作)。想想Python的OrderedDict。

我尝试了一些事情,然后我想出了以下代码:HashIntSetInt。我需要在源代码中添加一些文档,但基本上我使用线性探测的哈希来将索引存储在键的向量中。由于线性探测始终将最后一个元素放在已填充单元格的连续范围的末尾,因此无需复杂的删除操作即可轻松实现pop()。

我有以下问题:

  • 数据结构消耗大量内存(显然有些改进:stackKeys大于需要)。
  • 某些操作比我使用fastutil(例如:pop(),甚至在某些情况下使用push())慢。我尝试使用fastutil和trove4j重写类,但我的应用程序的整体速度减半。

您对我的代码有什么性能改进建议? 您知道我可以尝试哪些开源库/代码?

3 个答案:

答案 0 :(得分:1)

我认为你想要的东西(几乎)已经在库中可用:LinkedHashSet是一个带有底层双向链表的哈希集(这使得它可以迭代)。 LinkedHashMap甚至有一个removeEldestEntry,听起来与pop方法非常相似。

天真解决方案的表现如何:

class HashStack<T> {

    private HashMap<T, Integer> counts = new HashMap<T, Integer>();
    private Stack<T> stack = new Stack<T>();

    public void push(T t) {
        stack.push(t);
        counts.put(t, 1 + getCount(t));
    }

    public T pop() {
        T t = stack.pop();
        counts.put(t, counts.get(t) - 1);
        return t;
    }

    private int getCount(T t) {
        return counts.containsKey(t) ? counts.get(t) : 0;
    }

    public boolean contains(T t) {
        return getCount(t) > 0;
    }

    public String toString() {
        return stack.toString();
    }
}

答案 1 :(得分:1)

你已经有了很好的实现。对我来说唯一明显的改进是,你在弹出时搜索比你需要的更多的工作。您应该在堆栈中存储而不是密钥本身,而是将索引存储到密钥数组中。当你想要查看最后一个项目时,这会给你一些快速的弹出,只花费一个指针间接。

除了这个之外,只需将堆栈大小调整为LOAD_FACTOR *(堆数组大小),并且您应该拥有尽可能快的实现,因为您可以根据速度要求管理尽可能少的内存。

答案 2 :(得分:0)

我建议使用TreeSet<T>,因为它为添加,删除和包含提供了保证的O(log n)成本。