简体   繁体   English

C ++优先级字典

[英]C++ priority dictionary

I need a container to store pairs, I have two operations: 我需要一个容器来存储对,我有两个操作:

  1. update value by key 按键更新值
  2. get the key with maximum value. 获得具有最大价值的密钥。

For the first operation, map is a good structure. 对于第一个操作,map是一个很好的结构。 For the second operation, seems priority queue is a good one. 对于第二个操作,似乎优先队列是一个好的队列。 How would you do this? 你会怎么做? Is there anyway to have both of the two operations done without having a O(n) loop? 无论如何在没有O(n)循环的情况下完成两个操作? Thanks. 谢谢。

An asymptotically efficient solution to this would be to use a combination of a hash table and a Fibonacci heap. 对此渐近有效的解决方案是使用散列表和Fibonacci堆的组合。 You would use the hash table to be able to access the value associated with any particular key in O(1) time, and would use the Fibonacci heap to be able to quickly look up the key/value pair with the lowest value (doing so in O(1)). 您可以使用哈希表在O(1)时间内访问与任何特定键相关联的值,并使用Fibonacci堆能够快速查找具有最低值的键/值对(这样做)在O(1))。

If you want to change the value associated with a key, if you are increasing the value, you can do so in (amortized) O(1) time by using the increase-key operation on the Fibonacci heap, which has O(1) amortized time. 如果要更改与键关联的值,如果要增加该值,则可以在(摊销)O(1)时间内使用Fibonacci堆上的增量键操作来执行此操作,该操作具有O(1)摊销时间。 If you are decreasing the value, it will take O(log n) time to delete the element out of the Fibonacci heap and then reinsert it. 如果要减小该值,则需要O(log n)时间从Fibonacci堆中删除该元素,然后重新插入。

Overall, this gives a time complexity of 总的来说,这给出了时间复杂度

  • Insert a new element: O(1) for hash, O(1) for insert into Fibonacci heap: O(1) time . 插入一个新元素:O(1)表示散列,O(1)表示插入Fibonacci堆: O(1)时间
  • Delete an element: O(1) for hash, O(log n) for delete from Fibonacci heap: O(log n) time . 删除元素:O(1)表示散列,O(log n)表示从Fibonacci堆中删除: O(log n)时间
  • Find top element: O(1) for lookup in Fibonacci heap: O(1) time. 查找顶部元素:在Fibonacci堆中查找O(1)O(1)时间。
  • Increase a value: O(1) for hash, O(1) for increase-key: O(1) time. 增加一个值:散列为O(1),增加键为O(1)O(1)时间。
  • Decrease a value: O(1) for hash, O(log n) for delete/insert: O(log n) time. 减小值:散列为O(1),删除/插入为O(log n)O(log n)时间。

Hope this helps! 希望这可以帮助!

Create a heap structure (for the second bullet) and put each of its nodes in a map (for the first bullet). 创建堆结构 (对于第二个项目符号)并将其每个节点放在一个映射中(对于第一个项目符号)。

EDIT: An implementation of min heap I had done some time in the past 编辑:我曾经做过一段时间的min heap的实现

#ifndef MINHEAP_H
#define MINHEAP_H

//////////////////////// MinHeap with Map for Data ////////////////////////

template <class T, class M = int> class MinHeap {
    T*          array;
    unsigned const int  arr_max;
    unsigned int        elements;
    M           map;

    void percolate_down(unsigned int i=0) {
        unsigned int n = elements-1, min;
        do {
            unsigned int l = 2*i + 1, r = 2*i + 2;
            if (l <= n && array[i] > array[l]) min = l;
            else min = i;
            if (r <= n && array[i] > array[r] && array[l] > array[r]) min = r;
            if (i != min) {
                T temp = array[i];
                array[i] = array[min];
                array[min] = temp;
                map.update(array[i], i);
                map.update(array[min], min);
                i = min;
            } else break;
        } while (i < n);
    }
    void percolate_up(unsigned int i) {
        while (i && array[(i-1)/2] > array[i]) {
            T temp = array[i];
            array[i] = array[(i-1)/2];
            array[(i-1)/2] = temp;
            map.update(array[i], i);
            map.update(array[(i-1)/2], (i-1)/2);
            i = (i-1)/2;
        }
    }
public:
    MinHeap(const int max) : array(new T[max]), arr_max(max), elements(0), map(max) {}
    ~MinHeap(void) { delete[] array; }

    bool empty(void) const { return elements == 0; }
    unsigned int capacity(void) const { return arr_max; }
    unsigned int size(void) const { return elements; }
    const M& heapmap(void) const { return map; }
    const T& peek(unsigned int i=0) const { return array[i]; }

    bool insert(T& element) {
        if (arr_max == elements) return false;

        unsigned int k = elements++;
        map.update(element, k);
        array[k] = element;
        percolate_up(k);
        return true;
    }
    unsigned int mass_insert(T copy[], unsigned int n) {
        unsigned int i = 0;     
        for( ; i < n ; i++) if (!insert(copy[i])) break;
        return i;
    }
    bool delete_min(void) {
        if (elements == 0) return false;

        map.update(array[0], arr_max+1);
        array[0] = array[--elements];
        map.update(array[0], 0);
        percolate_down();
        return true;
    }
    bool delete_element(unsigned int i) {
        if (i > elements) return false;

        map.update(array[i], arr_max+1);
        T temp = array[i];      
        array[i] = array[--elements];
        map.update(array[i], i);
        if (array[i] > temp) percolate_down(i);
        else if (temp > array[i]) percolate_up(i);
        return true;
    }
    bool update(unsigned int i, T& element) {
        if (i > elements) return false;

        map.update(array[i], arr_max+1);
        T temp = array[i];      
        array[i] = element;
        map.update(array[i], i);
        if (array[i] > temp) percolate_down(i);
        else if (temp > array[i]) percolate_up(i);
        return true;
    }

//  void print() { using namespace std; for (unsigned int i=0 ; i < elements ; i++) cout << array[i] << " | "; cout << endl; }


    // Iterators
/*
    friend class Const_Iterator;

    class Const_Iterator {
        MinHeap<T>* heap;
        unsigned int    index;
        Const_Iterator(MinHeap<T>* h, unsigned int i) : heap(h), index(i) {}
    public:
        Const_Iterator(const Const_Iterator& clone) : heap(clone.heap), index(clone.index) {}

        friend Const_Iterator MinHeap<T>::begin(void);
    };

    Const_Iterator begin(void) { return Const_Iterator(this, 0); }
*/
};

