本文的優先隊列採用的以最大堆爲例實現的,實現語言爲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實現