需求分析
最大最小优先队列:
优先队列是0个或多个元素的集合,每个元素都有一个优先权或值,以队列形式存放数据,因此只允许底端加入数据,顶端取出数据,数据的排列按照优先权或值的大小排列。需要实现以下操作:
1、 查找:找出队列中最小或最大元素。
2、 删除:删除队列中最大或最小元素。
3、 插入:插入新元素到队列中。
4、 查看:查看整个队列的所有数据。
5、 实现以上操作后的队列,仍然要为最小或最大优先队列。
算法原理介绍
以线性表的形式存放数据,只允许在第一个元素前插入数据。
利用堆排序算法将队列调整成优先队列。
实现查找、删除、插入等操作。
主要算法:
voidHeapAdjust2(SqList&L,int s,int m)//堆调整算法2(最大优先队列)
{
int j,rc;
rc=L.elem[s];
for(j=2*s;j<=m;j*=2) \\一次堆调整,使小局部顶端为最大元素
{
if(j<m&&L.elem[j]>L.elem[j+1])++j;
if(rc<L.elem[j])break;
L.elem[s]=L.elem[j];
s=j;
}
L.elem[s]=rc;
}
voidHeapSort2(SqList&L)//堆排序算法2(最大优先队列)
{
int i,t;
for(i=L.length/2;i>0;--i)
HeapAdjust2(L,i,L.length); \\由L.length/2 个元素开始进行堆调整
for(i=L.length;i>1;--i)
{
t=L.elem[i];
L.elem[i]=L.elem[1]; \\由L.length/2到第2个元素进行堆调整,最
\\终使整个队列完成堆排序,形成最大堆
L.elem[1]=t;
HeapAdjust2(L,1,i-1);
}
}
实现过程
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include"windows.h"
#define ElemType int
#define list_init_size 10000
#define LISTINCREMENT 10
#define OK 1
#define ERROR 0
typedef struct
{
ElemType*elem;
intlength;
intlistsize;
}SqList;
int InitList_Sq(SqList &L)//初始化线性表
int ListInsert(SqList&L,int i,ElemTypee)//线性表插入操作
int ListDelete(SqList &L,int i,ElemType&e)//线性表删除操作
int ListLoad(SqList&L)//读取线性表数据
void HeapAdjust1(SqList&L,int s,int m)//堆调整算法1(最小优先队列)
{
intj,rc;
rc=L.elem[s];
for(j=2*s;j<=m;j*=2)
{
if(j<m&&L.elem[j]<L.elem[j+1])++j;
if(rc>L.elem[j])break;
L.elem[s]=L.elem[j];
s=j;
}
L.elem[s]=rc;
}
void HeapAdjust2(SqList&L,int s,int m)//堆调整算法2(最大优先队列)
{
intj,rc;
rc=L.elem[s];
for(j=2*s;j<=m;j*=2)
{
if(j<m&&L.elem[j]>L.elem[j+1])++j;
if(rc<L.elem[j])break;
L.elem[s]=L.elem[j];
s=j;
}
L.elem[s]=rc;
}
void HeapSort1(SqList&L)//堆排序算法1(最小优先队列)
{
inti,t;
for(i=L.length/2;i>0;--i)HeapAdjust1(L,i,L.length);
for(i=L.length;i>1;--i)
{
t=L.elem[i];
L.elem[i]=L.elem[1];
L.elem[1]=t;
HeapAdjust1(L,1,i-1);
}
}
void HeapSort2(SqList&L)//堆排序算法2(最大优先队列)
{
inti,t;
for(i=L.length/2;i>0;--i)HeapAdjust2(L,i,L.length);
for(i=L.length;i>1;--i)
{
t=L.elem[i];
L.elem[i]=L.elem[1];
L.elem[1]=t;
HeapAdjust2(L,1,i-1);
}
}
void printmainmenu() //主菜单
void Min(SqList &L)//最小优先序列实现函数
{
inti,a,e,x,choice;
while(1)
{
printmainmenu();
scanf("%d",&choice);
while(choice<1||choice>5) //保证用户正确操作
{
printf("\n您的输入有误,请重新选择:");
scanf("%d",&choice);
}
switch(choice) //选择菜单
{
case1: printf("请确定要录入的数据个数:");
scanf("%d",&a);
printf("inputdata:\n");
for(i=0;i<a;i++)
{
scanf("%d",&e);
ListInsert(L,1,e);
}
HeapSort1(L);
getchar();ListLoad(L);
printf("录入成功按任意键返回~");
getchar();break;
case2: if(L.length==0){printf("队列为空插入失败(按任意键返回)");getchar();}
else{printf("请输入数据:");scanf("%d",&a);
ListInsert(L,1,a);HeapSort1(L);getchar();ListLoad(L);printf("插入成功按任意键返回~");}getchar();break;
case3: ListDelete(L,1,e);
if(L.length!=0){
printf("\ndeletethe data :%d\n",e);
getchar();
ListLoad(L);
printf("删除成功按任意键返回~");}
getchar();break;
case4:ListLoad(L);getchar();
printf("按任意键返回~");
getchar();break;
case5:exit(1);break;
}
}
}
void Max(SqList &L)//最大优先序列实现函数
{
inti,a,e,x,choice;
while(1){
printmainmenu();
scanf("%d",&choice);
while(choice<1||choice>5) //保证用户正确操作
{
printf("\n您的输入有误,请重新选择:");
scanf("%d",&choice);
}
switch(choice) //选择菜单
{
case1: printf("请确定要录入的数据个数:");
scanf("%d",&a);
printf("inputdata:\n");
for(i=0;i<a;i++)
{
scanf("%d",&e);
ListInsert(L,1,e);
}
HeapSort2(L);
getchar();ListLoad(L);
printf("录入成功按任意键返回~");
getchar();break;
case2: if(L.length==0){printf("队列为空插入失败(按任意键返回)");getchar();}
else{printf("请输入数据:");scanf("%d",&a);
ListInsert(L,1,a);HeapSort2(L);getchar();ListLoad(L);printf("插入成功按任意键返回~");}getchar();break;
case3: ListDelete(L,1,e);
if(L.length!=0){
printf("\ndeletethe data :%d\n",e);
getchar();
ListLoad(L);
printf("删除成功按任意键返回~");}
getchar();break;
case4:ListLoad(L);getchar();
printf("按任意键返回~");
getchar();break;
case5:exit(1);break;
}
}
}
void main()
{
SqListL;
inti,a,e,x,choice;
InitList_Sq(L);
printf("OK");
system("cls");
printf("\n\t**********************模式选择****************************\n");
printf("\t*** ***\n");
printf("\t*** ***\n");
printf("\t*** 1——最大优先队列操作 ***\n");
printf("\t*** ***\n");
printf("\t*** ***\n");
printf("\t*** 2——最小优先队列操作 ***\n");
printf("\t*** ***\n");
printf("\t*** ***\n");
printf("\t*** 0——退出 ***\n");
printf("\t*** ***\n");
printf("\t*************************************************************\n");
printf("\t\t请选择您要的操作:");
scanf("%d",&x);
while(x<0||x>2) //保证用户正确操作
{
printf("\n您的输入有误,请重新选择:");
scanf("%d",&x);
}
switch(x)
{
case1:Max(L);break;
case2:Min(L);break;
case0:exit(1);break;
}
getchar();
}
测试:
选择模式界面。假设选择最大优先队列。
进入主界面,进行相关操作;
选择1,对列初始化操作,当队列数据存在时,初始化失败,不进行操作直接返回主界面。
选择2,添加数据,并显示当前队列信息;当队列为空时,插入失败,不进行操作直接返回主界面。
选择3,删除权值最大数据,并显示当前队列信息;当队列为空时,删除失败,不进行操作直接返回主界面。
选择4,显示当前队列信息(按权值由大到小排列);当队列为空时,查看失败,不进行操作直接返回主界面。
结果分析:
算法优缺点
优点在于:
1、时间复杂度小,排序稳定
2、算法思想简单易于理解编写
3、合理地利用数据数组类型的特点
4、算法主要采用板块化函数设计,相互独立,减少了个别错误影响整个系统稳定的问题。
缺点在于:
1、每次删除、查找、插入操作都必须重新进行一次堆排序