数据结构-队列

1、概括

队列(queue)是一种操作受限的线性表,只允许在一端插入,而在表的另一端删除。和我们日常中的排队性质是一样的,操作特性为先行先出(First in and First out,FIFO)。队头指允许删除的一端,队尾指允许插入的一端

了解数据结构要从三要素入手:

  1. 逻辑结构:操作受限的线性表
  2. 存储结构(物理结构):顺序存储和链式存储
  3. 数据的运算:

初始化队列,入队,出队,判队列空,读队头元素

2、顺序存储

分配一块连续的存储空间存放队列中的元素。

并附设两个指针:

  1. 队头指针front 指向队头元素
  2. 队尾指针rear 指向队尾元素的下一个位置

这两个指针的定义可以是其他形式的,只是这里统一这样处理而已。

2.1 普通队列

普通队列的话因为会出现“假溢出”,所以就不多说了。

什么是“假溢出”?

简单说就是按照程序判断该队列已经是满的,但是实际情况队列依然有可以存放元素的位置。

怎么解决?

后面讲的循环队列就是解决方法,思路其实就是把表从逻辑上视为一个环。

2.2 循环队列

初始状态:Q.front = Q.rear = 0

入队:Q.front = ( Q.front +1 ) % maxSize

出队:Q.rear = ( Q.rear + 1 ) % maxSize

队列长度: ( Q.rear - Q.front + maxSize ) % maxSize

判空: Q.front == Q.rear

但是这样设置的话队满时也有  Q.front == Q.rear,那么怎么区分呢?

(1)牺牲一个单元来区分队空和队满。约定以“队头指针在队尾指针的下一位置作为队满的标志”

  • 队空条件:Q.front == Q.rear
  • 队满条件:( Q.rear + 1 ) % maxSize = Q.front
  • 队列元素的个数: ( Q.rear - Q.front + maxSize ) % maxSize (不管是front指向当前元素还是front指向当前元素的前一个位置,都是这种计算方法)

(2)类型中增加表示元素个数的成员变量size。

  • 队空条件:Q.size == 0
  • 队满条件:Q.size == maxSize

(3)类型中增加tag数据成员,以区分是队满还是队空。tag等于0,若因删除导致Q.front == Q.rear,则为队空;tag等于1时,若因添加导致Q.front == Q.rear,则为队满。(也就是tag为0时才有可能队空)

队列Q初始时,置tag=0、front=rear=0;

//入队
int EnQueue(SqQueue &Q,ElemType x){
    if(Q.front == Q.rear && Q.tag == 1){
        return 0;//队满
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % maxSize;
    Q.tag = 1; //将标志置为1
    return 1;
}
//出队
int DeQueue(SqQueue &Q, ElemType x){
    if(Q.front == Q.rear && Q.tag==0 ){
        return 0;
    }
    x = Q.data[Q.front];
    Q.front = (Q.front + 1) % maxSize;
    Q.tag = 0;
    return 1;
}

扩展题目:

题目1:Q是一个队列,S是一个空栈,实现将队列中的元素逆置的算法。

思路很简单,队列是先进先出的,所以当靠队列的操作不可能将元素逆置,但是栈可以啊。利用栈的先进后出,不就刚好符合元素逆置的要求。我们把队列的元素逐个取出来,再逐个入栈。然后再逐个出栈,逐个入队即可。

void Inverser(Stack &S, Queue &Q){
    int x;
    while(!QueueEmpty(Q)){
        x = DeQueue(Q); //队列中元素依次出队
        Push(S,x); //队列元素依次入栈
    }
    while(!StackEmpty(S)){
        Pop(S,x); //栈中元素依次出栈
        EnQueue(Q,x); //元素依次入队
    }
}

利用c++库函数写法 

#include <iostream>
#include <queue>
#include <stack>
using namespace std;

void Inverser(stack<int> &S, queue<int> &Q){
    int x;
    while(!Q.empty()){
        x = Q.front(); 
		Q.pop(); //队列中元素依次出队
        S.push(x); //队列元素依次入栈
    }
    while(!S.empty()){
    	x=S.top();
        S.pop(); //栈中元素依次出栈
        Q.push(x); //元素依次入队
    }
} 

int main(){
	queue<int> q;
	stack<int> s;
	for (int i = 1; i <= 6; i++){
		q.push(i);
	}
	Inverser(s,q);
	for (int j = 0; j < 6; j++){
		int tmp = q.front();
		cout << tmp << " ";
		q.pop();
	}
}

输出结果为:6 5 4 3 2 1 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值