优先队列(堆) - C语言实现(摘自数据结构与算法分析 C语言描述)

一、概述

  优先队列(堆)是允许至少下列两种操作的数据结构:Insert(插入),它的工作显而易见的,以及DeleteMin(删除最小者),它的工作是找出、返回和删除优先队列中最小的元素。

  如同大多数数据结构那样,有时可能要添加一些操作,但这些添加的操作属于扩展的操作,而不属于图1所描述的基本模型。

优先队列(堆) - C语言实现(摘自数据结构与算法分析 C语言描述)_第1张图片

图1 优先队列的基本模型

  使操作被快速执行的性质是堆序(heap order)性,由于我们想要快速地找到最小元因此最小元应该在根上。应用这个逻辑我们得到堆序性质。在一个堆中,对于每一个节点X,X的父亲中的关键字小于(或等于)X中的关键字(这种堆叫做最小堆),根节点除外(它没有父亲)。图2中左边的树是一个堆,但是,右边的树则不是(虚线表示堆序性质被破坏)。

优先队列(堆) - C语言实现(摘自数据结构与算法分析 C语言描述)_第2张图片

图2 两棵完全二叉树(只有左边的树是堆)

  无论从概念上还是实际上考虑,执行这两种所要求的操作都是容易的,只需始终保持堆序性质。

二、实现

  Insert(插入):插入操作一般使用的策略叫做上滤(percolate up):新元素在堆中上滤直到找出正确的位置(设堆为H,待插入的元素为X,首先在size+1的位置建立一个空穴,然后比较X和空穴的父亲的大小,把“大的父亲”换下来,以此推进,最后把X放到合适的位置)。

  DeleteMin(删除最小元):与插入“上滤”相对应,采用一种“下滤”的策略,就是逐层推进,把较小的儿子换上来,这里面有个小的问题在具体算法实现上要注意,设堆的最后一个元素是L,在推进到倒数第二层时,将导致最后一层的某个孩子被换上去而产生一个洞,这时候为了保持堆的结构,必须把最后一个元素运过去补上,此时就存在一个问题,如果L比那个孩子小的话就不能保证堆序的性质了,所以在程序中要加一个if语句来进行这个边界条件的处理,对于一个完整的程序,算法是重要的一方面,而对算法边界问题的处理则是更重要的一方面。

文件名:binheap.h
#ifndef _BinHeap_H

typedef int ElementType;

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

文件名:binheap.c
#include "fatal.h"
#include "binheap.h"

#define MinPQSize (10)
#define MinData (-32767)

struct HeapStruct
{
	int Capacity;
	int Size;
	ElementType *Elements;
};

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;

	return H;
}

/* H->Elements[ 0 ] is a sentinel */
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) /* The new element is percolated up the heap  */
		H->Elements[ i ] = H->Elements[ i / 2 ];           /* until the correct location is found */
	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 )
	{
		/* Find smaller child */
		Child = i * 2;
		if ( Child != H->Size && H->Elements[ Child + 1 ]
								<H->Elements[ Child ] )
			Child++;

		/* Percolate one level */
		if ( LastElement > H->Elements[ Child ] )
			H->Elements[ i ] = H->Elements[ Child ];
		else
			break;
	}
	H->Elements[ i ] = LastElement;
	return MinElement;
}

void
MakeEmpty( PriorityQueue H )
{
	H->Size = 0;
}

ElementType
FindMin( PriorityQueue H )
{
	if( !IsEmpty( H ) )
		return H->Elements[ 1 ];
	Error( "Priority Queue is Empty" );
	return H->Elements[ 0 ];
}

int
IsEmpty( PriorityQueue H )
{
	return H->Size == 0;
}

int
IsFull( PriorityQueue H )
{
	return H->Size == H->Capacity;
}

void
Destroy( PriorityQueue H )
{
	free( H->Elements );
	free( H );
}

文件名:main.c
#include "binheap.h"
#include <stdio.h>

int 
main()
{
	PriorityQueue H = Initialize( 50 );
	int ar[] = { 32, 21, 16, 24, 31, 19, 68, 65, 26, 13 };
	int i;
	for ( i = 0; i < 10; i++ )
		Insert( ar[i], H );
	for ( i = 0; i < 10; i++ )
	{
		printf( "%d\n", DeleteMin( H ) );

	}
	return 0;
}


附录:上述代码中用到了Error、FatalError等函数,其实现如下(即fatal.h文件):
#include <stdio.h>
#include <stdlib.h>

#define Error( Str )        FatalError( Str )
#define FatalError( Str )   fprintf( stderr, "%s\n", Str ), exit( 1 )

备注:本文摘自《数据结构与算法分析 C语言描述 Mark Allen Weiss著》,代码经gcc编译测试通过。

附件下载:http://download.csdn.net/detail/shuxiao9058/4212412#binheap_20120407.tar.gz


你可能感兴趣的:(数据结构,c,算法,struct,insert,语言)