簡體   English   中英

排序哈希表(map,dictionary)數據結構設計

[英]Sorted hash table (map, dictionary) data structure design

這是數據結構的描述:

它的操作類似於帶有getputremove方法的常規映射,但是有一個sort方法可以調用它來對地圖進行排序。 但是,映射會記住它的排序結構,因此后續的sort調用可以更快(如果結構在調用sort之間沒有太大的變化)。

例如:

  • 我將put方法稱為1,000,000次。
  • 我稱之為sort方法。
  • 我多次調用put方法100。
  • 我稱之為sort方法。

我第二次調用sort方法應該是一個更快的操作,因為map的結構沒有太大變化。 請注意,地圖不必保持呼叫之間的排序順序sort

我知道這可能不可能,但我希望O(1) getputremove操作。 TreeMap這樣的東西為這些操作提供了保證的O(log(n))時間成本,但始終保持排序順序(沒有sort方法)。

那么這個數據結構的設計是什么?

編輯1 - 返回前K個條目

雖然我很高興聽到上面一般情況的答案,但我的用例更加具體:我不需要對整個事情進行排序; 只是頂部的K元素。

用於有效返回哈希表的前K個條目的數據結構(地圖,字典)

謝謝!

對於“O(1)獲取,放置和刪除操作”,你基本上需要O(1)查找,這意味着一個哈希函數(如你所知),但是一個好的哈希函數的要求經常打破要求,以便輕松排序。 (如果你有一個哈希表,其中相鄰的值映射到同一個桶,它會在許多常見數據上退化為O(N),這是一個更糟糕的情況,你通常希望哈希函數避免。)

我可以想到如何讓你90%的方式。 在排序的並行索引旁邊設置哈希表。 索引有一個干凈的部分(有序)和一個臟部分(無序)。 索引會將鍵映射到值(或對哈希表中存儲的值的引用 - 在性能或內存使用方面適合您)。 添加到哈希表時,新條目將被推送到臟列表的后面。 從哈希表中刪除時,該條目將從索引的干凈和臟的部分中刪除/刪除。 您可以對索引進行排序,該索引僅對臟條目進行排序,然后將它們合並到索引的已排序的“干凈”部分中。 顯然你可以迭代索引。

據我所知,除了remove操作之外,這給你O(1),並且使用標准容器(至少由C ++,Java或Python提供)仍然相當簡單。 它還為您提供了“第二種更便宜”的條件,只需要對臟索引條目進行排序,然后讓您進行O(N)合並。 所有這些的成本顯然是索引的額外內存和使用它時的額外間接。

為什么你需要一個sort()函數?
您可能想要和需要的是紅黑樹。

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

這些樹通過您給出的比較器自動對輸入進行排序。 它們很復雜,但具有優異的O(n)特性。 將您的樹條目作為關鍵字與哈希映射作為字典,您將獲得您的數據結構。

在Java中,它作為TreeMap實現為SortedMap的實例。

我不知道是否有名稱,但您可以將每個項目的當前索引存儲在哈希中。

也就是說,您有一個HashMap< Object, Pair( Integer, Object ) >和一個List<Object>對象

put ,添加到列表的尾部或頭部,並使用您的數據和插入索引插入到散列映射中。 這是O(1)

當你get ,從hashmap中拉出並忽略索引。 這是O(1)

remove ,從地圖中拉出。 獲取索引並從列表中刪除。 這是O(1)

sort ,只需對列表進行排序。 在排序期間更新映射中的索引,或在排序完成后更新。 這不會影響O(nlgn)排序,因為它是線性步驟。 O(nlgn + n) == O(nlgn)

有序字典

最新版本的Python(2.7,3.1)有“有序詞典”,聽起來就像你所描述的那樣。

官方Python“有序字典”實現的靈感來自之前的第三方實現,如PEP 372中所述

參考文獻:

你正在看的是一個哈希表,在排序順序的下一個條目的條目中有指針。 它與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());
        }

    }

}

我不知道具有該確切行為的數據結構分類,至少在Java Collections(或非線性數據結構類)中沒有。 也許你可以實現它,從此它將被稱為RudigerMap

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM