一:
1.优先级队列定义:
优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有
(1)查找
(2)插入一个新元素
(3)删除 一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。
2.最小堆:
最小堆,是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于其左子节点和右子节点的值。
堆存储在下标从0开始计数的数组中,因此,在堆中给定下标为i的结点时:
1 .如果 i = 0,结点 i 是根结点,无父结点;否则结点 i 的父结点为结点 [(i - 2) / 2]
2. 如果 2i + 1 > n - 1,则结点 i 无左子女;否则结点 i 的左子女为结点 2i + 1
3. 如果 2i + 2 > n - 1,则结点 i 无右结点;否则结点 i 的右子女为结点 2i + 2
二:
最小堆的实现:
第一步:利用给定的数组大小和数组元素,创建堆空间,并进行拷贝。
第二步:调整成为最小堆
利用自定义的filterdown()
函数,实现下滑调整:
设置初值currentPos指向最后一个非叶子节点
1. 从currentPos节点开始向下调整到最后一个节点size-1,执行 步骤2
2. currentPos = currentPos-1,如果 currentPos >= 0 执行步骤1,(所有的非叶子节点都遍历一遍);
template <typename T>
bool MinHeap<T>::createMinHeap(T *a,int length){
if(length > capacity)
return false;
for(int i = 0; i < length;i++)
heap[i] = a[i];
size = length;
int currentPos = (size-2)/2; //从最后一个非叶子结点开始向下调整
while(currentPos >= 0){ //一直到头节点
filterdown(currentPos,size-1);
currentPos--;
}
return true;
}
三:
利用最小堆实现优先级队列有两个重要的函数:
filterup(int index):对这个堆从第index个结点向上调整到头节点
template <typename T>
void MinHeap<T>::filterup(int start){
int j = start;
if(j == 0)
return;
int i = (start-1)/2; //i是start的父亲节点
T temp = heap[start];
while( j > 0){
if(heap[i]>= temp){ //如果父亲节点大于temp
heap[j] = heap[i]; //子节点就要等于父亲节点,父亲节点现在默认为temp
j = i; //父亲结点现在是子节点
i = (i-1)/2; //父亲结点的父亲节点
}else
break; //如果找到一个父亲结点小于temp,就不需要在向上调整了,可以保证上边的节点都 小于temp
}
heap[j] = temp; //如果向上调整,找到一个小于heap[start]的结点,那么调整就可以结束了
//结点j最终等于temp
}
filterdown(int start,int end) :对这个堆从第start个结点开始向下调整到end个结点
template<typename T>
void MinHeap<T>::filterdown(int start,int end){
int i = start;
int j = i*2 + 1; //i的左儿子
int temp = heap[i];
if(j > size-1)
return;
while( i <= end){
if(j > size-1)
break;
if(j + 1 <=size-1 && heap[j] > heap[j+1]) //如果右儿子比左儿子小,j表示右儿子
j++; //j表示两个儿子中最小的儿子
if(temp < heap[j]) //如果temp比最小的儿子还小,就不需要调整了
break;
else{ //如果temp比最小的儿子大
heap[i] = heap[j]; //交换i和j ,heap[j]现在默认等于temp,所以还没有赋值
i = j;
j = 2*i+1;
}
}
heap[i] = temp;
}
四:
最小堆实现优先级队列
插入操作:
1.将size = size + 1
2.将插入的节点放最小堆的末尾
3.向上调整到头节点
删除操作:
1.找到删除节点的坐标
2.将要删除的节点与堆最后一个节点交换,size = size - 1;
3.从删除节点开始向下调整到最后一个节点size-1;
完整的程序如下:
#include <iostream>
#include <algorithm>
using namespace std;
template <typename T>
class MinHeap{
public:
MinHeap(int cap);
bool insert(T value);
bool remove(T value);
void print();
bool createMinHeap(T *a,int length);
T getTop();
void filterup(int index);
void filterdown(int start,int end);
int size;
private:
int capacity;
T *heap;
};
template <typename T>
MinHeap<T>::MinHeap(int cap):capacity(cap),size(0),heap(NULL){
heap = new T[capacity];
};
template <typename T>
T MinHeap<T>::getTop(){
if(size != 0)
return heap[0];
return 0;
}
template <typename T>
void MinHeap<T>::print(){
for(int i = 0; i < size;i++){
cout<<heap[i];
if(i == size-1)
cout<<endl;
else
cout<<" ";
}
}
template <typename T>
bool MinHeap<T>::createMinHeap(T *a,int length){
if(length > capacity)
return false;
for(int i = 0; i < length;i++)
heap[i] = a[i];
size = length;
int currentPos = (size-2)/2;
while(currentPos >= 0){
filterdown(currentPos,size-1);
currentPos--;
}
return true;
}
template <typename T>
void MinHeap<T>::filterup(int start){
int j = start;
if(j == 0)
return;
int i = (start-1)/2;
T temp = heap[start];
while( j > 0){
if(heap[i]>= temp){
heap[j] = heap[i];
j = i;
i = (i-1)/2;
}else
break;
}
heap[j] = temp;
}
template<typename T>
void MinHeap<T>::filterdown(int start,int end){
int i = start;
int j = i*2 + 1;
int temp = heap[i];
if(j > size-1)
return;
while( i <= end){
if(j > size-1)
break;
if(j + 1 <=size-1 && heap[j] > heap[j+1])
j++;
if(temp < heap[j])
break;
else{
heap[i] = heap[j];
i = j;
j = 2*i+1;
}
}
heap[i] = temp;
}
template <typename T>
bool MinHeap<T>::remove(T value){ //删除节点
bool judge = false;
for(int i = 0; i < size;i++){
if(heap[i] == value){
heap[i] = heap[size-1];
size--;
filterdown(i,size);
judge = true;
}
}
return judge;
}
template <typename T>
bool MinHeap<T>::insert(T value){ //插入节点
if(size == capacity){
cout<<"Heap full"<<endl;
return false;
}
heap[size] = value;
filterup(size);
size++;
return true;
}
int main(){
MinHeap<int>heap(100);
int arr[10] = { 2,1,3,14,7,5,6,9,8,0};
heap.createMinHeap(arr,10);
heap.print();
heap.insert(1);heap.print();
heap.remove(3);heap.print();
}