优先队列(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 之最大优先队列的实现的更多相关文章

  1. 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅰ

    许多应用程序都需要处理有序的元素,但不一定要求他们全部有序,或者是不一定要以此就将他们排序.很多情况下我们会手机一些元素,处理当前键值最大的元素,然后再收集更多的元素,再处理当前键值最大的元素.如此这 ...

  2. C/C++解题常用STL大礼包 含vector,map,set,queue(含优先队列) ,stack的常用用法

    每次忘记都去查,真难啊 /* C/C++解题常用STL大礼包 含vector,map,set,queue(含优先队列) ,stack的常用用法 */ /* vector常用用法 */ //头文件 #i ...

  3. c++ STL queue:deque+优先队列

    /* queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque队列   类型.一:定义queue(要有头文件#include <qu ...

  4. 第二十八篇 玩转数据结构——堆(Heap)和有优先队列(Priority Queue)

          1.. 优先队列(Priority Queue) 优先队列与普通队列的区别:普通队列遵循先进先出的原则:优先队列的出队顺序与入队顺序无关,与优先级相关. 优先队列可以使用队列的接口,只是在 ...

  5. c++ STL:队列queue、优先队列priority queue 的使用

    说明:本文全文转载而来,原文链接:http://www.cppblog.com/wanghaiguang/archive/2012/06/05/177644.html C++ Queues(队列) C ...

  6. 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅴ

    命题Q.对于一个含有N个元素的基于堆叠优先队列,插入元素操作只需要不超过(lgN + 1)次比较,删除最大元素的操作需要不超过2lgN次比较. 证明.由命题P可知,两种操作都需要在根节点和堆底之间移动 ...

  7. 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅳ

    2.4.4 堆的算法 我们用长度为 N + 1的私有数组pq[]来表示一个大小为N的堆,我们不会使用pq[0],堆元素放在pq[1]至pq[N]中.在排序算法中,我们只能通过私有辅助函数less()和 ...

  8. 优先队列Priority Queue和堆Heap

    对COMP20003中的Priority queue部分进行总结.图片来自于COMP20003 queue队列,顾名思义特点先进先出 priority queue优先队列,出来的顺序按照优先级prio ...

  9. 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 ...

随机推荐

  1. 为什么要重写hashCode()方法和equals()方法及如何重写

    我想写的问题有三个: 1.首先我们为什么需要重写hashCode()方法和equals()方法 2.在什么情况下需要重写hashCode()方法和equals()方法 3.如何重写这两个方法 **** ...

  2. linux grep进阶

    1.搜寻特定字符串 搜寻特定字符串很简单吧?假设我们要从刚刚的文件当中取得 the 这个特定字符串,最简单的方式就是这样: 那如果想要『反向选择』呢?也就是说,当该行没有 'the' 这个字符串时才显 ...

  3. 用 gdb 调试 GCC 程序

    Linux 包含了一个叫 gdb 的 GNU 调试程序. gdb 是一个用来调试 C 和 C++ 程序的强力调试器. 它使你能在程序运行时观察程序的内部结构和内存的使用情况. 以下是 gdb 所提供的 ...

  4. Hdu2841 Visible Trees 2017-06-27 22:13 24人阅读 评论(0) 收藏

    Visible Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  5. Mahout简介

    Mahout简介 一.mahout是什么 Apache Mahout是ApacheSoftware Foundation (ASF)旗下的一个开源项目,提供了一些经典的机器学习的算法,皆在帮助开发人员 ...

  6. bootstrap4.2 导航搜索框

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  7. Nvu

    在Jennifer Niederst Robbins的书<Learning Web design>(密码:v9i1)推荐软件Nvu 界面: Nvu tips:

  8. Windows安装配置docker

    如果是win10的,请在https://docs.docker.com/docker-for-windows/install/#download-docker-for-windows 下载Stable ...

  9. ASP .Net C# ---Excel导入导出方法

    导入导出的方法以及引用,可以自行创建一个帮助类 using System;using NPOI.SS.UserModel;using NPOI.XSSF.UserModel;using NPOI.HS ...

  10. 【转】JS浮点数运算Bug的解决办法

    37.5*5.5=206.08 (JS算出来是这样的一个结果,我四舍五入取两位小数) 我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998 怎么会这样,两个只有一 ...