1. 程式人生 > >STL 之 priority_queue 的介紹與簡單示例

STL 之 priority_queue 的介紹與簡單示例

priority_queue 優先佇列,其底層是用堆來實現的。在優先佇列中,隊首元素一定是當前佇列中優先順序最高的那一個。

在優先佇列中,沒有 front() 函式與 back() 函式,而只能通過 top() 函式來訪問隊首元素(也可稱為堆頂元素),也就是優

先級最高的元素。基本操作有:
empty() 如果佇列為空返回真
pop() 刪除對頂元素
push() 加入一個元素
size() 返回優先佇列中擁有的元素個數
top() 返回優先佇列對頂元素


priority_queue 預設為大頂堆,即堆頂元素為堆中最大元素(比如:在預設的int型中先出隊的為較大的數)。

基本資料型別(int,double,char等可以直接使用的資料型別),優先佇列對他們的優先順序設定一般是數字大的優先順序高,因

此隊首元素就是優先佇列內元素最大的那個(如果是 char 型,則是字典序最大的)。

如果我們想要用小頂堆的話需要增加使用兩個引數:
priority_queue< int, vector<int>, greater<int> > q;  // 小頂堆
priority_queue< int, vector<int>, less<int> > q;     // 大頂堆


下面兩種優先佇列的定義是等價的
priority_queue< int > q;
priority_queue< int,vector<int>,less<int> >;

其中第二個引數( vector ),是來承載底層資料結構堆的容器,第三個引數( less ),則是一個比較類,less 表示數字大的優

先級高,而 greater 表示數字小的優先順序高。

如果需要對結構體的優先順序設定,有兩種方法:
方式一:過載運算子 ‘<’
方式二:把過載的函式寫在結構體外

 

示例程式碼:

// priority_queue_test.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <vector>
#include <queue>
#include <iostream>
#include <functional>
#include <string>
using std::vector;
using std::priority_queue;

 
//方式一(比較函式寫在結構體外面):
struct student{
	std::string name;
	int score;
	student(std::string _name = "", int _score = 0):name(_name), score(_score) {}
};

struct cmp{
	bool operator() (const student& a, const student& b ){
		return a.score > b.score;
	}
};

//方式二(過載操作符): 
struct Fruit{
	std::string name;
	double price;
	Fruit(std::string _name = "", double _price = 0):name(_name), price(_price) {}

	friend bool operator < (const Fruit left, const Fruit right ){
		return left.price > right.price;
	}
};

//輸入n個整數,找出其中最小的k個數。例如輸入8、1、7、2、6、3、5、4這8個數字,則最小的4個數字是1,2,3,4。
vector<int> GetLeastNumbers(vector<int> rawArray, int k)
{
	int size = rawArray.size();
	vector<int> ret;

	if (size == 0 || k <= 0 || k > size)
		return ret;

	priority_queue<int> _queue;
	for (int i = 0; i < size; i++) {
		if (_queue.size() < k)
			_queue.push(rawArray[i]);
		else {
			if (rawArray[i] < _queue.top()) {
				_queue.pop();
				_queue.push(rawArray[i]);
			}
		}
	}

	while (!_queue.empty()) {
		ret.push_back(_queue.top());
		_queue.pop();
	}

	reverse(ret.begin(), ret.end());

	return ret;
}

void test_priority_queue()
{
	//預設情況下,數值大的在隊首位置(降序)
	priority_queue<int> queueLess;
	//priority_queue<int, vector<int>, std::less<int>> q;//等同於priority_queue<int> q;
	for(int i  = 0;i <= 10;i ++)
		queueLess.push(i);

	while(!queueLess.empty()){
		std::cout << queueLess.top() << " ";
		queueLess.pop();
	}
	std::cout << std::endl;

	//greater<int>表示數值小的優先順序越大
	priority_queue<int, vector<int>, std::greater<int> > queueGreater;
	for(int i  = 0;i <= 10;i ++)
		queueGreater.push(i);

	while(!queueGreater.empty()){
		std::cout << queueGreater.top() << " ";
		queueGreater.pop();
	}
	std::cout << std::endl;
}

void test_priority_queue2()
{
	//
	priority_queue<student, vector<student>, cmp> nodeQueue; 
	student node1, node2, node3;
	node1.name = "tom";
	node1.score = 60;
	node2.name = "kelly";
	node2.score = 80;
	node3.name = "mary";
	node3.score = 70;
	nodeQueue.push(node1);
	nodeQueue.push(node2);
	nodeQueue.push(node3);

	while(!nodeQueue.empty()){
		std::cout << nodeQueue.top().name << " : " << nodeQueue.top().score << std::endl;
		nodeQueue.pop();
	}
}

void test_priority_queue3()
{
	//
	priority_queue<Fruit> node2Queue; 
	Fruit _node1, _node2, _node3;
	_node2.name = "banana";
	_node2.price = 3.2;
	_node1.name = "apple";
	_node1.price = 4.5;
	_node3.name = "grape";
	_node3.price = 2.1;
	node2Queue.push(_node1);
	node2Queue.push(_node2);
	node2Queue.push(_node3);

	while(!node2Queue.empty()){
		std::cout << node2Queue.top().name << " : " << node2Queue.top().price << std::endl;
		node2Queue.pop();
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	test_priority_queue();

	test_priority_queue2();

	test_priority_queue3();

	//
	vector<int> intArray;
	intArray.push_back(8);
	intArray.push_back(1);
	intArray.push_back(7);
	intArray.push_back(2);
	intArray.push_back(6);
	intArray.push_back(3);
	intArray.push_back(5);
	intArray.push_back(4);

	vector<int> rets = GetLeastNumbers(intArray, 4);
	for (int i=0; i<rets.size(); ++i){
		std::cout << rets[i] << std::endl;
	}

	system("pause");
	return 0;
}