//////////////////////////////////////////////////////////////////////////////


//////////////////////// MinHeap without Map for Data ////////////////////////

template <class T> class MinHeap <T, int> {
    T*          array;
    unsigned const int  arr_max;
    unsigned int        elements;

    void percolate_down(unsigned int i=0) {
        unsigned int n = elements-1, min;
        do {
            unsigned int l = 2*i + 1, r = 2*i + 2;
            if (l <= n && array[i] > array[l]) min = l;
            else min = i;
            if (r <= n && array[i] > array[r] && array[l] > array[r]) min = r;
            if (i != min) {
                T temp = array[i];
                array[i] = array[min];
                array[min] = temp;
                i = min;
            } else break;
        } while (i < n);
    }
    void percolate_up(unsigned int i) {
        while (i && array[(i-1)/2] > array[i]) {
            T temp = array[i];
            array[i] = array[(i-1)/2];
            array[(i-1)/2] = temp;
            i = (i-1)/2;
        }
    }
public:
    MinHeap(const int max) : array(new T[max]), arr_max(max), elements(0) {}
    ~MinHeap(void) { delete[] array; }

    bool empty(void) const { return elements == 0; }
    unsigned int capacity(void) const { return arr_max; }
    unsigned int size(void) const { return elements; }
    const T& peek(unsigned int i=0) const { return array[i]; }

    bool insert(T& element) {
        if (arr_max == elements) return false;

        unsigned int k = elements++;
        array[k] = element;
        percolate_up(k);
        return true;
    }
    unsigned int mass_insert(T copy[], unsigned int n) {
        unsigned int i = 0;     
        for( ; i < n ; i++) if (!insert(copy[i])) break;
        return i;
    }
    bool delete_min(void) {
        if (elements == 0) return false;

        array[0] = array[--elements];
        percolate_down();
        return true;
    }
    bool delete_element(unsigned int i) {
        if (i > elements) return false;

        T temp = array[i];      
        array[i] = array[--elements];
        if (array[i] > temp) percolate_down(i);
        else if (temp > array[i]) percolate_up(i);
        return true;
    }
    bool update(unsigned int i, T& element) {
        if (i > elements) return false;

        T temp = array[i];      
        array[i] = element;
        if (array[i] > temp) percolate_down(i);
        else if (temp > array[i]) percolate_up(i);
        return true;
    }

//  void print() { using namespace std; for (unsigned int i=0 ; i < elements ; i++) cout << array[i] << " | "; cout << endl; }
};

//////////////////////////////////////////////////////////////////////////////

#endif // MINHEAP_H

boost :: bimap可以做你想要的,反向映射用于实现#2。

According to my C++0x standard, The fundamental property of iterators of associative containers is that they iterate through the containers in the non-descending order of keys where non-descending is defined by the comparison that was used to construct them. 根据我的C ++ 0x标准, The fundamental property of iterators of associative containers is that they iterate through the containers in the non-descending order of keys where non-descending is defined by the comparison that was used to construct them.

So just use a map. 所以只需使用地图。 Random lookup is O(log(n)), and to get the highest element takes O(1) time. 随机查找是O(log(n)),并且获得最高元素需要O(1)时间。

value getHighest(map<key, value>& map) {
    assert(map.empty() == false);
    return (--map.end())->second;
}

我认为bimap是最好的路线

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM