索引優先隊列

本文的優先隊列採用的以最大堆爲例實現的,實現語言爲C++

頭文件

#ifndef PRIORITYQUEUE_H_
#define PRIORITYQUEUE_H_

#include <vector>
#include <cassert>
#include <iostream>
using std::cerr;
using std::endl;
using std::vector;
typedef int Key;

//NOTE:堆的最大元素在pq[1]上面,出於對錶示的方便考慮  這個不帶索引的優先隊列
class maxHeap
{
public:
    maxHeap():sz(0){ }
    maxHeap(int maxN) :sz(0)
    {
        assert(0 <= maxN);
        pq.resize(maxN + 1);
    }
    maxHeap(vector<Key>& a);
    void insert(Key v);
    Key max()const
    {
        return pq[1];
    }
    Key delMax();
    bool isEmpty()const
    {
        return 0 == sz;
    }
    int size()const
    {
        return sz;
    }

private:
    //交換pq[i]與pq[j]
    void exch(int i, int j)
    {
        Key t = pq[i];
        pq[i] = pq[j];
        pq[j] = t;
    }
    bool less(int i, int j)
    {
        return pq[i] < pq[j];
    }
    void swim(int k);
    void sink(int k);
    //pq[] : binary heap using 1-based indexing
    vector<Key> pq;
    int sz;
};

typedef int Index;
//NOTE:堆的最大元素在pq[1]上面,出於對錶示的方便考慮  這個不帶索引的優先隊列
class indexMaxHeap
{
public:
    indexMaxHeap():sz(0)
    {
    }
    indexMaxHeap(int maxN):sz(0)
    {
        assert(0 <= maxN);
        pq.resize(maxN + 1);
        idx2Priority.resize(maxN + 1, -1);
        element.resize(maxN + 1);
    }
    int maxIndex()const
    {
        return pq[1];
    }
    Key maxKey()const
    {
        return element[pq[1]];
    }
    bool isEmpty()const
    {
        return 0 == sz;
    }
    Key keyOf(int i)const
    {
        return element[i];
    }
    //返回的是優先隊列的大小
    int size()const
    {
        return sz;
    }
    bool contains(int i)
    {
        return -1 != idx2Priority[i];
    }
    //這裏面的i用來定位element[i]
    void insert(int i, Key key);
    void changeKey(int i, Key key);
    void increaseKey(int i, Key key);
    void decreaseKey(int i, Key key);
    int delMax();
    void deleteElem(int i);
private:
    /***************************************************************************
    * General helper functions.
    ***************************************************************************/
    //交換pq[i]與pq[j]
    void exch(int i, int j)
    {
        int tmp = pq[i];
        pq[i] = pq[j];
        pq[j] = tmp;
        idx2Priority[pq[i]] = i;
        idx2Priority[pq[j]] = j;
    }
    bool less(int i, int j)
    {
        return element[pq[i]] < element[pq[j]];
    }
    void swim(int k);
    void sink(int k);
    vector<Index> pq;
    // inverse of pq - idx2Priority[pq[i]] = pq[idx2Priority[i]] = i
    vector<Index> idx2Priority;
    vector<Key> element;
    int sz;
};

#endif

實現文件

#include "01PriorityQueue.h"

//------------------ maxHeap ---------------------------
maxHeap::maxHeap(vector<Key>& a)
{
    for(auto x : a)
    {
        insert(x);
    }
}

void maxHeap::swim(int k)
{
    while(1 < k&&less(k / 2, k))
    {
        exch(k / 2, k);
        k = k / 2;
    }
}

void maxHeap::sink(int k)
{
    while(2 * k <= sz)
    {
        int j = 2 * k;
        if(j < sz&&less(j, j + 1))
        {
            ++j;
        }
        if(false == less(k, j))
        {
            break;
        }
        exch(k, j);
        k = j;
    }
}

void maxHeap::insert(Key v)
{
    ++sz;
    if(sz >= static_cast<int>(pq.size()))
    {
        pq.resize(static_cast<int>(sz*1.5));
    }
    pq[sz] = v;
    swim(sz);
}

Key maxHeap::delMax()
{
    Key max = pq[1];
    exch(1, sz--);
    pq[sz + 1] = Key();
    sink(1);
    return max;
}

//---------------- indexMaxHeap ---------------------
void indexMaxHeap::insert(int i, Key key)
{
    if(contains(i))
    {
        cerr << "A wrong insertion!" << endl;
        exit(0);
    }
    ++sz;
    if(sz >= static_cast<int>(pq.size()))
    {
        pq.resize(static_cast<int>(sz*1.5));
        idx2Priority.resize(static_cast<int>(sz*1.5));
        element.resize(static_cast<int>(sz*1.5));
    }
    pq[sz] = i;
    idx2Priority[i] = sz;
    element[i] = key;
    swim(sz);
}

void indexMaxHeap::changeKey(int i, Key key)
{
    element[i] = key;
    //可能需要上浮
    swim(idx2Priority[i]);
    //也可能需要下沉
    sink(idx2Priority[i]);
}

void indexMaxHeap::increaseKey(int i, Key key)
{
    if(element[i] >= key)
    {
        cerr << "A wrong increase!" << endl;
        exit(0);
    }
    element[i] = key;
    //需要上浮
    swim(idx2Priority[i]);
}

void indexMaxHeap::decreaseKey(int i, Key key)
{
    if(element[i] <= key)
    {
        cerr << "A wrong decrease!" << endl;
        exit(0);
    }
    element[i] = key;
    //需要下沉
    sink(idx2Priority[i]);
}

int indexMaxHeap::delMax()
{
    assert(0 < sz);
    int maxIdx = pq[1];
    exch(1, sz--);
    sink(1);
    //刪除元素
    idx2Priority[maxIdx] = -1;
    element[maxIdx] = Key();
    //刪除索引
    pq[sz + 1] = -1;
    return maxIdx;
}

void indexMaxHeap::deleteElem(int i)
{
    if(!contains(i))
    {
        cerr << "A wrong delete!" << endl;
        exit(0);
    }
    int idx = idx2Priority[i];
    exch(idx, sz--);
    swim(idx);
    sink(idx);
}

void indexMaxHeap::swim(int k)
{
    while(1 < k&&less(k / 2, k))
    {
        exch(k / 2, k);
        k = k / 2;
    }
}

void indexMaxHeap::sink(int k)
{
    while(2 * k <= sz)
    {
        int j = 2 * k;
        if(j < sz&&less(j, j + 1))
        {
            ++j;
        }
        if(false == less(k, j))
        {
            break;
        }
        exch(k, j);
        k = j;
    }
}

測試文件

/*
 * ---------------------------------------------------
 *  Copyright (c) 2017 josan All rights reserved.
 * ---------------------------------------------------
 *
 *               創建者: Josan
 *             創建時間: 2017/9/4 14:02:40
 */
#include <iostream>
#include <vector>
#include <string>
#include "01PriorityQueue.h"
using namespace std;
int main()
{
    //maxHeap mHeap(10);
    //mHeap.insert(12);
    //mHeap.insert(11);
    //mHeap.insert(123);
    //int res = mHeap.delMax();

    vector<int> ivec{41, 67, 34, 0, 69, 24, 78, 58, 62, 64};
    /*for(auto& x : ivec)
    {
        x = rand() % 100;
        cout << x << "   ";
    }*/
    indexMaxHeap idxHeap(10);

    for(int i = 0; i < 10; ++i)
    {
        idxHeap.insert(i, ivec[i]);
        if(7 == i)
        {
            idxHeap.changeKey(i, 120);
        }
        else if(i % 5 == 0)
        {
            idxHeap.increaseKey(i, ivec[i] + 10);
        }
        else if(i % 9 == 0)
        {
            idxHeap.decreaseKey(i, ivec[i] - 10);
        }
    }

    while(!idxHeap.isEmpty())
    {
        Key key = idxHeap.maxKey();
        int i = idxHeap.delMax();
        cout << i << ": " << key << endl;
    }

    return 0;
}

運行結果

只以索引隊列爲例,

- 建堆之前

idxHeap

索引 0 1 2 3 4 5 6 7 8 9 10
pq 0 0 0 0 0 0 0 0 0 0 0
idx2Priority -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
element 0 0 0 0 0 0 0 0 0 0 0

sz = 0

- 建堆之後

idxHeap

索引 0 1 2 3 4 5 6 7 8 9 10
pq 0 7 6 4 1 9 5 2 3 8 0
idx2Priority 10 4 7 8 3 6 2 1 9 5 -1
element 51 67 34 0 69 34 78 120 62 54 0

sz: 10

- 輸出之後

idxHeap

索引 0 1 2 3 4 5 6 7 8 9 10
pq 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
idx2Priority -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
element 0 0 0 0 0 0 0 0 0 0 0

sz: 0

參考資料

《算法4》源碼JAVA實現

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章