优先队列是堆排序的一个具体应用。
优先队列分为如下几个操作:
1.INSERT(S,x)把元素x插入到优先队列中。
2.MAXIMUM(S):返回s中具有最大关键字的元素。
3.EXTRACT_MAX(S):去掉S中最大关键字的元素
4.INCREASE_KEY(S,x,k):将元素x的关键字值增加到k,k是不小于x的元素。
优先队列的应用:
1.共享计算机系统的作业调度。最大优先队列要i记录要执行的各个作业以及他们之间的相对优先级。当一个作业完成或者被中断后,调度器调用EXTRACT_MAX从所有的等待作业中,选出具有最高优先级的作业来执行。在任何时候调度器可以调用INSERT把一个新作业假如到队列中来。
2.可以用于最小生成树和单元最短路径优先算法中,需要应用DECREASE_KEY的应用。
代码:
/*
Author:Bai
Name:优先队列
Use for:1.共享计算机系统中的作业调度
2.基于事件驱动的模拟器
3.用在最小生成树和单元最短路径中
Date:2015/4/30
*/
#include<iostream>
using namespace std;
typedef struct heap
{
int heap_size;
int *key;
}heap;
void initialize(heap *A)
{
A->key=new int;
A->heap_size=0;
}
void MAX_HEAPIFY(heap *A,int i)//为了使堆保持大根堆的性质(我这里利用了循环操作的方法,而算法导论中应用了递归调用的办法)
{
//非递归方法
int largest;
int l=2*i;//l是A的左孩子
int r=2*i+1;//r是A的右孩子
if(l<=A->heap_size&&A->key[l]>A->key[i])//这里的大于号更改成小于号就是小根堆排序
largest=l;
else
largest=i;
if(r<=A->heap_size&&A->key[r]>A->key[largest])
largest=r;
while(largest!=i)
{
int temp=A->key[i];
A->key[i]=A->key[largest];
A->key[largest]=temp;
i=largest;
l=2*i;
r=2*i+1;
if(l<=A->heap_size&&A->key[l]>A->key[i])
largest=l;
else
largest=i;
if(r<=A->heap_size&&A->key[r]>A->key[largest])
largest=r;
}
for(int k=1;k<=A->heap_size;k++)
printf("%d,",A->key[k]);
printf("\n");
}
void BUILD_MAX_HEAP(heap *A)
{
int m=(A->heap_size)/2;
while(m>=1)
{
MAX_HEAPIFY(A,m);
m--;
}
}
void HEAP_SORT(heap *A)
{
BUILD_MAX_HEAP(A);
printf("第一次建立大根堆后的数组是:");
for(int k=1;k<=A->heap_size;k++)
printf("%d,",A->key[k]);
printf("\n");
int length=A->heap_size;
printf("大根堆排序后的数组是:");
printf("%d,",A->key[1]);
for(int i=length;i>=2;i--)
{
A->key[1]=A->key[i];
A->heap_size--;
MAX_HEAPIFY(A,1);//现在只有这个堆的第一个结点是错误的,其他的子树都是大根堆
printf("%d ",A->key[1]);
}
printf("\n");
printf("done\n");
}
//求优先队列的最大值
int HEAP_MAXIMUM(heap *A)
{
printf("%d\n",A->key[1]);
return 0;
}
//将优先队列中去除最大值
void HEAP_EXTRACT_MAX(heap *A)
{
if(A->heap_size<1)
printf("不能再继续删除了!\n");
A->key[1]=A->key[A->heap_size];
A->heap_size--;
MAX_HEAPIFY(A,1);
}
//将优先队列中的某个数m增大到key,key>m
void HEAP_INCREASE_KEY(heap *A,int i,int key)
{
A->key[i]=key;
int parent=i/2;
while(i>1&&A->key[i]>A->key[parent])//这个点增大后,要向上判断其是否比父节点大,然后依次循环修改。
{
int temp=A->key[i];
A->key[i]=A->key[parent];
A->key[parent]=temp;
i=parent;
parent=i/2;
}
}
//将key这个值插入到A优先队列
//首先建立一个新的结点,然后将它赋值为负无穷大,最后再利用HEAP_INCREASE_KEY将它增大到key。
void HEAP_INSERT(heap *A,int key)
{
A->heap_size=A->heap_size+1;
A->key[A->heap_size]=INT_MIN;
HEAP_INCREASE_KEY(A,A->heap_size,key);
}
void SHOW_HEAP(heap *A)
{
printf("当前的优先队列是:\n");
for(int i=1;i<=A->heap_size;i++)
printf("%d ",A->key[i]);
printf("\n");
}
int main(void)
{
int ch;
heap *A=new heap;
initialize(A);
printf("请输入一组堆的值以#结束?\n");
int key;
int i=1;
while(scanf("%d",&key)==1)
{
HEAP_INSERT(A,key);//插入的过程会自动创建称为优先队列
}
fflush(stdin);
while(1)
{
printf("***************请选择如下操作选项***************\n");
printf("1.取优先队列的最大值\n");
printf("2.去除优先队列当前的最大值,去除后仍然自动变换为优先队列结构\n");
printf("3.插入某个值,插入后仍然自动变换为优先队列结构\n");
printf("4.把某个i点上的值增大到key\n");
printf("5.退出系统\n");
scanf("%d",&ch);
switch(ch)
{
case 1:HEAP_MAXIMUM(A);break;
case 2:
HEAP_EXTRACT_MAX(A);
break;
case 3:
{
int key;
printf("请输入您要插入的Key值:");
scanf("%d",&key);
HEAP_INSERT(A,key);
}
SHOW_HEAP(A);
break;
case 4:
{
printf("请问您要把第几个数变成多大?:");
int i,key;
scanf("%d %d",&i,&key);
HEAP_INCREASE_KEY(A,i,key);
}
SHOW_HEAP(A);
break;
case 5:
return 0;
default: break;
}
}
}
结果展示: