二叉堆

    堆是一棵被完全填满的二叉树,有可能的例外是在底层。

    因为完全二叉树很有规律,因此可以用数组来表示,而不需要用指针。对于数组中任一位置i上的元素,其左儿子在2i上,右儿子在左儿子后的单元中。它的父亲则在i/2中。因此,遍历该树所需要的操作也非常简单,唯一的问题是最大的堆大小需要事先估计。

    因此,一个堆数据结构由一个数组(不论是什么类型)、一个代表最大值的整数以及当前堆的大小组成。

    堆快速执行的性质是堆序性。在一个堆中,对于每一个节点X ,X 的父亲中的关键字小于或等于X 中的关键字,根节点除外。(相应的,也可以大于或等于)


1:声明

#ifndef _BinHeap_H

struct HeapStruct;
typedef struct HeapStruct *PriorityQueue;

PriorityQueue Initialize( int MaxElements );
void Destroy( PriorityQueue H );
void MakeEmpty( PriorityQueue H );
void Insert( ElementType x,PriorityQueue H );
ElementType DeleteMin( PriorityQueue H );
ElementType FindMin( PriorityQueue H );
int IsEmpty( PriorityQueue H );
int IsFull( PriorityQueue H );

#endif


struct HeapStruct
{
	int Capacity;
	int Size;
    ElementType *Elements;
};
2:初始化
PriorityQueue
Initialize( int MaxElements )
{
	PriorityQueue H;
	if( MaxElements < MinPQSize )
	     Error( "Priority queue size is too small" );
	     
	H = malloc( sizeof( struct HeapStruct ) );
	if( H == NULL )
	    FatalError( "Out of space" );
	
	H->Elements = malloc( ( MaxElements + 1 ) * sizeof( ElementType ) );
	if( H->Elements == NULL )
		FatalError( "Out of space" );
	H->Capacity = MaxElements;
	H->Size = 0;
	H->Elements[0] =MinData;
	
	return H;
}
3:插入

        为将一个元素X 插入到堆中,在下一个空闲位置即最后一个元素创建一个空位置(添加了一个新元素)。否则该堆就不是完全堆了。如果X 可以放在这个位置又不破坏堆的性质,那么插入完成,否则,就将把它的父节点的元素移入该空穴,这样,空穴就向上移了一层。直到符合堆的性质。

void
Insert( ElementType X,PriorityQueue H )
{
	int i;
	if( IsFull( H ) )
	{
		Error( "Priority queue is full" );
		return;
	}
	
	for( i = ++H->Size; H->Elements[ i / 2 ] > X; i /= 2 );
		H->Elements[ i ] = H->Elements[ i / 2 ];
	H->Element[ i ] = X;
}
        也可以先将X放入空穴,然后与父节点比较,不符合的话就交换,但是这样时间较慢。

        如果插入的数时新的最小值,那么将一直上升到顶端,i=1,那么需要跳出for循环,令位置0处的值足够小就可以了,称之为标记。

4:DeleteMin

       当删除一个最小元时,在根节点处产生了一个空穴,需要将最后一个元素正确的移入空穴。将空穴的两个儿子中的较小者放入空穴中,重复该步骤直到可以将堆中最后一个元素放入空穴中。

Element
DeleteMin( PriorityQueue H )
{
	int i,child;
	ElementType MinElement,LastElement;
	
	if( IsEmpty( H ) )
	{
		Error( "Priority queue is empty" );
		return h->Elements[ 0 ];
	}
	MinElement = H->Elements[ 1 ];
	LastElement = H->Elements[H->Size--];
	
	for( i = 1; i * 2 <= H->Size; i = child  )
	{
		child = i * 2;
		if( child != H->Size && H->Elements[ child + 1 ] < H->Elements[ child ] )//判断左右儿子大小
		child++;
		
		if( LastElement > H->Elements[ child ] )//判断最后一个元素与当前空穴的较小儿子的大小,是否可以插入空穴
			H->Elements[ i ] = H->Elements[ child ];
		else
			break;
	}
	H->Elements[ i ] = LastElement;
	return MinElement;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值