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

本文深入探讨了堆和优先权队列的数据结构实现,包括堆的定义、存储方式、建堆算法及优先权队列的实现方法。通过具体的C语言程序实例,展示了如何利用堆构建优先权队列,以及实现入队和出队操作。

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

一,堆

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



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值