本文轉自:《C++程序設計》 Y. Daniel Liang著 王剛,劉曉光,劉璟 譯, 機械工業出版社
簡單介紹堆的概念:堆,實際上就是一顆完全二叉樹,它的每個節點的值都大於等於其任何孩子節點的值。
堆是二叉樹,因此可用二叉樹的結構描述,但是,如果堆的大小預先可知的話,更爲有效的描述方法是使用向量或數組。下面的代碼使用的向量來描述的,操作比較簡單。
堆的刪除操作步驟:
1、將最後一個節點移至根節點,代替根;
2、令根爲當前結點;
3、while(當前節點有孩子節點,且當前節點小於其中的某個孩子節點){
將當前節點與最大的孩子節點交換;
令當前節點爲與與之交換的孩子節點;
}
堆的插入操作步驟:
1、將待插入節點,插入到堆的末尾;
2、令最後一個節點(新節點)爲當前節點;
3、while(當前節點大於其父節點){
將當前節點與其父節點交換;
當前節點變爲爲父節點;
}
代碼實現:
#include<iostream>
#include<string>
#include<vector>
#include<stdexcept>
using namespace std;
template<typename T=int>
class Heap{
public:
Heap(){};
Heap(T elements[], int arraySize){
for(int i=0; i<arraySize; i++){
add(elements[i]);
}
}
T remove() throw (runtime_error){
if(v.size()==0){
throw runtime_error("Heap is empty");
}
T removedElement = v[0];
v[0] = v[v.size()-1];
v.pop_back();//remove root
int currentIndex = 0;
while(currentIndex < v.size()){
int leftChildIndex = currentIndex * 2 + 1;
int rightChildIndex = currentIndex * 2 + 2;
if(leftChildIndex >= v.size()){
break;
}
int maxIndex = leftChildIndex;
if(rightChildIndex < v.size()){
if(v[maxIndex] < v[rightChildIndex]){
maxIndex = rightChildIndex;
}
}
if(v[currentIndex] < v[maxIndex]){
T temp = v[maxIndex];
v[maxIndex] = v[currentIndex];
v[currentIndex] = temp;
currentIndex = maxIndex;
}
else{
break;
}
}
return removedElement;
}
void add(T element){
v.push_back(element);
int currentIndex = v.size() - 1;
while(currentIndex > 0){
int parentIndex = (currentIndex-1) / 2;
if(v[currentIndex] > v[parentIndex]){
T temp = v[currentIndex];
v[currentIndex] = v[parentIndex];
v[parentIndex] = temp;
currentIndex = parentIndex;
}
else{
break;
}
}
}
int getSize(){
return v.size();
}
private:
vector<T> v;
};
template<typename T=int>
class PriorityQueue{
public:
PriorityQueue(){}
void enqueue(T element){
heap.add(element);
}
T dequeue() throw(runtime_error){
return heap.remove();
}
int getSize(){
return heap.getSize();
}
private:
Heap<T> heap;
};
class Patient{
public:
Patient(string name, int priority){
this->name = name;
this->priority = priority;
}
bool operator<(Patient &secondPatient){
return (this->priority < secondPatient.priority);
}
bool operator>(Patient &secondPatient){
return (this->priority > secondPatient.priority);
}
string getName(){
return this->name;
}
int getPriority(){
return this->priority;
}
private:
string name;
int priority;
};
int main(){
PriorityQueue<Patient> patientQueue;
patientQueue.enqueue(Patient("John", 2));
patientQueue.enqueue(Patient("Jim", 1));
patientQueue.enqueue(Patient("Tim", 5));
patientQueue.enqueue(Patient("Cindy", 7));
while(patientQueue.getSize() > 0){
Patient element = patientQueue.dequeue();
cout << element.getName() << " (priority: " <<
element.getPriority() << " )";
}
return 0;
}