优先队列与循环队列

优先队列用法
在优先队列中,优先级高的元素先出队列。
标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。
优先队列的第一种用法,也是最常用的用法:

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;
	}
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值