priority queue with limited space: looking for a good algorithm

后端 未结 8 1625
旧巷少年郎
旧巷少年郎 2020-12-06 02:07

This is not a homework.

I\'m using a small \"priority queue\" (implemented as array at the moment) for storing last N items with smallest value. This is a b

相关标签:
8条回答
  • 2020-12-06 02:46

    If amount of priorities is small and fixed than you can use ring-buffer for each priority. That will lead to waste of the space if objects is big, but if their size is comparable with pointer/index than variants with storing additional pointers in objects may increase size of array in the same way.
    Or you can use simple single-linked list inside array and store 2*M+1 pointers/indexes, one will point to first free node and other pairs will point to head and tail of each priority. In that cases you'll have to compare in avg. O(M) before taking out next node with O(1). And insertion will take O(1).

    0 讨论(0)
  • 2020-12-06 02:47

    Found a solution ("difference" means "priority" in the code, and maxRememberedResults is 255 (could be any (2^n - 1)):

    template <typename T> inline void swap(T& a, T& b){
        T c = a;
        a = b;
        b = c;
    }
    
    
    struct MinDifferenceArray{
        enum{maxSize = maxRememberedResults};
        int size;
        DifferenceData data[maxSize];
        void add(const DifferenceData& val){
            if (size >= maxSize){
                if(data[0].difference <= val.difference)
                    return;
    
                data[0] = val;
    
                for (int i = 0; (2*i+1) < maxSize; ){
                    int next = 2*i + 1;
                    if (data[next].difference < data[next+1].difference)
                        next++;
                    if (data[i].difference < data[next].difference)
                        swap(data[i], data[next]);
                    else
                        break;
                    i = next;
                }
            }
            else{
                data[size++] = val;
                for (int i = size - 1; i > 0;){
                    int parent = (i-1)/2;
                    if (data[parent].difference < data[i].difference){
                        swap(data[parent], data[i]);
                        i = parent;
                    }
                    else
                        break;
                }
            }
        }
    
        void clear(){
            size = 0;
        }
    
        MinDifferenceArray()
            :size(0){
        }
    };
    
    1. build max-based queue (root is largest)
    2. until it is full, fill up normally
    3. when it is full, for every new element
      1. Check if new element is smaller than root.
      2. if it is larger or equal than root, reject.
      3. otherwise, replace root with new element and perform normal heap "sift-down".

    And we get O(log(N)) insert as a worst case scenario.

    It is the same solution as the one provided by user with nickname "Moron". Thanks to everyone for replies.

    P.S. Apparently programming without sleeping enough wasn't a good idea.

    0 讨论(0)
提交回复
热议问题