priority_queue 详解

priority_queue 详解

  优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。
  priority_queue 是容器适配器,它提供常数时间的(默认)最大元素查找,对数代价的插入与释出。

  注意:默认情况下priority_queue是大堆。

priority_queue 接口介绍及使用

在使用优先级队列时需要包含如下头文件:

include <queue>          
using std::priority_queue

优先级队列默认是大根堆。下面的例子按大根堆进行演示,后面会讲解如何使用小根堆。

empty

  判断当前优先级队列中是否为空,若为空返回1,否则返回0。

int main ()
{
  std::priority_queue<int> mypq;
  int sum (0);

  for (int i=1;i<=10;i++) 
  	mypq.push(i);

  while (!mypq.empty())    
  {
     sum += mypq.top();
     mypq.pop();
  }

  std::cout << "total: " << sum << '\n';

  return 0;
}

size

  返回当前优先级队列中的元素个数。

int main ()
{
  std::priority_queue<int> myints;
  std::cout << "0. size: " << myints.size() << '\n';

  for (int i=0; i<5; i++) myints.push(i);
  std::cout << "1. size: " << myints.size() << '\n';

  myints.pop();
  std::cout << "2. size: " << myints.size() << '\n';

  return 0;
}

push

  将元素放入优先级队列中。

int main ()
{
  std::priority_queue<int> mypq;

  mypq.push(30);
  mypq.push(100);
  mypq.push(25);
  mypq.push(40);

  std::cout << "Popping out elements...";
  while (!mypq.empty())
  {
     std::cout << ' ' << mypq.top();
     mypq.pop();
  }
  std::cout << '\n';

  return 0;
}

emplace

  和push一样将元素放入优先级队列中。

int main ()
{
  std::priority_queue<std::string> mypq;

  mypq.emplace("orange");
  mypq.emplace("strawberry");
  mypq.emplace("apple");
  mypq.emplace("pear");

  std::cout << "mypq contains:";
  while (!mypq.empty())
  {
     std::cout << ' ' << mypq.top();
     mypq.pop();
  }
  std::cout << '\n';

  return 0;
}

push和emplace的区别:

首先: push的操作可以直接用于emplace。
两者的区别主要体现在传入对象时。

  1. 直接传入对象
//假设栈内的数据类型是data
class data {
  int a,b;
public:
  data(int x, int y):a(x), b(y) {}
};
//push
data d(1,2);
S.push(d) 
S.emplace(d);

先构造好对象后,再放入优先级队列。

  1. 在传入的时候构造对象
S.push(data(1,2)) 
S.emplace(data(1,2));

  但是,emplace可以直接传入构造对象需要的元素,然后自己调用其构造函数,而push不行。
示例如下:

S.emplace(1,2)

  emplace这样接受新对象的时候,自己会调用其构造函数生成对象然后放在容器内(比如这里传入1,2,它则会自动调用一次data(1,2))
  而push,只能让其构造函数构造好了对象之后,再使用复制构造函数!

  相当于emplace直接用原料造了一个,而push是造好了之后,再复制到自己家里,多了复制这一步

   所以emplace相对于push,会更节省内存。emplace这样接受新对象的时候,自己会调用其构造函数生成对象然后放在容器内(比如这里传入了1,2,它则会自动调用一次data(1,2))

pop

  将堆顶的元素弹出优先级队列。

int main ()
{
  std::priority_queue<int> mypq;

  mypq.push(30);
  mypq.push(100);
  mypq.push(25);
  mypq.push(40);

  std::cout << "Popping out elements...";
  while (!mypq.empty())
  {
     std::cout << ' ' << mypq.top();
     mypq.pop();
  }
  std::cout << '\n';

  return 0;
}

top

  返回堆顶的元素。

int main ()
{
  std::priority_queue<int> mypq;

  mypq.push(10);
  mypq.push(20);
  mypq.push(15);

  std::cout << "mypq.top() is now " << mypq.top() << '\n';

  return 0;
}

swap

  可以交换两个容器。

int main ()
{
  std::priority_queue<int> foo,bar;
  foo.push (15); foo.push(30); foo.push(10);
  bar.push (101); bar.push(202);

  foo.swap(bar);

  std::cout << "size of foo: " << foo.size() << '\n';
  std::cout << "size of bar: " << bar.size() << '\n';

  return 0;
}

如何使用小根堆

priority_queue 的模板

template <class T, class Container = vector<T>,
  class Compare = less<typename Container::value_type> > class priority_queue;
  • T :需要存放的数据类型(int,double,string,类等)
  • Container :使用什么样子的容器
  • Compare : 传入仿函数,默认是less< int >

大根堆:
  使用仿函数 less,将容器中的元素进行降序排列

priority_queue<int,vector<int>,less<int>>  ret //降序队列,大顶堆

  这样得到的ret容器是一个大根堆,C++默认优先级队列为大根堆,所以可以直接priority_queueret,但小根堆不行

小根堆:
  使用仿函数 greater,将容器中的元素进行升序排列

priority_queue<int,vector<int>,greater<int>> ret //升序队列,小顶堆

  这样得到的ret容器是一个小根堆

仿函数:

(部分代码已经简化)
less:
  实质上也是一个类的模板,类中重载了运算符(),以实现两个元素的比较。因为是模板,所以可以支持多种元素类型的比较。

template <class T> 
struct less {
  bool operator() (const T& x, const T& y) const 
  {
  		return x<y;
  }
}

greater:

template <class T> 
struct greater {
  bool operator() (const T& x, const T& y) const 
  {
  		return x>y;
  }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ryan.Alaskan Malamute

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值