首先,堆是一种完全二叉树,堆可以分为最小堆和最大堆。最小堆的儿子节点一定不小于它的父亲节点(a[parent]<=a[child],即根节点最小),最大堆的儿子节点一定不大于它的父亲节点(a[parent]>=a[child],根节点最大)。一般,堆排序算法使用的是最大堆,优先队列使用的是最小堆。


如果把堆看成一棵树,一个堆中的节点的高度就是该节点到叶子节点最长简单路径上边的数目。从而,堆的高度即为根节点的高度。如果一个堆含有n个元素,则该堆的高度为floor(log2n2是底数,floor()向下取整。


堆的插入与删除操作与堆的深度成正比,所以,如果一共n个元素,那么每个操作可以在O(logn)的时间内完成


堆可以用数组来存储,若记父亲节点下标为i,则左儿子节点下标:2*i+1 。右儿子节点下标:2*i+2 。


实现(以最小堆为例):

//heap为存储堆的数组,sz为堆的元素个数 
int heap[MAX],sz = 0;
void push(int x){	//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 pop(){
	int ret = heap[0];		//要删除的元素
	int x = heap[--sz];		//准备提最后一个元素,且元素个数减一
	int i = 0;				//插入位置 
	while(i*2+1<sz){
		int LeftChild = i*2+1;		//比较要插入的位置的两个儿子节点 
		int RightChild = i*2+2;
		if(RightChild<sz && heap[RightChild]<heap[LeftChild])
			LeftChild = RightChild;		//总保证左儿子最小 
		if(heap[LeftChild]>=x)			//如果最小的子节点都比自己大,则退出 
			break;
		heap[i] = heap[LeftChild];		//否则将最小的儿子提上来 
		i = LeftChild;
	} 
	heap[i] = x;
	return ret;
	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值