标准库priority_queue的一种实现

优先级队列相对于普通队列,提供了插队功能,每次最先出队的不是最先入队的元素,而是优先级最高的元素。

它的实现采用了标准库提供的heap算法。该系列算法一共提供了四个函数。使用方式如下:

首先,建立一个容器,放入元素:

vector<int> coll;
insertNums(coll, 3, 7);
insertNums(coll, 5, 9);
insertNums(coll, 1, 4);

printElems(coll, "all elements: ");

打印结果为:

all elements:
3 4 5 6 7 5 6 7 8 9 1 2 3 4

然后我们调用make_heap,这个算法把[beg, end)内的元素建立成堆

make_heap(coll.begin(), coll.end());

printElems(coll, "after make_heap: ");

打印结果:

after make_heap:
9 8 6 7 7 5 5 3 6 4 1 2 3 4

然后我们调用pop_heap,这个算法必须保证[beg, end)已经是一个heap,然后它将堆顶的元素(其实是begin指向的元素)放到最后,再把[begin. end-1)内的元素重新调整为heap

pop_heap(coll.begin(), coll.end());
coll.pop_back();
printElems(coll, "after pop_heap: ");

打印结果为:

after pop_heap:
8 7 6 7 4 5 5 3 6 4 1 2 3

接下来我们调用push_heap,该算法必须保证[beg, end-1)已经是一个heap,然后将整个[beg, end)调整为heap

coll.push_back(17);
push_heap(coll.begin(), coll.end());

printElems(coll, "after push_heap: ");

打印结果为:

after push_heap:
17 7 8 7 4 5 6 3 6 4 1 2 3 5

最后我们使用sort_heap将[beg, end)由heap转化为有序序列,所以,前提是[beg, end)已经是一个heap

sort_heap(coll.begin(), coll.end());
printElems(coll, "after sort_heap: ");

打印结果为:

after sort_heap:
1 2 3 3 4 4 5 5 6 6 7 7 8 17

完整的测试代码如下:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

template <typename T>
void insertNums(T &t, int beg, int end)
{
    while(beg <= end)
    {
        t.insert(t.end(), beg);
        ++beg;
    }
}

