堆的push,pop数组实现(挑战程序设计竞赛)

堆是形如下图的二叉树

堆的最重要的性质,就是儿子的值一定不小于父亲的值。树的节点从上到下,从左到右的顺序紧凑排列。


【插入数据】push

 

首先在堆的末尾插入数据,然后不断向上提升直到没有大小颠倒


【删除数据】pop


从堆中删除最小的数据

先将堆中最后一个节点的值复制到根节点上,并且删除最后一个节点。然后不断向下交换,直到没有大小颠倒;

在向下交换的过程中,如果有两个儿子,则与其中较小的交换(如果儿子比自己小)。


【堆的操作复杂度】

两种操作都与树的深度成正比。 因此,如果有n个元素,那么每个操作的复杂度为O(logn);


【堆的实现】

给每个元素按照从上到下从左到右的顺序编号,并用数组来储存,此时儿子的编号满足如下性质

1.左儿子的编号是自己编号 x 2 + 1;

2.右儿子的编号是自己编号 x 2 + 2;

#include <iostream>
using namespace std;
const int maxn=10000;

class priority_q{
	public:
		priority_q(){
			sz = 0; //size 初始化为0;
		}
		void push(int x);
		int pop();
		int size(){
			return this->sz;
		}
	private:	
		int heap[maxn],sz; 
};
void priority_q::push(int x){
	int i = sz++;
	while(i > 0){
		// 父亲节点的编号
		int p = (i - 1)/2;
		
		if(heap[p] <= x) break;
		//把父亲的节点放下来
		heap[i] = heap[p];
		//当前节点更新
		i = p;
	}
	heap[i] = x;
}
int priority_q::pop(){
	int ret = heap[0]; //根,最小值
	
	int x = heap[--sz]; //最后一个节点, 放到根的数值
	
	int i = 0;
	//从根向下交换
	while(i * 2 + 1< sz){ 
		int a= i * 2 + 1, b= i * 2 + 2; //两个儿子的位置 
		if(b < sz && heap[b]< heap[a]) a = b; //选出 最小的儿子
		
		if(heap[a] >= x) break;  //如果没有大小颠倒 退出
		//把儿子的值提上来
		heap[i] = heap[a];
		i = a;
	}
	heap[i] = x; //最终在找到的位置 i 填入 x;
	return ret; 
}
int main(){
	priority_q pq;
	pq.push(5);
	pq.push(10);
	pq.push(7);
	pq.push(2);
	int size = pq.size();
	for(int i = 0; i < size; i++){
		cout<<"第"<<i+1<<"个数"<<pq.pop()<<endl;
	}
	return 0;
}
搞笑的是,在我敲完上面这段代码运行的时候,360说这个是木马!搞得我关掉360杀毒才成功运行难过

posted @ 2015-08-05 09:02  编程菌  阅读(316)  评论(0编辑  收藏  举报