堆的操作,用数组实现

包括插入操作--自底向上调整、删除操作--把最后一位赋值给堆顶,然后从堆顶向下调整

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
using namespace std;
//堆
//一种数组对象,可以被视为一棵完全二叉树,树中的每个节点都与数组中存放该节点中值得那个元素对应
int heap_size=0;
int heap[10001];

//插入操作:自底向上 
void put(int d){//首先看插入操作put 
	int now,next;
	heap[++heap_size]=d;//首先把元素插入末尾 
	now=heap_size;
	while(now>1){
		next=now>>1;//即next=now/2
		if(heap[now]>=heap[next]) break;//这是小根堆,因为小的在上面 
		else swap(heap[next],heap[now]);//否则就交换,并且继续迭代 
		now=next;
	}
} 


//删除操作: 取出堆顶元素,然后把最后一个赋值给堆顶,然后向下调整 
int get(){//从堆中取出并删除一个元素get,
	int now,next,res;
	 res=heap[1];
	 heap[1]=heap[heap_size--];
	now=1;
	while(now*2<=heap_size){
		next=now*2;
		if(next<heap_size&&heap[next]<heap[next+1]) next++; //用最小的与之交换 
		if(heap[now]<=heap[next]) break;
		swap(heap[now],heap[next]);
		now=next;
	}
	return res;
}

int main(){
	int a[20]={0,3,5,1,7,6,4,2,5,4,1};
	for(int i=1;i<=10;i++) put(a[i]);
	cout<<"堆中元素如下"<<endl; 
	for(int i=1;i<=10;i++) cout<<heap[i]<<" ";
	cout<<endl;
	cout<<"最小的元素 "<<endl; 
	cout<<get(); 
return 0;
}

  

完整的:大根堆,可以实现排序

建堆的时候倒着建,for(int i=n/2;i>=1;i--)  这样可以保证每个子树的根都是最大的

排序的时候每次都把堆顶移到最后,然后n=i这样减少  for(int i=n;i>1;i--)  swap(a[i],a[1])  downjust(1,i-1)

//堆:
//a heap is a specialized tree-based data structure(树)、并查集、堆的实质其实都可以是树 
//一般的快速数据结构:优先队列:
//优先队列默认:大顶堆 (不用自己写函数) 
priority_queue<int> q1;
//小顶堆
priority_queue<int,vector<int>,greater<int> > q2;
//跟一般的数据结构(需要自己写函数的那种) 

//需要自己写函数 
int heap[maxn];  //just like堆 
//但是掌握堆的自顶向上和自底向上的两种写法是很重要的
//建堆的过程:自上向下调整,但是需要倒着枚举调整,调整所有的非叶子节点,从n/2到1,倒着调整,但是调整是自顶向下的
//包括删除节点的时候:删除堆顶元素,用最后一个元素覆盖第一个,然后调整downjust(1,n)
void downadjust(int low,int high){ //向下调整:删除、建堆、堆排序 
	int i=low,j=2*i;
	while(j<=high){
		//如果有孩子存在,且有孩子的值大于左孩子的值,就像后移,然后再跟i比较大小
		if(j+1<=high&&heap[j+1]>heap[j]) j++;
		if(heap[j]>heap[i]){
			//如果孩子比爸爸大,就要交换
			swap(heap[j],heap[i]);
			i=j;
			j=2*i; 
		} 
		else break; //不然就退出 
	}
} 
void create(){
	for(int i=1;i<=n;i++) cin>>heap[i];
	for(int i=n/2;i>=1;i--) downadjust(i,n);
}   //倒着调整:这样才能满足每个节点都是以他为父节点的最大值 
//删除堆顶元素
void del(){
	heap[1]=heap[n--];
	downadjust(1,n);  //调整堆顶 
} 
//添加一个元素的时候:添加再最后面,然后自底向上调整 
void upadjust(int high,int low){
	int i=high,j=high/2;
	while(j>=low){
		//总是和父亲比较的话,就不存在j++或者j--了,直接比较就可以了
		if(heap[j]<heap[i]){
			swap(heap[j],heap[i]); 
			i=j;  //如果父亲比小的话,就交换 
			j/=2;
		} 
		else break;
	}
}
void insert(int x){
	heap[++n]=x;  //添加再末尾 
	upadjust(n,1);
}
//删除堆顶,添加末尾
 
//堆排序
//由于堆中堆顶元素是确定的最大的,所以每次都去堆顶元素和最末尾的元素交换,然后从堆顶进行自顶向下的调整
//这样每次都取出了最大堆顶元素,而且对的范围也在缩小
void heapsort(){
	create(); //先建堆 
	for(int i=n;i>1;i--) {
		swap(a[i],a[1]);  //交换 
		downadjust(1,i-1);  //范围再缩小 
	}
	for(int i=1;i<=n;i++) cout<<heap[i]<<" ";
	//自小到大的序列 
} 

  

 

 posted on 2020-02-05 20:04  shirlybabyyy  阅读(1)  评论(0编辑  收藏  举报