数据结构——队列

形状

队列是一种先进后出 的线性表,它允许++插入++ 的一端叫++队尾++ ,允许++删除++ 的一端叫++队头++。

与平时排队一样,从队伍后面排,从队伍前面出。

当多个任务同时运行且需要通过同一个通道输出时,就要按照请求顺序来排队,此时便可使用队列。

顺序表示(顺序队列)

头指针front始终指向队头,当队列未满时,rear始终指向队尾元素的下一个。

c 复制代码
#define MAXQSIZE 100
typedef struct
{
    QElemType *base;//存储空间基地址
    int front;//头指针,int类型,存储队伍头地址
    int rear;//尾指针,int类型,存储队伍尾地址
}SqQueue;

为解决入队出队导致空间有些没用到的问题(如下图所示,经过四次操作后,尾指针已经指向最后一个位置,而前面是空但是因为头指针不能插入了),我们使队列变成一个环形结构,称为循环队列。

其他与原理一致,只不过在循环队列中头尾指针加一时使用模运算来实现:

  • Q.rear =(Q.rear + 1) % MAXQSIZE
  • Q.front =(Q.front + 1) % MAXQSIZE

判断队满队空:少用一个数据元素(有一个地方始终为空),即m个位置,m-1个元素则算队列满了:

  • 队空 -> Q.rear = Q.front
  • 队满 -> (Q.rear + 1) % MAXQSIZE = Q.front

初始化

c 复制代码
Status InitQueue(SqQueue& Q)
{
    Q.base = new SqElemType[MAXQSIZE];//顺序表,需要开辟一段空间
    if (!Q.base) exit(OVERFLOW);//分配失败
    Q.rear = Q.front = 0;//空队列
    return ok;
}

获取长度

c 复制代码
int QueueLength(SqQueue Q)
{
	return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;//循环队列可能出现尾减头为负数的情况,所以要加上MAXQSIZE;当为正数加上MAXQSIZE会大于实际大小,则取余MAXQSIZE,得出大小
}

入队

c 复制代码
Status EnQueue(SqQueue& Q, QElemType e)
{
    if ((Q.rear + 1)  %  MAXQSIZE == Q.front) return error;//队列已满
    Q.base[Q.rear] = e;//把新元素放入队列
    Q.rear = (Q.rear + 1)  %  MAXQSIZE;//尾指针加一
    return ok;
}

出队

c 复制代码
Status DeQueue(SqQueue& Q, QElemType& e)
{
    if (Q.rear == Q.front) return error;//队列为空
    e = Q.base[Q.front];//把元素取出
    Q.front = (Q.front + 1)  %  MAXQSIZE;//头指针加一,队列头出队后,要往后移,地址是增加的
    return ok;
}

取队头元素

c 复制代码
QElemType GetHead(SqQueue Q)
{//返回队头元素,不改变头指针
    if(Q.front != Q.rear)//队列非空
        return Q.base[Q.front];
}

链式表示(链队列)

队列的删除插入地方不一样,故而需要两个指针,为了安全和方便操作,使用结构将其封装起来;

所以需要先创造节点结构,再创造链表结构,使链表结构中有整个队列的头尾指针,区分操作;

而栈只在栈顶操作,所以只需要一个指针,在函数内直接定义一个即可串起来全部。

无论是栈还是队列,在链式表示中,在栈底与队列头都需要一个全空的节点作为判断。

c 复制代码
#define MAXQSIZE 100
typedef struct QNode
{
    QElemType data;
    struct QNode *next;//存储空间基地址
}QNode, *QueuePtr;

typedef struct
{
    QueuePtr front;//头指针,int类型,存储队伍头地址
    QueuePtr rear;//尾指针,int类型,存储队伍尾地址
}LinkQueue; 

初始化

c 复制代码
Status InitQueue(LinkQueue& Q)
{
    Q.front = Q.rear = new QNode;//申请一个头节点
    Q.front->next = NULL;//头指针的next置空
    return ok;
}

入队

c 复制代码
Status EnQueue(LinkQueue& Q, QElemType e)
{//不需要判断队列满没有,因为链表是动态的;下面只改变尾指针是因为头指针只能删除用,故而用尾指针插入
    QNode p = new QNode;//创建一个节点
    p->data = e;
    p->next = NULL;
    Q.rear->next = p;//使新节点插入队尾
    Q.rear = p;//队尾指针指向队尾元素
    return ok;
}

出队

c 复制代码
Status DeQueue(LinkQueue& Q, QElemType& e)
{
    if (Q.rear == Q.front) return error;//队列为空
    p = Q.front->next;//用一个新节点代替队头节点,便于等会挪完队头指针后,在内存空间删除它
    e = p->data;
    Q.front->next = p->next;//修改头节点,指向下一个
    if(Q.rear = p) Q.rear = Q.front;//若最后一个元素被删除了,队尾指针指向队头指针
    delete p;
    return ok;
}

取队头元素

c 复制代码
QElemType GetHead(LinkQueue Q)
{//返回队头元素,不改变头指针
    if(Q.front != Q.rear)//队列非空
        return Q.front->next->data;
}

在STL中队列的主要操作函数

1.queue<> q

创建一个空队列

c 复制代码
queue<队列内数据的类型> q;

2. push()

将元素加入队尾(back)。

cpp 复制代码
queue<int> q;
q.push(10);  // 将 10 加入队尾
q.push(20);  // 将 20 加入队尾

3. pop()

移除队头(front)元素。注意,pop() 不会返回被删除的元素。

cpp 复制代码
q.pop();  // 移除队头元素 10

4. front()

返回队头元素的引用,但不删除它。

cpp 复制代码
int front_element = q.front();  // 获取队头元素,值为 20

5. back()

返回队尾元素的引用,但不删除它。

cpp 复制代码
int back_element = q.back();  // 获取队尾元素,值为 20

6. empty()

检查队列是否为空,若为空则返回 true,否则返回 false

cpp 复制代码
bool is_empty = q.empty();  // 检查队列是否为空

7. size()

返回队列中元素的数量。

cpp 复制代码
size_t count = q.size();  // 队列中的元素数量

示例代码

cpp 复制代码
#include <iostream>
#include <queue>
using namespace std;

int main() {
    queue<int> q;
    q.push(1);
    q.push(2);
    q.push(3);

    cout << "队头元素: " << q.front() << endl;  // 输出 1
    cout << "队尾元素: " << q.back() << endl;   // 输出 3

    q.pop();  // 移除队头元素 1

    cout << "移除队头后的新队头: " << q.front() << endl;  // 输出 2
    cout << "队列的大小: " << q.size() << endl;  // 输出 2
    cout << "队列是否为空: " << (q.empty() ? "是" : "否") << endl;

    return 0;
}
相关推荐
就爱学编程1 小时前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
ALISHENGYA2 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
DARLING Zero two♡2 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
波音彬要多做4 小时前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
Noah_aa4 小时前
代码随想录算法训练营第五十六天 | 图 | 拓扑排序(BFS)
数据结构
KpLn_HJL5 小时前
leetcode - 2139. Minimum Moves to Reach Target Score
java·数据结构·leetcode
AC使者10 小时前
5820 丰富的周日生活
数据结构·算法
无 证明11 小时前
new 分配空间;引用
数据结构·c++
别NULL15 小时前
机试题——疯长的草
数据结构·c++·算法