优先队列用法
在优先队列中,优先级高的元素先出队列。
标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。
优先队列的第一种用法,也是最常用的用法:
priority_queue<int> qi;
通过<操作符可知在整数中元素大的优先级高。
故示例1中输出结果为:9 6 5 3 2
第二种方法:
在示例1中,如果我们要把元素从小到大输出怎么办呢?
这时我们可以传入一个比较函数,使用functional.h函数对象作为比较函数。
priority_queue<int, vector<int>, greater<int> >qi2;
其中
第二个参数为容器类型。
第二个参数为比较函数。
故示例2中输出结果为:2 3 5 6 9
第三种方法:
自定义优先级。
struct node
{
friend bool operator< (node n1, node n2)
{
return n1.priority < n2.priority;
}
int priority;
int value;
};
在该结构中,value为值,priority为优先级。
通过自定义operator<操作符来比较元素中的优先级。
在示例3中输出结果为:
优先级 值
9 5
8 2
6 1
2 3
1 4
但如果结构定义如下:
struct node
{
friend bool operator> (node n1, node n2)
{
return n1.priority > n2.priority;
}
int priority;
int value;
};
则会编译不过(G++编译器)
因为标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。
而且自定义类型的<操作符与>操作符并无直接联系,故会编译不过。
//代码清单
#include<iostream>
#include<functional>
#include<queue>
using Namespace stdnamespace std;
struct node
{
friend bool operator< (node n1, node n2)
{
return n1.priority < n2.priority;
}
int priority;
int value;
};
int main()
{
const int len = 5;
int i;
int a[len] = {3,5,9,6,2};
//示例1
priority_queue<int> qi;
for(i = 0; i < len; i++)
qi.push(a[i]);
for(i = 0; i < len; i++)
{
cout<<qi.top()<<" ";
qi.pop();
}
cout<<endl;
//示例2
priority_queue<int, vector<int>, greater<int> >qi2;
for(i = 0; i < len; i++)
qi2.push(a[i]);
for(i = 0; i < len; i++)
{
cout<<qi2.top()<<" ";
qi2.pop();
}
cout<<endl;
//示例3
priority_queue<node> qn;
node b[len];
b[0].priority = 6; b[0].value = 1;
b[1].priority = 9; b[1].value = 5;
b[2].priority = 2; b[2].value = 3;
b[3].priority = 8; b[3].value = 2;
b[4].priority = 1; b[4].value = 4;
for(i = 0; i < len; i++)
qn.push(b[i]);
cout<<"优先级"<<'\t'<<"值"<<endl;
for(i = 0; i < len; i++)
{
cout<<qn.top().priority<<'\t'<<qn.top().value<<endl;
qn.pop();
}
return 0;
}
C++中的应用编辑
语法
queue类是为程序员提供了一个队列的功能的容器适配器,具体而言,一个FIFO(先入先出)的数据结构
在头文件<queue>中定义。
原型
template<
class T,
class Container =std::deque<T>
> class queue;
成员函数
empty()判断队列空,当队列空时,返回true。
size()访问队列中的元素个数。
push()会将一个元素置入queue中。
front()会返回queue内的下一个元素(也就是第一个被置入的元素)。
back()会返回queue中最后一个元素(也就是最后被插入的元素)。
pop()会从queue中移除一个元素。
注意:pop()虽然会移除下一个元素,但是并不返回它,front()和back()返回下一个元素但并不移除该元素。
队列:
1. 只允许从一端入,从另一端出
2. 先进先出的存储结构
分类:
1. 链式队列 (链表实现)
2. 静态队列 (数组实现)
静态队列通常都是循环队列
循环队列:
1. 静态队列为什么必须是循环队列
2. 循环队列需要几个参数来确定
需要2个参数来确定
3. 循环队列各个参数的含义
2个参数不同场合有不同的含义
1)队列初始化
front和rear都是零
2)队列非空
front代表队列的第一个元素
rear代表队列的最后一个有效元素的下一个元素
3)队列空
front和rear的值相等,但不一定是零
4. 循环队列入队伪算法
两步完成:
1)将值存入rear所代表的位置
2)rear = (rear+1)%数组的长度
5. 循环队列出队伪算法
两步完成:
1)从front所代表的位置取出值,保存为出队的元数值
2)front = (front+1)%数组的长度
6. 如何判断循环队列是否为空
如果front和rear的值相等,则该队列为空
7. 如何判断循环队列是否已满
front的值可能比rear的值大,也可能比rear的值小,也可能相等(队空)
两种方式:
1)多增加一个表标识的参数
2) 少用一个元素(满时有一个位置不存有效值)
通常使用第2种方式:
如果rear和front的值紧挨着,则队列已满
伪算法:
if((r+1)%数组的长度 == f)
已满
else
不满
# include <stdio.h>
# include <malloc.h>
# include <stdlib.h>
// 循环队列
typedef struct Queue
{
int * pBase;
int front; //队头元素下标
int rear; //队尾元素下一位置的下标
int length; //队列元素个数
}QUEUE,* PQUEUE;
void init_queue(PQUEUE pQ);
int en_queue(PQUEUE pQ,int val); // 入队
void traverse_queue(PQUEUE pQ); // 遍历输出队列
int out_queue(PQUEUE pQ,int * pVal); // 出队
int is_empty_queue(PQUEUE pQ); // 1 空队列 0 非空队列
int is_full_queue(PQUEUE pQ); // 1 循环队列满 0 未满
int main(void)
{
QUEUE Q;
int choose,value;
init_queue(&Q);
do
{
printf("1) 入队\t\t2) 出队\n");
printf("3) 遍历\t\t4) 清空\n");
printf("0) 退出\n> ");
scanf("%d",&choose);
switch(choose)
{
case 1:
printf("输入要入队的元素值: ");
scanf("%d",&value);
if (en_queue(&Q,value))
{
printf("入队成功!\n");
}
else
{
printf("入队失败!\n");
}
break;
case 2:
if (out_queue(&Q,&value))
{
printf("出队成功,出队元素值为【%d】!\n",value);
}
else
{
printf("出队失败!\n");
}
break;
case 3:
traverse_queue(&Q);
break;
case 4:
Q.front = 0;
Q.rear = 0;
break;
case 0:
free(Q.pBase);
exit(0);
break;
default:
break;
}
}while(choose);
free(Q.pBase);
return 0;
}
void init_queue(PQUEUE pQ)
{
int len;
printf("输入初始化队列的长度: ");
scanf("%d",&len);
len = len + 1; // 下标为rear的元素非有效元素
pQ->length = len;
pQ->pBase = (int *)malloc(sizeof(int)*(pQ->length));
pQ->front = 0;
pQ->rear = 0;
return;
}
int is_empty_queue(PQUEUE pQ)
{
if (pQ->rear == pQ->front)
return 1;
else
return 0;
}
int is_full_queue(PQUEUE pQ)
{
if ((pQ->rear + 1)%(pQ->length) == pQ->front)
return 1;
else
return 0;
}
int en_queue(PQUEUE pQ,int val)
{
if (is_full_queue(pQ))
{
printf("队列已满,不可再入队!\n");
return 0;
}
else
{
pQ->pBase[pQ->rear] = val;
pQ->rear = (pQ->rear + 1) % (pQ->length);
return 1;
}
}
void traverse_queue(PQUEUE pQ)
{
int i = pQ->front;
if (is_empty_queue(pQ))
{
printf("队列空!\n");
return;
}
printf("队列为:\n 队头<");
while(i != pQ->rear)
{
printf(" %d ",pQ->pBase[i]);
i = (i+1) % (pQ->length);
}
printf("< 队尾\n");
return;
}
int out_queue(PQUEUE pQ,int * pVal)
{
if (is_empty_queue(pQ))
{
printf("队列空!\n");
return 0;
}
else
{
*pVal = pQ->pBase[pQ->front];
pQ->front = (pQ->front+1) % (pQ->length);
return 1;
}
}