您的位置:首页 > 其它

二叉堆实现二

2015-10-14 22:36 218 查看
堆可以视为一棵完全二叉树,树的每一层都是被填满的,最后一层可能除外,所以堆可以用数组来表示。对于数组中任意位置i上的元素,其左儿子在位置i*2+1,其右儿子在位置i*2+2上,其父节点在位置(i+1)/2-1处。

二叉堆有两种:最大堆和最小堆。最大堆中,除根结点外(其无父结点),每个结点的关键字都不大于其父结点的关键字。最小堆中,除根结点外,每个结点的关键字都不小于其父结点的关键字。

插入元素(insert):

在堆中插入元素X时,在数组的尾部增加一个空穴,如果X可以放在空穴并使堆的性质满足,则插入完成。否则,将空穴的父节点的关键字下移到空穴,使空穴上移。重复该过程直到X可以插入空穴。这种方法叫上滤。下图展示了使用上滤法将14插入一个最小堆的过程(图来自《数据结构与算法分析:C语言描述》)。




删除最小元素(deleteMin):
最小堆的最小元素在根结点处。删除最小元素后,在根结点处产生一个空穴,如果将堆中最后一个元素X放在空穴中可以不破坏堆的性质,则删除完成。否则将空穴两个儿子中较小的一个放入空穴,空穴下移一层。重复该过程直到X可以放入空穴中。这种方法叫做下滤。下图展示了deleteMin的执行过程。




//参考《数据结构与算法分析:C语言描述》
#include <iostream>
#include <vector>
using namespace std;

vector<int> heap;
void insert(int e)
{
    heap.push_back(e);  //创建空穴
    if(heap.size()>1){  //确保不是父结点
		int x=heap.size()-1;
		int p=heap.size()/2-1;//p是x的父节点的坐标
		while((p>=0)&&(e<heap[p])){
			heap[x]=heap[p];   //父结点下移至空穴
		       	x=p;      p=(p+1)/2-1; //空穴上移
		}
		heap[x]=e;    //插入e
    }
}

int deleteMin()
{
    int c=0,i=0;

    int last=*--heap.end(),min=heap[0];
    for( i=0;i*2<heap.size()-1;i=c){
		c=i*2+1;   //左儿子
		if((c!=heap.size()-1)&&(heap[c+1]<heap[c]))
			++c;
		if(last>heap[c])
			heap[i]=heap[c];
		else
			break;
	}
    heap[i]=last;
    heap.pop_back();
    return min;
}

int main()
{
    for(int i=0;i<11;++i){
		int a;    cin>>a;
		insert(a);
	}
	for(int i=0;i<10;++i){
		for(auto x:heap)
			cout<<x<<"   ";
		deleteMin();
		cout<<endl;
	}
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: