您的位置:首页 > 其它

二叉堆

2013-10-11 20:45 232 查看
堆是一棵被完全填满的二叉树,有可能的例外是在底层。

因为完全二叉树很有规律,因此可以用数组来表示,而不需要用指针。对于数组中任一位置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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: