堆-优先队列[数组]

堆和优先队列

分大顶堆和小顶堆,这里实现的是小顶堆,也就是说父亲节点一定小于孩子节点,不像二叉排序树这样,堆对子节点之间的大小没有限制,限制的仅仅只有一个条件,父亲一定比孩子节点小,这就是小顶堆,大顶堆则相反

优先队列:堆中的每个元素都带有一个优先级,入队是无序的,出队是有序的,排序过程只需要在每步插入和删除都平衡一下堆就够了,所以有种排序算法叫堆排序

代码实现

结构

这里用数组实现,length代表堆数组的长度,注意这里的树形结构是完全二叉树结构

int Heap[MAX]={0};
int length = 0;	

寻找父亲和孩子节点

这里反回的是节点的索引

int parent(int j){
	if(j>0){
		return (j-1)/2;  //返回当前节点父亲的位置 		
	} 
	return -1;  //返回当前节点父亲的位置 
}

int left(int j){
	return j*2+1;
}
int right(int j){
	return j*2+2;
}

元素上浮

上浮操作发生在插入的时候,因为插入永远都是从尾部插入,为了平衡堆,所以需要将插入的元素 上浮到符合小顶堆的位置

//上浮 
void up(int j){
	if(j>0 && Heap[j]<Heap[parent(j)]){ //如果比父母小 
		swap(Heap[j],Heap[parent(j)]);// 交换 
		up(parent(j)); //递归 
	} 
}

元素下沉

下沉操作发生在删除元素的时候,因为删除元素的逻辑是将堆顶元素和尾部元素替换,注意,堆顶元素永远都是整个堆的最小的元素

那为什么要和尾部元素替换呢?为了方便堆顶元素的移除,尾部元素移除很方便快速

将尾部元素替换到堆顶后,可能会打破平衡,所以需要将刚替换的堆顶元素下沉

//下沉 
void down(int j){
	//堆是一颗完全二叉树 先有左边 再有右边 
	if(has_left(j)){
		int small = left(j);
		if(has_right(j))
			if(Heap[small]>Heap[right(j)])
				small = right(j);
		
			
		if(Heap[small]<Heap[j]){
			swap(Heap[small],Heap[j]);
			down(small); //递归 
		}
	}
} 

添加和删除

//添加 
void add(int val){
	Heap[length++] = val;
	up(length-1); //将新元素上浮	
}

//删除 取堆顶元素 
int remove(){
	
	swap(Heap[0],Heap[length-1]);//先和最后一个换 再删除
	int r = Heap[--length]; //返回结果 
	
	down(0);  //堆顶下沉
	return r; 
} 

取最小值

int get_min(){
	if(length>0){
		return Heap[0];
	}else{
		return -1;
	}
}

所有可执行代码

#include <iostream>
using namespace std;
#define MAX 100

int Heap[MAX]={0};
int length = 0;	

int parent(int j){
	if(j>0){
		return (j-1)/2;  //返回当前节点父亲的位置 		
	} 
	return -1;  //返回当前节点父亲的位置 
}

int left(int j){
	return j*2+1;
}
int right(int j){
	return j*2+2;
}


bool has_left(int j){
	return left(j)<length; 
}
bool has_right(int j){
	return right(j)<length;
}

//上浮 
void up(int j){
	if(j>0 && Heap[j]<Heap[parent(j)]){ //如果比父母小 
		swap(Heap[j],Heap[parent(j)]);// 交换 
		up(parent(j)); //递归 
	} 
}

//下沉 
void down(int j){
	//堆是一颗完全二叉树 先有左边 再有右边 
	if(has_left(j)){
		int small = left(j);
		if(has_right(j))
			if(Heap[small]>Heap[right(j)])
				small = right(j);
		
			
		if(Heap[small]<Heap[j]){
			swap(Heap[small],Heap[j]);
			down(small); //递归 
		}
	}
} 

int get_min(){
	if(length>0){
		return Heap[0];
	}else{
		return -1;
	}
} 

//添加 
void add(int val){
	Heap[length++] = val;
	up(length-1); //将新元素上浮	
}

//删除 取堆顶元素 
int remove(){
	
	swap(Heap[0],Heap[length-1]);//先和最后一个换 再删除
	int r = Heap[--length]; //返回结果 
	
	down(0);  //堆顶下沉
	return r; 
} 







int main(int argc, char *argv[])
{
	add(43); 
	add(53);
	add(4);
	add(3);
	add(9);
	add(100);

	cout<<remove()<<endl;
	cout<<remove()<<endl;
	cout<<remove()<<endl;
	cout<<remove()<<endl;
	cout<<remove()<<endl;
	cout<<remove()<<endl;
	
	cout<<"----------"<<endl; 

	return 0;
}
原文地址:https://www.cnblogs.com/biningooginind/p/12536701.html