<C/C++算法>最大优先队列

一,最大优先级队列基本概念

最大优先队列不是一种普通的先进先出队列(和队列一样),它维护的元素有个优先级属性,不管如何进队列,出列队的都是优先级最大的元素!通常应用在计算机的分时调度,最小生成树的Prim算法等。

在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象。最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话。在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue) 。优先级队列中有多个事件发生,每个事件有自己独立的优先级,优先级是非负数,数值越大优先级越高。采用最大优先级队列模拟事件执行的优先顺序。


1,最大优先级队列的操作

(1)HEAP_MAXIMUM

用O(1)时间实现MAXIMUM(S)操作,即返回最大堆第一个元素的值即可(return A[1])。


(2)HEAP_EXTRACT_MAX

实现EXTRACT_MAX操作,删除最大堆中第一个元素,然后调整堆。操作过程如下:将最堆中最后一个元素复制到第一个位置,删除最后一个节点(将堆的大小减少1),然后从第一个节点位置开始调整堆,使得称为新的最大堆。伪代码如下:


(3)HEAP_INCREASE_KEY

实现INCREASE_KEY,通过下标来标识要增加的元素的优先级key,增加元素后需要调整堆,从该节点的父节点开始自顶向上调整。


(4)MAX_HEAP_INSERT

实现INSERT操作,向最大堆中插入新的关键字。新的关键字插入在优先级的队尾部,然后从尾部的父节点开始自顶向上调整堆.


二,最大优先级队列C++实现

注:本代码基于最大堆

1,Heap.h实现

#include "stdafx.h"
#include "iostream"
#include "vector"
using namespace std;

template <typename DataType>  
class Heap
{
public:
	Heap(int size)
	{
		heapSize=size;
		nLen=0;
		a=new DataType[size];
		if (a==NULL)
		{
			exit(1);
		}
	}
	~Heap()
	{
		if (a!=NULL)
		{
			delete a;
			a=NULL;
		}
		
	}
	int Left(int i)
	{     
		return 2*i+1;  
	}
	
	int Right(int i)
	{     
		return 2*i+2;  
	} 

	int Parent(int i)
	{     
		return i/2;  
	} 

	void swap(DataType *a,DataType *b)
	{
		DataType temp;
		temp=*a;
		*a=*b;
		*b=temp;
	}
	void KeepMaxHeap(int i,int heapsize);
	void BuildMaxHeap();
	void HeapSort();
	void InitArr(); 
	void printArray();
	void HeapIncreaseKey(int i,DataType key);
	DataType HeapMax();
	DataType HeapExtractMax();
private:
	int heapSize;
	int nLen;
	DataType *a;
};
 

template <typename DataType>      
void Heap<DataType>::InitArr()  
{  
	for (int i=0;i < heapSize;i++)  
	{  
		int key=rand()%10;
		a[i]=key;  
		nLen++;
	}  
}

//打印数组  
template <typename DataType>    
void  Heap<DataType>::printArray()  
{  
 
	cout<<"当前数组结果为: ";  
	for ( int i = 0; i < nLen; i++ )    
	{  
		cout << a[ i ]<<" ";    
		if ((i+1)%10 == 0)  
		{  
			cout<<endl;  
		}  
	}  
	cout<<endl;   
} 
//保持堆的性质  
//使a[i]这个元素下降(如果不满足最大根要求的话)    
template <typename DataType>      
void  Heap<DataType>::KeepMaxHeap( int i,int hpsize) 
{     
	int l=Left(i);  
	int r=Right(i);  
	int largest=0;   

	if (l<= hpsize && a[l]>a[i])//与左子比  
	{  
		largest=l;  
	}  
	else  
	{  
		largest=i;  
	}  

	if (r <= hpsize && a[r]> a[largest])//将较大者与右子比  
	{  
		largest=r;  
	}    
  
	if (largest!=i)  
	{  
		swap(&a[i],&a[largest]);  
		KeepMaxHeap(largest,hpsize);  
	}  
}  

//创建堆,将数组调整为最大堆  
template <typename DataType>      
void  Heap<DataType>::BuildMaxHeap()      
{     
	heapSize=nLen-1;  
	for (int i=heapSize/2 ; i>=0 ;i-- )  
	{  
		//heapsize/2+1到a.size-1的整数都是树叶,所以只需对0到heapsize/2作处理
		KeepMaxHeap(i,heapSize);  
	}  
}  

//堆排序  
template <typename DataType>      
void  Heap<DataType>::HeapSort()      
{     
	BuildMaxHeap();//使数组成为最大堆  
	heapSize=nLen-1;  
	for (int i=heapSize;i>0;i--)  
	{  
		swap(&a[0],&a[i]);  
		heapSize--;  
		KeepMaxHeap(0,heapSize);//保持堆的性质  
	}  
}  

template <typename DataType>   
DataType  Heap<DataType>::HeapMax()
{
	return this->a[0];
}

template <typename DataType>   
DataType  Heap<DataType>::HeapExtractMax()
{
	if (0 >= nLen )
	{
		cerr<<"Heap UnderFlow"<<endl;
	}
	DataType max=a[0];
	a[0]=a[heapSize];
	heapSize--;
	KeepMaxHeap(0,heapSize);
	return max;
}


template <typename DataType>   
void  Heap<DataType>:: HeapIncreaseKey(int i,DataType key)
{
	if (key < a[i])
	{
		cerr<<"新的值key比原值更小"<<endl;
	}
	a[i]=key;
	while (i>1&&a[Parent(i)]<a[i])
	{
		swap(&a[i],&a[Parent(i)]);
		i=Parent(i);
	}
}



2,主测试程序

// ConsoleAppPriorityQueue.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Heap.h"
#include "iostream"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	system("color 0A");
	Heap<int> hp(10);
	hp.InitArr();
	hp.printArray();
	//hp.HeapSort();
	//hp.printArray();
	hp.BuildMaxHeap();

	int bb=hp.HeapExtractMax();
	cout<<"去掉并获取当前堆中最大值:"<<bb<<endl;

	int cc=hp.HeapExtractMax();
	cout<<"去掉并获取当前堆中最大值:"<<cc<<endl;

	int cc1=hp.HeapExtractMax();
	cout<<"去掉并获取当前堆中最大值:"<<cc1<<endl;

	int cc2=hp.HeapExtractMax();
	cout<<"去掉并获取当前堆中最大值:"<<cc2<<endl;

	int aa=hp.HeapMax();
	cout<<"获取当前堆中最大值:"<<aa<<endl;

	aa=hp.HeapMax();
	cout<<"再次取当前堆最大值:"<<aa<<endl;

	hp.HeapIncreaseKey(0,10);
	aa=hp.HeapMax();
	cout<<"获取当前堆位置为0,且被增加到10的元素:"<<aa<<endl;

	system("pause");
	return 0;
}

3,测试结果




注:

本文部分文字学习并copy自网络,代码参考并改编自算法导论.

如果侵犯了您的版权,请联系本人tangyibiao520@163.com,本人将及时编辑掉!


参考资源:

【1】《维基百科》
【2】《算法导论》
【3】http://www.cnblogs.com/Anker/archive/2013/01/23/2873951.html
【4】《STL源码剥析》侯捷著



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值