夜深人静写算法——最小堆实现优先级队列

一:

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();
}



 

猜你喜欢

转载自blog.csdn.net/curtern/article/details/84566692
今日推荐