数据结构------堆和优先权队列

来源:互联网 发布:房地产网络推广方案 编辑:程序博客网 时间:2024/06/04 23:29

堆和优先权队列是基于树型结构的实现的。

一,堆

1,堆的定义:一个大小为n的堆是一棵包含n个结点的完全二叉树,该书中每个结点的关键字值大于等于其双亲结点的关键字,完全二叉树的根称为对顶。它的关键字值是整棵树上最小的称为最小堆,反正最大的称为最大堆。

2,堆的存储,由于堆是完全二叉树,正如二叉树学习时提及,完全二叉树可以通过顺序存储来实现,故采用顺序存储结构来学习堆。

3,建堆算法,建堆算法主要涉及一个堆的调整问题。

实现算法如下:向下调整heap[r],设 temp=heap[r],如果temp大于其左右孩子的较小者,则将较小值的位置放置在temp的位置。继续这样的过程直到不再需要调整或到达堆的底部位置。基本过程如下图所示:


4,程序实现如下:

/* * ===================================================================================== * *       Filename:  heap.c * *    Description:   * *        Version:  1.0 *        Created:  2012年08月09日 08时49分52秒 *       Revision:  none *       Compiler:  gcc */#include <stdlib.h>#include <stdio.h>/*向下调整,构建最小堆,heap为顺序存储堆元素的指针,r表示调整的的元素的索引,n表示最大的索引*/void AdjustDown(int *heap,int r,int n){int child=2*r+1;int temp;temp=heap[r];while(child<=n){if((child<n)&&(heap[child]>heap[child+1]))child++;/*得到两个孩子中较小的值的索引*/if(temp<=heap[child])break;heap[(child-1)/2]=heap[child];child=2*child+1;}heap[(child-1)/2]=temp;}/*建最小堆,heap为顺序存储堆元素的指针,n表示元素个数 */void CreateMinHeap(int *heap,int n){int i=(n-2)/2;for(;i>-1;i--)AdjustDown(heap,i,n-1);}int main(){int i=0,n;int heap[]={61,43,81,28,36,47,83,5};n=sizeof(heap)/sizeof(heap[0]);CreateMinHeap(heap,n);for(i=0;i<n;i++)printf("%d ",heap[i]);printf("\n");return 0;}


二,优先权队列

堆是有效实现优先权队列的有效数据结构,如果最小值优先权最高,则使用最小堆。依据最小堆可以实现优先权队列。优先权队列涉及进队列和出队列的操作。进队列可以在最小堆中插入一个值,然后进行调整,出队列则删除堆顶元素,然后再调整。依然以最小堆为例来实现优先权队列。

/* * ===================================================================================== * *       Filename:  priq.heap.c * *    Description:   * *        Version:  1.0 *        Created:  2012年08月09日 03时49分52秒 *       Revision:  none *       Compiler:  gcc * * ===================================================================================== */#include <stdlib.h>#include <stdio.h>#define MAX 100typedef struct PriQueue{intheap[MAX];int n;/*当前结点数目*/}PriQueue;static PriQueue priq;/*向下调整,构建最小堆,priq.heap为顺序存储堆元素的指针,r表示调整的的元素的索引,n表示最大的索引*/void AdjustDown(int r,int n){int child=2*r+1;int temp;temp=priq.heap[r];while(child<=n){if((child<n)&&(priq.heap[child]>priq.heap[child+1]))child++;/*得到两个孩子中较小的值的索引*/if(temp<=priq.heap[child])break;priq.heap[(child-1)/2]=priq.heap[child];child=2*child+1;}priq.heap[(child-1)/2]=temp;}/* 向上调整堆 */void AdjustUp(int j){int i=j;int temp=priq.heap[i];while(i>0&&temp<priq.heap[(i-1)/2]){priq.heap[i]=priq.heap[(i-1)/2];i=(i-1)/2;}priq.heap[i]=temp;}/* 入队操作 */void append(int x){priq.heap[priq.n++]=x;AdjustUp(priq.n-1);}/*出对列操作 */void front(int *x){*x=priq.heap[0];priq.heap[0]=priq.heap[--priq.n];AdjustDown(0,priq.n-1);}int main(){int x;append(71);append(74);append(2);append(72);append(54);front(&x);printf("%d ",x);    front(&x);printf("%d ",x);front(&x);printf("%d ",x);front(&x);printf("%d ",x);front(&x);printf("%d ",x);return 0;}
测试结果:

2 54 71 72 74