template <typename T>
void printElems(const T &t, const string &s = "")
{
    cout << s << endl;
    for(typename T::const_iterator it = t.begin();
        it != t.end();
        ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
}

int main(int argc, char const *argv[])
{
    vector<int> coll;
    insertNums(coll, 3, 7);
    insertNums(coll, 5, 9);
    insertNums(coll, 1, 4);

    printElems(coll, "all elements: ");

    //在这个范围内构造heap
    make_heap(coll.begin(), coll.end());

    printElems(coll, "after make_heap: ");

    //将堆首放到最后一个位置,其余位置调整成堆
    pop_heap(coll.begin(), coll.end());
    coll.pop_back();
    printElems(coll, "after pop_heap: ");

    coll.push_back(17);
    push_heap(coll.begin(), coll.end());

    printElems(coll, "after push_heap: ");

    sort_heap(coll.begin(), coll.end());
    printElems(coll, "after sort_heap: ");

    return 0;
}

 

根据以上的算法,我们来实现标准库的优先级队列priority_queue,代码如下:

#ifndef PRIORITY_QUEUE_HPP
#define PRIORITY_QUEUE_HPP

#include <vector>
#include <algorithm>
#include <functional>

template <typename T,
          typename Container = std::vector<T>,
          typename Compare = std::less<typename Container::value_type> >
class PriorityQueue
{
public:
    typedef typename Container::value_type value_type; //不用T
    typedef typename Container::size_type size_type;
    typedef Container container_type;
    typedef value_type &reference;
    typedef const value_type &const_reference;

    PriorityQueue(const Compare& comp = Compare(),
                  const Container& ctnr = Container());
    template <class InputIterator>
    PriorityQueue (InputIterator first, InputIterator last,
                   const Compare& comp = Compare(),
                   const Container& ctnr = Container());
    void push(const value_type &val)
    {
        cont_.push_back(val);
        //调整最后一个元素入堆
        std::push_heap(cont_.begin(), cont_.end(), comp_);
    }

    void pop()
    {
        //第一个元素移出堆,放在最后
        std::pop_heap(cont_.begin(), cont_.end(), comp_);
        cont_.pop_back();
    }

    bool empty() const { return cont_.empty(); }
    size_type size() const { return cont_.size(); }
    const_reference top() const { return cont_.front(); }

private:
    Compare comp_; //比较规则
    Container cont_; //内部容器
};

template <typename T, typename Container, typename Compare>
PriorityQueue<T, Container, Compare>::PriorityQueue(const Compare& comp,
                                                    const Container& ctnr)
    :comp_(comp), cont_(ctnr)
{
    std::make_heap(cont_.begin(), cont_.end(), comp_); //建堆
}

template <typename T, typename Container, typename Compare>
template <class InputIterator>
PriorityQueue<T, Container, Compare>::PriorityQueue (InputIterator first,
                                                     InputIterator last,
                                                     const Compare& comp,
                                                     const Container& ctnr)
    :comp_(comp), cont_(ctnr)
{
    cont_.insert(cont_.end(), first, last);
    std::make_heap(cont_.begin(), cont_.end(), comp_);
}

#endif //PRIORITY_QUEUE_HPP

我们注意到:

1.优先级队列内部保存了排序规则,这与map和set是一致的。

2.前面我们提到heap算法除了make_heap之外,都必须保证之前是一个建好的heap,这里我们在构造函数中调用make_heap,保证了后面的各种heap算法都是合法的。

3.还有一点,如果T与容器的类型不一致,例如PriorityQueue<float, vector<int> >,那么我们的value_type优先采用int,毕竟我们操作的对象是容器。

测试代码如下:

#include "PriorityQueue.hpp"
#include <iostream>
using namespace std;

int main(int argc, char const *argv[])
{
    PriorityQueue<float> q;
    q.push(66.6);
    q.push(22.3);
    q.push(44.4);

    cout << q.top() << endl;
    q.pop();
    cout << q.top() << endl;
    q.pop();

    q.push(11.1);
    q.push(55.5);
    q.push(33.3);
    q.pop();

    while(!q.empty())
    {
        cout << q.top() << " ";
        q.pop();
    }
    cout << endl;

    return 0;
}
时间: 2025-01-02 22:20:24

标准库priority_queue的一种实现的相关文章

标准库Stack的一种实现

本文实现了STL中stack的大部分功能,同时添加了一些功能. 注意以下几点: 1.Stack是一种适配器,底层以vector.list.deque等实现 2.Stack不含有迭代器 在本例中,我添加了几项功能,包括不同类型stack之间的复制和赋值功能,可以实现诸如Stack<int, vector<int> >和Stack<double, list<double> >之间的复制和赋值,这主要依靠成员函数模板来实现. 为了更方便的实现以上功能,我添加了一个

C++ 异常机制分析(C++标准库定义了12种异常,很多大公司的C++编码规范也是明确禁止使用异常的,如google、Qt)

阅读目录 C++异常机制概述 throw 关键字 异常对象 catch 关键字 栈展开.RAII 异常机制与构造函数 异常机制与析构函数 noexcept修饰符与noexcept操作符 异常处理的性能分析 正文 回到顶部 C++异常机制概述 异常处理是C++的一项语言机制,用于在程序中处理异常事件.异常事件在C++中表示为异常对象.异常事件发生时,程序使用throw关键字抛出异常表达式,抛出点称为异常出现点,由操作系统为程序设置当前异常对象,然后执行程序的当前异常处理代码块,在包含了异常出现点的

三种标准库链接方式

Linux 应用程序因为 Linux 版本的众多与各自独立性,在工程制作与使用中必须熟练掌握如下两点才能有效地工作和理想地运行.1.Linux 下标准库链接的三种方式(全静态 , 半静态 (libgcc,libstdc++), 全动态)及其各自利弊.2.Linux 下如何巧妙构建 achrive(*.a),并且如何设置链接选项来解决 gcc 比较特别的链接库的顺序问题.全静态:1.-static -pthread -lrt -ldl2.不会发生应用程序在 不同 Linux 版本下的标准库不兼容问

C++ Primer 第四版读书笔记(二)之标准库类型

C++定义了一个内容丰富的抽象数据类型标准库,其中最重要的标准库类型是string和vector,它们分别定义了大小可变的字符串和集合.string和vector往往将迭代器用作配套类型,用于访问string中的字符,或者vector中的元素. 另一种标准库类型为bitset,提供了一种抽象方法来操作位的集合. string类型支持长度可变的字符串,vector用于保存一组指定类型的对象. bitset类标准库类型提供了更方便和合理有效的语言级的抽象设施.通过这个类可以把某个值当作位的集合来处理

Python标准库:1. 介绍

标准库包含了几种不同类型的库. 首先是那些核心语言的数据类型库,比如数字和列表相关的库.在核心语言手册里只是描述数字和列表的编写方式,以及它的排列,而没有定义它的语义.换一句话说,核心语言手册只是定义语法和优先级之类,并没有定义对这些类型的功能上的操作. 其次标准库包含了一些内置函数和异常处理对象,在使用这些对象时,并不需要明确使用import语句进行导入.其中有一些是核心语言需要的,但很多不是核心语言需要的,也在这里描述. 最后在标准库里大量的库都是这样的一些功能模块,可以有多种方式来分类.比

【C++ Primer每日一刷之五】标准库类型小结

标准库类型小结 C++ 标准库定义了几种更高级的抽象数据类型,包括 string 和 vector 类型.string 类型提供了变长的字符串,而 vector 类型则可用于管理同一类型 的对象集合.迭代器实现了对存储于容器中对象的间接访问.迭代器可以用于访问和遍历 string 类型和vectors 类型的元素.下一节将介绍 C++ 的内置数据类型:数组和指针.这两种类型提供了类似于 vector 和 string 标准库类型的低级抽象类型.总的来说,相对于C++ 内置数据类型的数组和指针而言

[C/C++标准库]_[优先队列priority_queue的使用]

std::priority_queue 场景: 1. 对于一个任务队列,任务的优先级由任务的priority属性指明,这时候就需要优先级越高的先执行.而queue并没有排序功能,这时priority_queue是比较好的选择. 2 对于异步的task也是一样,在不断添加新的task时,当然希望优先级越高的先执行. 解析: 1. 如果需要把优先级最高的先pop,那么comp比较时需要返回false. 代码: //1.Elements are popped from the "back"

谈谈两种标准库类型---string和vector

两种最重要的标准库---string和vector string和vector是两种最重要的标准库类型,string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列. 一.标准库类型string   1.定义和初始化string对象:初始化string对象的方式有 string s1   默认初始化,s1是一个空串   string s2(s1)   s2是s1的副本 string s2=s1   等价于s2(s1),s2是s1的副本 string s3("value&qu

日月累积的整理!140种Python标准库、第三方库和外部工具都有了

Python数据工具箱涵盖从数据源到数据可视化的完整流程中涉及到的常用库.函数和外部工具.其中既有Python内置函数和标准库,又有第三方库和工具. 读者福利,想要了解python人工智能可直接点击链接即可领取相关学习福利包:石墨文档 是安全网站放心,继续访问就可以领取了哦 这些库可用于文件读写.网络抓取和解析.数据连接.数清洗转换.数据计算和统计分析.图像和视频处理.音频处理.数据挖掘/机器学习/深度学习.数据可视化.交互学习和集成开发以及其他Python协同数据工作工具. 为了区分不同对象的