优先队列

C++ Priority Queue(优先队列)


C++优先队列类似队列,但是在这个数据结构中的元素按照一定的断言排列有序。它的头文件为<queue>。由于适配器不支持迭代,一个 priority_queue 将有没有关联的迭代器。

函数列表:
empty() 如果优先队列为空,则返回真
pop() 删除第一个元素
push() 加入一个元素
size() 返回优先队列中拥有的元素的个数
top() 返回优先队列中有最高优先级的元素

/////////////////////////////////////////////////////////////////////////////////////

构造函数
explicit priority_queue(const Pred& pr = Pred(),
const allocator_type& al = allocator_type());
priority_queue(const value_type *first, const value_type *last,
const Pred& pr = Pred(), const allocator_type& al = allocator_type());

empty
语法:
bool empty();
empty()函数返回真(true)如果优先队列为空,否则返回假(false)。
pop
语法:
void pop();
pop()函数删除优先队列中的第一个元素。
push
语法:
void push( const TYPE &val );
push()函数添加一个元素到优先队列中,值为val。
size
语法:
size_type size();
size()函数返回优先队列中存储的元素个数。
top
语法:
TYPE &top();
top()返回一个引用,指向优先队列中有最高优先级的元素。注意只有pop()函数删除一个元素。
示例1:
#include <iostream>
#include <queue>
#include <deque>
#include <vector>
#include <functional>
using namespace std;

#if _MSC_VER > 1020 // if VC++ version is > 4.2
using namespace std; // std c++ libs implemented in std
#endif

// Using priority_queue with deque
// Use of function greater sorts the items in ascending order
typedef deque<int, allocator<int> > INTDQU;
typedef priority_queue<int,INTDQU, greater<int> > INTPRQUE;

// Using priority_queue with vector
// Use of function less sorts the items in descending order
typedef vector<char, allocator<char> > CHVECTOR;
typedef priority_queue<char,CHVECTOR,less<char> > CHPRQUE;

void main(void)
{

int size_q;
INTPRQUE q;
CHPRQUE p;

// Insert items in the priority_queue(uses deque)
q.push(42);
q.push(100);
q.push(49);
q.push(201);

// Output the item at the top using top()
cout << q.top() << endl;
// Output the size of priority_queue
size_q = q.size();
cout << "size of q is:" << size_q << endl;
// Output items in priority_queue using top()
// and use pop() to get to next item until
// priority_queue is empty
while (!q.empty())
{
cout << q.top() << endl;
q.pop();
}

// Insert items in the priority_queue(uses vector)
p.push('c');
p.push('a');
p.push('d');
p.push('m');
p.push('h');

// Output the item at the top using top()
cout << p.top() << endl;

// Output the size of priority_queue
size_q = p.size();
cout << "size of p is:" << size_q << endl;

// Output items in priority_queue using top()
// and use pop() to get to next item until
// priority_queue is empty
while (!p.empty())
{
cout << p.top() << endl;
p.pop();
}
}
输出结果:
42
size of q is:4
42
49
100
201
m
size of p is:5
m
h
d
c
a

示例2:
#include<iostream>
#include<queue>
using namespace std;
struct cmp
{
bool operator()(const int &a,const int &b)

{
return a<b;//按升序排序

}
};
typedef priority_queue< int, vector<int>, cmp > qu;
void main()
{
qu p;
p.push(42);
p.push(100);
p.push(49);
p.push(201);
while (!p.empty())
{
cout << p.top() << endl;
p.pop();
}
}
输出结果:
201
100
49
42

示例3(用priority_queue实现哈夫曼树):
#include<iostream>
#include<queue>
using namespace std;
class Node
{
public:
int weight;
Node* left;
Node* right;
Node(int w, Node* l, Node* r): weight(w), left(l), right(r) {}
Node(int w): weight(w), left(NULL), right(NULL) {}
};

class cmp //用于priority_queue的仿函数类
{
public :
bool operator()(Node* a,Node* b)

{
return a->weight>=b->weight;
}
};

//传入的是指针,如果用对象去实现,你就不知道左右指针的指向了

//中序遍历
void InOrder(Node* p)
{
if (p != NULL)
{
InOrder(p->left);
cout<<p->weight<<'\t';
InOrder(p->right);
}
}

void freeTree(Node* p)//销毁二叉树
{
if(p->left!=NULL)
freeTree(p->left);
if(p->right!=NULL)
freeTree(p->right);
delete(p);
}

int main()
{
Node* m1,*m2;
priority_queue<Node*,vector<Node*>,cmp> q;
for(int i=0;i<6;++i)//6个节点
{
int n=rand()%100;
q.push(new Node(n));//权值随机产生
cout<<n<<'\t';
}
cout<<endl;
for(int j=1;j<6;++j)//合并5次
{
m1=q.top(); q.pop();
m2=q.top(); q.pop();
int w=m1->weight+m2->weight;
q.push(new Node(w,m1,m2));
}
Node* root=q.top();
InOrder(root);
cout<<endl;
freeTree(root);

system("pause");
return 0;
}
输出结果:
41 67 34 0 69 24
41 99 0 24 24 58 34 235 67 136
69

最近用近似算法实现旅行商问题,需要首先求解最小生成树,用Prim算法求解最小生成树,需要找割的最小边。于是想到了使用priority_queue,现在把priority_queue用法总结一下,不废话了,总结完了,快点求解TSP。

在STL中它的源码如下:

class priority_queue

{

     protected:
         _Sequence  c;                  ///容器
        _Compare   comp;          ///比较准则
     public:
     bool empty() const
     { return c.empty(); }
     size_type size() const
     { return c.size(); }
     const_reference top() const
     {
         __glibcxx_requires_nonempty();
         return c.front();
     }
     void push(const value_type& __x)
     {
         try
         {
          c.push_back(__x);
          std::push_heap(c.begin(), c.end(), comp);
        }
        catch(...)
        {
           c.clear();
           __throw_exception_again;
         }
     }
     void pop()
     {
         __glibcxx_requires_nonempty();
         try
         {
           std::pop_heap(c.begin(), c.end(), comp);
           c.pop_back();
         }
         catch(...)
         {
           c.clear();
           __throw_exception_again;
         }
     }

}

用法:

C++头文件 #include <queue>

template<typename _Tp,
             typename _Sequence = vector<_Tp>,
             typename _Compare  = less<typename _Sequence::value_type> >

第一个参数 _Tp: 指定存储的类型名称;

第二个参数 _Sequence: 指定存储的数据结构,该结果必须支持随机存取迭代器;

第三个参数 _Compare : 比较函数,对于自定义类型有两种方法实现大小顶堆,第一个是重载操作符,第二个是写一个结构实现比较。

各个数据类型算法讲解如下:

1.  对于一般的基本数据类型,比如 int,double等。

1).    默认是大顶堆,测试代码如下

 

其中省略了比较泛型函数less<int>

输出结果如下:


2).   小顶堆实现如下:

其中加上了存储的数据结构,和比较函数大小。

输出结果如下:


2.  对于自定义类型,必须实现比较函数。

自定义类型如下:


实现小顶堆:

自定义比较函数,这里选择实现比较结构:


测试代码为:


运行结果如下:



等价的重载大于号实现:


测试代码:


运行结果:


总结大顶堆于小于号有关,小顶堆与大于号有关,这样关联起来就不会忘了。

 

posted @ 2012-11-30 16:08  剑不飞  阅读(237)  评论(0编辑  收藏  举报