优先队列/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 ...
随机推荐
- GIS矢量数据化简:一种改进的道格拉斯-普克算法以及C++实现
GIS领域的同志都知道,传统的道格拉斯-普克算法都是递归实现.然而有时候递归的层次太深的话会出现栈溢出的情况.在此,介绍一种非递归的算法. 要将递归算法改为非递归算法,一般情况下分为两种场景.第一种是 ...
- python一键升级所有第三方库
import pip from subprocess import call for dist in pip.get_installed_distributions(): call("pip ...
- spoj high
matrixtree定理裸体,学了行列式的n^3解法,(应该是能应用于所有行列式): 代码是参考某篇题解的... #include<iostream> #include<cstrin ...
- (最大上升子序列)Monkey and Banana -- hdu -- 1069
http://acm.hdu.edu.cn/showproblem.php?pid=1069 Monkey and Banana Time Limit:1000MS Memory L ...
- java基础-day6
第06天 java基础语法 今日内容介绍 u Eclipse断点调试 u 基础语法的练习 第1章 Eclipse断点调试 1.1 Eclipse断点调试概述 Eclipse的断点调试可以 ...
- 【译】Surface中你也许不知道的五件事
Bring up the Quick Link Menu - Select the Windows Key + X or right click the Start Button to bring u ...
- 《mysql必知必会》学习_第八章_20180730_欢
第八章学习LIKE操作符,百分百(%)通配符,下划线(_)通配符 P47 select prod_id,prod_name from products where prod_name LIKE 'je ...
- hdu 1226 超级密码
超级密码 Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem D ...
- GDI+配置
GDI+的配置过程: 一.打开stdafx.h文件,在其中加入: #include "Gdiplus.h" #pragma comment(lib,"Gdiplus.h& ...
- VisualSVN 破解方法
第一步,首先准备反汇编工具 ildasm.exe,找到VisualSVN的安装路径,一般先备份,在备份里面操作. 第二步,转储 , 得到同名的il文件:VisualSVN.Core.L.il,用记事本 ...