本文转自:《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;
}