您的位置:首页 > 其它

优先队列的简单实现-二叉堆实现

2017-01-21 20:08 627 查看

二叉堆



二叉堆简介

二叉堆是优先队列的一种实现方式

同二叉查找树一样,二叉堆也有结构性和堆序性

结构性

堆是一棵除底层外完全被填满的树

堆序性

使操作被快速执行的性质是堆序性。在这里,我们想实现的是快速找出最小值(最大值),因此最小值(最大值)应该在根上。

所以我们可以得出一个堆序性:在堆中,对于每一个节点X,X的父亲的值应该小于等于(大于等于)X的值。

如果你不知道二叉树这些知识,建议先自行了解这些知识

下面先给出关键的源代码,稍后再作分析

优先队列

头文件代码

BinHeap.h

#ifndef BINHEAP_H_INCLUDED
#define BINHEAP_H_INCLUDED

struct HeapStruct;
typedef struct HeapStruct *PriorityQueue;

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

#endif // BINHEAP_H_INCLUDED


具体实现

BinHeap.c

#include <stdio.h>
#include <stdlib.h>
#include "BinHeap.h"

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!!!" );

/* Allocate the array plus one extra for sentinel */
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;
}

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->Elements[ i ] = X;
}

ElementType 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;
}


代码分析

为什么用数组来实现二叉堆

因为“实惠”

因为二叉堆有个特点是:除了最底层,其他层都必须是满的,也就是一棵二叉完全树



比如上图中,一共有十个节点,那么用数组就可以这样来存

1 2 3 4 5 6 7 8 9 10

下标为1-10

那么的节点1的儿子的下标就是2*1,2*1+1

节点5的父亲便是5/2 = 2

这样很方便吧,写起来也简单

Insert操作

插入操作采取的是上滤

首先我们在数组末端开一个空穴,然后把要插入的值放在空穴里面,之后比较空穴的父亲的值和插入的值的大小,

如果父亲的值教大,那么便交换空穴和父亲,一只重复这个操作,直到找到符合条件的位置

DeleteMin操作

删除最小元操作采取的是下滤

下滤和上滤的思路是差不多的,只是过程相反,这里就不多说,留着读者自己思考吧
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二叉树 结构