堆和优先权队列是基于树型结构的实现的。
一,堆
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 100
typedef struct PriQueue{
int heap[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
本文深入探讨了堆和优先权队列的数据结构实现,包括堆的定义、存储方式、建堆算法及优先权队列的实现方法。通过具体的C语言程序实例,展示了如何利用堆构建优先权队列,以及实现入队和出队操作。
661

被折叠的 条评论
为什么被折叠?



