Priority Queue(Heap)的实现及其应用

本文介绍了一种基于堆实现的优先队列数据结构,并通过两个实际应用案例——堆排序和在数组中查找第k大的数进行了说明。优先队列不需要遵循FIFO原则,主要操作包括插入新记录和移除最大元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

优先队列严格说实际上不是一种队列,因为它并不需要遵循队列的FIFO特性,而要求的基本操作包括:向队列中插入新的记录,以及移出队列中的最大的元素。我们可以以各种不同的方式来实现优先队列——只要能够满足上面的两个接口就可以了。但是基于堆的优先队列则具有较好的性能。

优先队列是一种很有用的数据结构,因为实际上我们不是每时每刻都需要对数据进行严格的排序,有时候我们仅仅能够获得最大的元素的即可,但是如果以顺序查找的方式实现的话,效率上根本满足不了要求。而堆则提供了一种较高效率的实现策略。

这里给出一个最小堆的实现,并且结合两个应用进行说明,一个是堆排序,一个是在n个数中寻找第k大的数。

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->template<typenameT>
classCPriorityQueue
ExpandedBlockStart.gifContractedBlock.gif
{//优先队列类
public:
CPriorityQueue(
intmaxElements=0);
CPriorityQueue(T
*data,intn);
~CPriorityQueue(void);
voidInsert(constT&num);//插入优先队列
TDeleteMin();//返回最小值
boolisEmpty()const;//是否空队列
boolisFull()const;//是否已经满了
private:
intcapicity;//容量
intsize;//当前大小
T*elements;//元素存储区
voidinit(intn);//初始化
voiddestroy();//销毁优先队列
}
;

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->#include"stdafx.h"
#include
<cstdlib>
#include
"PriorityQueue.h"
#include
<iostream>
usingnamespacestd;

template
<typenameT>
voidCPriorityQueue<T>::init(intn)
ExpandedBlockStart.gifContractedBlock.gif
{//初始化
this->elements=newT[n+1];
this->capicity=n;
this->size=0;
}

template
<typenameT>
CPriorityQueue
<T>::CPriorityQueue(intmaxElements)
ExpandedBlockStart.gifContractedBlock.gif
{
this->init(maxElements);
}

template
<typenameT>
CPriorityQueue
<T>::CPriorityQueue(T*data,intn)
ExpandedBlockStart.gifContractedBlock.gif
{
this->init(n);
for(inti=0;i<n;++i)
ExpandedSubBlockStart.gifContractedSubBlock.gif
{
this->Insert(data[i]);
}

}

template
<typenameT>
voidCPriorityQueue<T>::destroy()
ExpandedBlockStart.gifContractedBlock.gif
{//销毁优先队列
if(this->elements!=NULL)
ExpandedSubBlockStart.gifContractedSubBlock.gif
{
delete[]elements;
this->elements=NULL;
this->size=0;
}

}

template
<typenameT>
CPriorityQueue
<T>::~CPriorityQueue(void)
ExpandedBlockStart.gifContractedBlock.gif
{
this->destroy();
}

template
<typenameT>
boolCPriorityQueue<T>::isEmpty()const
ExpandedBlockStart.gifContractedBlock.gif
{
returnthis->size==0;
}

template
<typenameT>
boolCPriorityQueue<T>::isFull()const
ExpandedBlockStart.gifContractedBlock.gif
{
returnthis->size==this->capicity;
}

template
<typenameT>
voidCPriorityQueue<T>::Insert(constT&num)
ExpandedBlockStart.gifContractedBlock.gif
{//入队列
if(!this->isFull())
ExpandedSubBlockStart.gifContractedSubBlock.gif
{
inti;
for(i=++this->size;num<this->elements[i/2];i/=2)
this->elements[i]=this->elements[i/2];
this->elements[i]=num;
}

}

template
<typenameT>
TCPriorityQueue
<T>::DeleteMin()
ExpandedBlockStart.gifContractedBlock.gif
{
TminElement,lastElement;
inti,child;
if(!this->isEmpty())
ExpandedSubBlockStart.gifContractedSubBlock.gif
{
minElement
=this->elements[1];//最小的
lastElement=this->elements[this->size--];//最后一个元素
for(i=1;i*2<=this->size;i=child)
ExpandedSubBlockStart.gifContractedSubBlock.gif
{
child
=i*2;
if(child!=this->size&&this->elements[child+1]<this->elements[child])
child
++;
if(lastElement>this->elements[child])
ExpandedSubBlockStart.gifContractedSubBlock.gif
{
this->elements[i]=this->elements[child];
}

else
break;
}

this->elements[i]=lastElement;
returnminElement;
}

returnthis->elements[0];//失败
}

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->//Test.cpp:Definestheentrypointfortheconsoleapplication.
//
ExpandedBlockStart.gifContractedBlock.gif
/**//*
**author:phinecos
**date:7/19/2008
*/

#include
"stdafx.h"
#include
"PriorityQueue.cpp"
#include
<iostream>
usingnamespacestd;

voidprintArray(int*data,intn)
ExpandedBlockStart.gifContractedBlock.gif
{
inti;
for(i=0;i<n;++i)
ExpandedSubBlockStart.gifContractedSubBlock.gif
{
cout
<<data[i]<<"";
}

cout
<<endl;
}

voidHeapSort(int*data,intn)
ExpandedBlockStart.gifContractedBlock.gif
{//堆排序
CPriorityQueue<int>*pQueue=newCPriorityQueue<int>(data,n);
inti;
for(i=0;i<n;++i)
ExpandedSubBlockStart.gifContractedSubBlock.gif
{
data[i]
=pQueue->DeleteMin();
}

deletepQueue;
}

intFindKthMax(int*data,intn,intk)
ExpandedBlockStart.gifContractedBlock.gif
{//在n个数中找第k大的数
CPriorityQueue<int>*pQueue=newCPriorityQueue<int>(data,n);
inti,result;
for(i=0;i<k;++i)
ExpandedSubBlockStart.gifContractedSubBlock.gif
{
result
=pQueue->DeleteMin();
}

deletepQueue;
returnresult;
}

intmain(intargc,char*argv[])
ExpandedBlockStart.gifContractedBlock.gif
{
ExpandedSubBlockStart.gifContractedSubBlock.gif
inta[]={10,32,55,41,39,12,11,15,20,19,21,22,29,25};
intlen=sizeof(a)/sizeof(int);
//堆排序演示
cout<<"排序前:"<<endl;
printArray(a,len);
HeapSort(a,len);
cout
<<"排序后:"<<endl;
printArray(a,len);
//寻找第k大数演示
cout<<"请输入k下标:"<<endl;
intk;
cin
>>k;
cout
<<"第k大数是:"<<FindKthMax(a,len,k)<<endl;
system(
"pause");
return0;
}

注意VS2008不支持将模板的声明和实现分开在.h.cpp中分别实现,总是会报“unresolved external symbol”的错误!这是由于模板具体实例化的特殊因素,导致编译器对分离模式的实现有巨大的复杂度,因而,分离模式至今未能获得大多数编译器的支持。所以在目前的编译环境下,请把模板的声明与定义全部放在.h文件中!否则,视不同的编译器,将会有不可预见的编译及链接错误生成。但我们可以直接include进来cpp文件以骗过编译器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值