优先队列/oriority queue 之最大优先队列的实现
优先队列(priority queue)
是一种用来维护一组数据集合S的数据结构。
每一个元素都有一个相关的值,被称为关键字key。
这里以实现最大优先队列为例子
最大优先队列支持的操作如下:
INSERT(S,x):把元素x插入集合S中
MAXIMUN(S):返回S中具有最大键字的元素。
EXTRACT-MAX(S):去掉并且返回S中具有最大键字的元素。
INCREASE-KEY(S,x,k):将元素x的关键字增加到k(k>=x)
下面对于最大优先队列的具体实现进行描述。
首先,最大优先队列是基于堆的,所以其相关的建立堆、维护堆操作在这里不赘述。详见上一篇随笔。
heap_maximun(arr,heap_size):在O(1)的时间内实现MAXIMUN(S)的操作。
int heapmax(int arr[])
{
return arr[];//返回堆顶
}
heap_extract_max(arr,heap_size):实现EXTRACT-MAX(S)的操作。吐出堆顶元素,并且把堆顶位置元素与最后一个位置的元素交换,heap_size减1,而后调用维护堆(max_heapify)函数对堆进行调整。使其在吐出一个元素之后仍然满足大根堆的性质。
int heap_extract_max(int arr[],int &heap_size)//去掉并返回arr中具有最大键字的元素
{
if(heap_size<) //
{
cout<<"heap underflow"<<endl;
return -;
}
int max_=arr[];
arr[]=arr[heap_size];
heap_size--;
max_heapify(arr,,heap_size);
return max_;
}
heap_increase_key(arr,x,k,heap_size):实现INCREASE-KEY(S,x,k)的操作。把元素x的关键字值增加到key,假设k的值不小于x原本关键字的值。在优先队列中,其元素由下标x来标识;而增大arr[i]的关键字有可能会违反最大堆的性质。所以在这个算法中,使用了【插入循环】的方式,从当前结点到根结点的路径上寻找新增关键字恰当的插入位置。
该过程会使结点x与其父结点的值比较。如果当前元素的关键字比较大,则交换当前元素与父结点元素的值。直到当前元素的关键字的值小于父元素关键字的值为止,此时已重新符合大根堆的性质。
如下图,显示了heap_increase_key的操作过程。(图截自算法导论)
int heap_increase_key(int arr[],int x,int k,int heap_size)//把元素x的关键字值增加到key,假设k的值不小于x原本关键字的值
{
if(k<arr[x])
{
cout<<"new key is smaller than current key";
}
arr[x]=k;
while(x>&&arr[x/]<arr[x])//插入值x的粑粑比崽值小,于是交换元素值
{
swap(arr[x/],arr[x]);
x=x/;
}
}
max_heap_insert:在原来队列的基础上新增一个元素。这个算法通过先增加一个值为负无穷的关键字作为叶结点来扩展最大堆,而后调用heap_increase_key来为新的结点设置对应的关键字,保持大根堆的性质。
void max_heap_insert(int arr[],int k,int &heap_size)//把元素x值插入到集合中
{
heap_size++;
arr[heap_size]=-;//通过增加一个关键字为负无穷的叶节点来扩展最大堆,这里用-1代替
heap_increase_key(arr,heap_size,k,heap_size);
}
总实现代码如下:
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;
void max_heapify(int arr[],int i,int heap_size)//维护堆
{
int largest;
int left=*i;
int right=*i+;
if(left<=heap_size&&arr[left]>arr[i]) largest=left;
else largest=i;
if(right<=heap_size&&arr[right]>arr[largest])
largest=right;
if(largest!=i)
{
swap(arr[largest],arr[i]);
max_heapify(arr,largest,heap_size);
}
}
void build_max_heap(int arr[],int length)//建立堆
{
int heap_size=length;
for(int i=length/; i>=; i--)
{
max_heapify(arr,i,heap_size);
}
}
void heapsort(int arr[],int length)
{
int heap_size=length;
build_max_heap(arr,length);
for(int i=length; i>=; i--)
{
swap(arr[],arr[i]);
heap_size--;
max_heapify(arr,,heap_size);
}
}
int heapmax(int arr[])
{
return arr[];//返回堆顶
}
int heap_extract_max(int arr[],int &heap_size)//去掉并返回arr中具有最大键字的元素
{
if(heap_size<) //
{
cout<<"heap underflow"<<endl;
return -;
}
int max_=arr[];
arr[]=arr[heap_size];
heap_size--;
max_heapify(arr,,heap_size);
return max_;
}
int heap_increase_key(int arr[],int x,int k,int heap_size)//把元素x的关键字值增加到key,假设k的值不小于x原本关键字的值
{
if(k<arr[x])
{
cout<<"new key is smaller than current key";
}
arr[x]=k;
while(x>&&arr[x/]<arr[x])//插入值x的粑粑比崽值小,于是交换元素值
{
swap(arr[x/],arr[x]);
x=x/;
}
}
void max_heap_insert(int arr[],int k,int &heap_size)//把元素x值插入到集合中
{
heap_size++;
arr[heap_size]=-;//通过增加一个关键字为负无穷的叶节点来扩展最大堆,这里用-1代替
heap_increase_key(arr,heap_size,k,heap_size);
}
void show(int arr[],int heap_size)
{
cout<<"show the heap:";
for(int i=; i<=heap_size; i++)
{
cout<<arr[i]<<" ";
}
cout<<endl;
}
int main()
{
int arr[]= {,,,,,,,,,,};
int heap_size=;
build_max_heap(arr,heap_size);//建堆
int maxn=heapmax(arr);
cout<<"the max data is:"<<maxn<<endl;
maxn=heap_extract_max(arr,heap_size);
cout<<"now the max data "<<maxn<<" was deleted."<<endl;
show(arr,heap_size);
heapsort(arr,heap_size);
cout<<"after sort and";
show(arr,heap_size);
int i=,key=;
heap_increase_key(arr,i,key,heap_size);//把堆中第i个元素的值改为key值。
max_heap_insert(arr,,heap_size);//插入新值100
show(arr,heap_size);
heapsort(arr,heap_size);
cout<<"after sort and";
show(arr,heap_size);
return ;
}
测试截图:
优先队列/oriority queue 之最大优先队列的实现的更多相关文章
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅰ
许多应用程序都需要处理有序的元素,但不一定要求他们全部有序,或者是不一定要以此就将他们排序.很多情况下我们会手机一些元素,处理当前键值最大的元素,然后再收集更多的元素,再处理当前键值最大的元素.如此这 ...
- C/C++解题常用STL大礼包 含vector,map,set,queue(含优先队列) ,stack的常用用法
每次忘记都去查,真难啊 /* C/C++解题常用STL大礼包 含vector,map,set,queue(含优先队列) ,stack的常用用法 */ /* vector常用用法 */ //头文件 #i ...
- c++ STL queue:deque+优先队列
/* queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque队列 类型.一:定义queue(要有头文件#include <qu ...
- 第二十八篇 玩转数据结构——堆(Heap)和有优先队列(Priority Queue)
1.. 优先队列(Priority Queue) 优先队列与普通队列的区别:普通队列遵循先进先出的原则:优先队列的出队顺序与入队顺序无关,与优先级相关. 优先队列可以使用队列的接口,只是在 ...
- c++ STL:队列queue、优先队列priority queue 的使用
说明:本文全文转载而来,原文链接:http://www.cppblog.com/wanghaiguang/archive/2012/06/05/177644.html C++ Queues(队列) C ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅴ
命题Q.对于一个含有N个元素的基于堆叠优先队列,插入元素操作只需要不超过(lgN + 1)次比较,删除最大元素的操作需要不超过2lgN次比较. 证明.由命题P可知,两种操作都需要在根节点和堆底之间移动 ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅳ
2.4.4 堆的算法 我们用长度为 N + 1的私有数组pq[]来表示一个大小为N的堆,我们不会使用pq[0],堆元素放在pq[1]至pq[N]中.在排序算法中,我们只能通过私有辅助函数less()和 ...
- 优先队列Priority Queue和堆Heap
对COMP20003中的Priority queue部分进行总结.图片来自于COMP20003 queue队列,顾名思义特点先进先出 priority queue优先队列,出来的顺序按照优先级prio ...
- HDU 4441 Queue Sequence(优先队列+Treap树)(2012 Asia Tianjin Regional Contest)
Problem Description There's a queue obeying the first in first out rule. Each time you can either pu ...
随机推荐
- webService之helloword(java)
webservice 远程数据交互技术 1.导入jar包(如果是 maven项目导入项目坐标) 2.创建服务 3.测试服务 我们使用maven来做测试服务 pom.xml文件 <project ...
- linux 查询搜索文件指令
一.which(寻找[执行档]) 二.whereis(由一些特定的目录中寻找文件文件名) 三.locate/updatedb 四.find 个人记录方便自用
- Beta阶段第四篇Scrum冲刺博客-Day3
1.站立式会议 提供当天站立式会议照片一张 2.每个人的工作 (有work item 的ID),并将其记录在码云项目管理中: 昨天已完成的工作. 张晨晨:学习新的测试模块需要的东西 郭琪容:学习复习模 ...
- Codeforces Round #298 (Div. 2)--D. Handshakes
#include <stdio.h> #include <algorithm> #include <set> using namespace std; #defin ...
- 锁——Java同步的基本思想
翻译人员: 铁锚 翻译时间: 2013年11月13日 原文链接: Monitors – The Basic Idea of Java synchronization 如果你上过操作系统课程,你就知道 ...
- nginx实现unigui群集
nginx实现unigui群集 在笔者写此文的时候,UNIGUI1.50.x的版本已经发布,其提供的HyperServer已经支持群集. 有网友还专门为此做了群集方面的测试: 从上图可以看出:群集总共 ...
- [杂谈] 一个关于 as 的小测试
代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 procedure TForm1.Button1Click(Sender: TObject); va ...
- Git之初识
我的Github地址:https://github.com/shinianzongjishinianxin 初见总是美好的,可是我第一次看到github有点纠结,因为看不懂,然而最终半蒙半猜还是注册完 ...
- EFCore2.1中DbFirst和CodeFirst简单使用
EFCore中没有DbFirst了吧,应该都是Code First 先说说第一种,Code First From Database(DbFirst)数据库先行,这种方式就要命令行了...(特不喜欢命令 ...
- Java基础巩固计划
3.26-4.1 JVM 虚拟机的内容写五篇博客 解决以下问题: 1. Java的内存模型以及GC算法 2. jvm性能调优都做了什么 3. 介绍JVM中7个区域,然后把每个区域可能造成内存的溢出的情 ...