排序哈希表(map,dictionary)数据结构设计

时间:2010-01-05 15:58:21

标签: data-structures map hashtable hashmap sorted

以下是数据结构的描述:

它的运作方式类似于使用getputremove方法的常规地图,但有一个sort方法,可以调用该方法对地图进行排序。但是,地图会记住其排序结构,因此后续调用排序可以更快(如果结构在调用sort之间没有太大变化)。

例如:

  • 我将put方法称为1,000,000次。
  • 我调用sort方法。
  • 我再次拨打put方法100次。
  • 我调用sort方法。

我第二次调用sort方法应该是一个更快的操作,因为地图的结构没有太大变化。请注意,地图不必在调用sort之间保持排序顺序。

我理解这可能不可能,但我希望O(1)getputremove操作。像TreeMap之类的东西为这些操作提供了保证的O(log(n))时间成本,但总是维护一个排序顺序(没有sort方法)。

那么这个数据结构的设计是什么?

编辑1 - 返回前K个条目

虽然我很高兴听到上面一般情况的答案,但我的用例更具体:我不需要对整个事情进行排序;只是前K个元素。

Data structure for efficiently returning the top-K entries of a hash table (map, dictionary)

谢谢!

6 个答案:

答案 0 :(得分:8)

对于“O(1)get,put和remove操作”,你基本上需要O(1)查找,这意味着一个哈希函数(如你所知),但是一个好的哈希函数的要求经常打破要求很容易分类。 (如果你有一个哈希表,其中相邻值映射到同一个桶,它会在许多常见数据上退化为O(N),这是一个更糟糕的情况,你通常希望哈希函数避免。)

我可以想到如何让你90%的方式。在排序的并行索引旁边设置哈希表。索引有一个干净的部分(有序)和一个脏部分(无序)。索引会将键映射到值(或对哈希表中存储的值的引用 - 在性能或内存使用方面适合您)。添加到哈希表时,新条目将被推送到脏列表的后面。从哈希表中删除时,该条目将从索引的干净和脏的部分中删除/删除。您可以对索引进行排序,该索引仅对脏条目进行排序,然后将它们合并到索引的已排序的“干净”部分中。显然你可以迭代索引。

据我所知,除了remove操作之外,这给你O(1),并且使用标准容器(至少由C ++,Java或Python提供)仍然相当简单。它还为您提供了“第二种更便宜”的条件,只需要对脏索引条目进行排序,然后让您进行O(N)合并。所有这些的成本显然是索引的额外内存和使用它时的额外间接。

答案 1 :(得分:4)

为什么你需要一个sort()函数?
您可能想要和需要的是红黑树。

http://en.wikipedia.org/wiki/Red-black_tree

这些树自动通过您给出的比较器对输入进行排序。它们很复杂,但具有优异的O(n)特性。将您的树条目作为密钥与哈希相结合 映射为字典,您就可以获得数据结构。

在Java中,它作为TreeMap实现为SortedMap的实例。

答案 2 :(得分:1)

我不知道是否有名称,但您可以将每个项目的当前索引存储在哈希值上。

也就是说,你有HashMap< Object, Pair( Integer, Object ) >List<Object>个对象

当您put时,添加到列表的尾部或头部,并使用您的数据和插入索引插入到散列图中。这是O(1)

当你get时,从哈希映射中拉出并忽略索引。这是O(1)

当你remove时,你从地图中拉出来。获取索引并从列表中删除。这是O(1)

当您sort时,只需对列表进行排序。在排序期间更新映射中的索引,或在排序完成后更新。这不会影响O(nlgn)排序,因为它是线性步骤。 O(nlgn + n) == O(nlgn)

答案 3 :(得分:1)

有序字典

最新版本的Python(2.7,3.1)有“有序词典”,听起来就像你所描述的那样。

官方Python“有序字典”实现的灵感来自之前的第三方实现,如PEP 372中所述。

参考文献:

答案 4 :(得分:1)

您正在查看的是一个哈希表,在排序顺序的下一个条目的条目中有指针。它与java中的LinkedHashMap非常相似,只是链接跟踪排序顺序而不是插入顺序。实际上,您可以通过包装LinkedHashMap并实现排序将LinkedHashMap中的条目传输到TreeMap然后再返回到LinkedHashMap来实现这一点。

这是一个实现,它对数组列表中的条目进行排序,而不是转移到树映射。我认为Collection.sort使用的排序算法可以很好地将新条目合并到已经排序的部分。

public class SortaSortedMap<K extends Comparable<K>,V> implements Map<K,V> {

    private LinkedHashMap<K,V> innerMap;

    public SortaSortedMap() {
        this.innerMap = new LinkedHashMap<K,V>();
    }

    public SortaSortedMap(Map<K,V> map) {
        this.innerMap = new LinkedHashMap<K,V>(map);
    }

    public Collection<V> values() {
        return innerMap.values();
    }

    public int size() {
        return innerMap.size();
    }

    public V remove(Object key) {
        return innerMap.remove(key);
    }

    public V put(K key, V value) {
        return innerMap.put(key, value);
    }

    public Set<K> keySet() {
        return innerMap.keySet();
    }

    public boolean isEmpty() {
        return innerMap.isEmpty();
    }

    public Set<Entry<K, V>> entrySet() {
        return innerMap.entrySet();
    }

    public boolean containsKey(Object key) {
        return innerMap.containsKey(key);
    }

    public V get(Object key) {
        return innerMap.get(key);
    }

    public boolean containsValue(Object value) {
        return innerMap.containsValue(value);
    }

    public void clear() {
        innerMap.clear();
    }

    public void putAll(Map<? extends K, ? extends V> m) {
        innerMap.putAll(m);
    }

    public void sort() {
        List<Map.Entry<K,V>> entries = new ArrayList<Map.Entry<K,V>>(innerMap.entrySet());
        Collections.sort(entries, new KeyComparator());
        LinkedHashMap<K,V> newMap = new LinkedHashMap<K,V>();
        for (Map.Entry<K,V> e: entries) {
            newMap.put(e.getKey(), e.getValue());
        }
        innerMap = newMap;
    }

    private class KeyComparator implements Comparator<Map.Entry<K,V>> {

        public int compare(Entry<K, V> o1, Entry<K, V> o2) {
            return o1.getKey().compareTo(o2.getKey());
        }

    }

}

答案 5 :(得分:0)

我不知道具有该确切行为的数据结构分类,至少在Java Collections(或非线性数据结构类)中没有。也许你可以实现它,从此它将被称为RudigerMap