优先队列(堆) - C语言实现(摘自数据结构与算法分析 C语言描述)
来源:互联网 发布:php高级程序员面试题 编辑:程序博客网 时间:2024/04/28 09:22
一、概述
优先队列(堆)是允许至少下列两种操作的数据结构:Insert(插入),它的工作显而易见的,以及DeleteMin(删除最小者),它的工作是找出、返回和删除优先队列中最小的元素。
如同大多数数据结构那样,有时可能要添加一些操作,但这些添加的操作属于扩展的操作,而不属于图1所描述的基本模型。
图1 优先队列的基本模型
使操作被快速执行的性质是堆序(heap order)性,由于我们想要快速地找到最小元因此最小元应该在根上。应用这个逻辑我们得到堆序性质。在一个堆中,对于每一个节点X,X的父亲中的关键字小于(或等于)X中的关键字(这种堆叫做最小堆),根节点除外(它没有父亲)。图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;
- }
- #include <stdio.h>
- #include <stdlib.h>
- #define Error( Str ) FatalError( Str )
- #define FatalError( Str ) fprintf( stderr, "%s\n", Str ), exit( 1 )
- 优先队列(堆) - C语言实现(摘自数据结构与算法分析 C语言描述)
- 优先队列(堆) - C语言实现(摘自数据结构与算法分析 C语言描述)
- 优先队列(堆) - C语言实现(摘自数据结构与算法分析 C语言描述)
- 队列 - C语言实现(摘自数据结构与算法分析 C语言描述)
- 队列 - C语言实现(摘自数据结构与算法分析 C语言描述)
- 队列 - C语言实现(摘自数据结构与算法分析 C语言描述)
- 排序 - C语言实现(摘自数据结构与算法分析C语言描述))
- 栈及其应用 - C语言实现(摘自数据结构与算法分析 C语言描述)
- 二叉查找树 - C语言实现(摘自数据结构与算法分析 C语言描述)
- 散列 - C语言实现(摘自数据结构与算法分析 C语言描述)
- 散列 - C语言实现(摘自数据结构与算法分析 C语言描述)
- 散列 - C语言实现(摘自数据结构与算法分析 C语言描述)
- 二叉查找树 - C语言实现(摘自数据结构与算法分析 C语言描述)
- 栈及其应用 - C语言实现(摘自数据结构与算法分析 C语言描述)
- AVL(Adelson-Velskii和Landis)树 - C语言实现(摘自数据结构与算法分析 C语言描述)
- AVL(Adelson-Velskii和Landis)树 - C语言实现(摘自数据结构与算法分析 C语言描述)
- 《算法与数据结构---C语言描述》优先队列
- (数据结构与算法分析 七)------优先队列中的二叉堆的实现( Java语言描述)
- Fragment之间的通信
- Android代码混淆的使用
- 排序-c语言实现(摘自数据结构与算法分析c语言实现)
- 黑马程序员_JAVA_银行调度管理系统
- C++ Primer学习笔记6 标准库类型(命名空间的using声明、标准库string类型)
- 优先队列(堆) - C语言实现(摘自数据结构与算法分析 C语言描述)
- 实例介绍Cocos2d-x中Box2D物理引擎:HelloBox2D
- 嵌入式 VFS: Cannot open root device "mtdblock2" or unknown-block(2,0)
- 谷歌构筑互联网生态 探秘谷歌气球+光纤
- String类的字符串操作(C++实现)
- UVA 10047 The Monocycle
- 嵌入式linux应用程序移植方法总结
- Java日期时间使用总结
- win32 sdk绘制矩形选择框