二叉堆实现优先队列中的上滤和下滤

来源:互联网 发布:博客html源码下载 编辑:程序博客网 时间:2024/05/03 22:01

优先队列是使用二叉堆来实现

其中很重要的两个操作,一个是插入,另一个是删除最优先值(这里认为是最小值)

其中插入操作可以这样实现:

把X放入二叉堆的最后端,然后再通过“上滤”操作把X放到相应位置

删除操作可以这样实现:

把最顶端的元素(即)最小值删除,然后把堆中最后一个元素先放到最顶端,然后通过“下滤”操作来使其到达正确位置

代码如下:

#include <stdio.h>#include <stdlib.h>typedef int ElementType;#define MinData -1typedef struct HeapStruct *PriorityQueue;struct HeapStruct {    ElementType  *Elements;    int Capacity;    int Size;};PriorityQueue Initialize( int MaxElements ); /* details omitted */void PercolateUp( int p, PriorityQueue H );void PercolateDown( int p, PriorityQueue H );void Insert( ElementType X, PriorityQueue H ) {    int p = ++H->Size;    H->Elements[p] = X;    PercolateUp( p, H );}ElementType DeleteMin( PriorityQueue H ) {     ElementType MinElement;     MinElement = H->Elements[1];    H->Elements[1] = H->Elements[H->Size--];    PercolateDown( 1, H );    return MinElement; }int main(){    int n, i, op, X;    PriorityQueue H;    scanf("%d", &n);    H = Initialize(n);    for ( i=0; i<n; i++ ) {        scanf("%d", &op);        switch( op ) {        case 1:            scanf("%d", &X);            Insert(X, H);            break;        case 0:            printf("%d ", DeleteMin(H));            break;        }    }    printf("\nInside H:");    for ( i=1; i<=H->Size; i++ )        printf(" %d", H->Elements[i]);    return 0;}void PercolateUp( int p, PriorityQueue H ){ElementType temp = H->Elements[p];while(temp < H->Elements[p>>1]){H->Elements[p] = H->Elements[p>>1];p>>=1;}H->Elements[p] = temp;} void PercolateDown( int p, PriorityQueue H ){int child, i;ElementType temp = H->Elements[p];for(i = p; i<<1 <= H->Size; i = child){child = i<<1;if(child != H->Size && H->Elements[child] > H->Elements[child+1])child++;if(temp > H->Elements[child])H->Elements[i] = H->Elements[child];elsebreak;}H->Elements[i] = temp;}


但要注意几点:

第一,可以把二叉堆对应数组的第0个元素用来存放一个“哨兵”Mindata,这样在上滤的过程中就不用特殊判断是否到达顶端,因为如果到达顶端,Elements[i/2]即为Elements[0]一定比Elements[1]要小,因此会自动停止上滤

第二,在上滤和下滤的比较过程中,千万记得是用temp去和Elements[p>>1]以及H->Elements[child]去比

比如,while(temp < H->Elements[p>>1])不要写成while( H->Elements[p]< H->Elements[p>>1]),因为我们每次都是只单纯把元素向下放,而不是交换,因此H->Elements[p]仍旧是原来的值,而不是我们想象中的逐步上升的上滤目标值

0 0