数据结构-队列

介绍

队列(Queue)是只允许在一端进行插入操作,另一端进行删除操作的线性表。它遵循先进先出(FIFO)的原则,插入端为队尾,删除端为队头。队列中的数据也是线性排列的。在队列中,数据的添加和删除操作分别在两端进行,这与栈结构有所不同。在队列中,处理总是从第一名开始往后进行,而新增加的只能排在队尾。

队列的实现包括顺序存储和链式存储,具有不同的特点和适用场景:

  1. 顺序存储:顺序存储是队列的一种常见存储方式,它将队列中的元素按照顺序存储在连续的内存空间中。在顺序存储中,每个元素都占据一个固定的位置,通过索引可以快速地访问和修改元素。顺序存储的优点是访问速度快,空间利用率高。然而,它需要预先分配固定的内存空间,如果队列的大小在运行时发生变化,可能会导致空间的浪费或者溢出。
  2. 链式存储:链式存储是队列的另一种存储方式,它通过链表来存储队列中的元素。在链式存储中,每个元素都包含数据和指向下一个元素的指针。链表的优点是可以动态地分配内存空间,不需要预先确定队列的大小。当队列中的元素数量发生变化时,链表可以自动调整其大小。此外,链式存储还支持在队列的任意位置插入和删除元素,操作比较灵活。然而,链式存储的访问速度相对较慢,因为需要通过指针来访问链表中的元素。同时,链式存储的空间利用率也较低,因为每个元素都需要额外的空间来存储指针。

实现举例

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

#define MAXSIZE 100 // 定义队列的最大容量

class Queue {
private:
    int data[MAXSIZE]; // 存储队列元素的数组
    int front; // 队头指针,指向队头元素的前一个位置
    int rear; // 队尾指针,指向队尾元素的位置
public:
    Queue() {
        front = rear = -1; // 初始化队头和队尾指针
    }
    bool isEmpty() {
        return front == rear; // 判断队列是否为空
    }
    bool isFull() {
        return (rear + 1) % MAXSIZE == front; // 判断队列是否已满
    }
    void enqueue(int x) {
        if (isFull()) {
            cout << "Queue is full!" << endl;
            return;
        }
        rear = (rear + 1) % MAXSIZE; // 计算新的队尾位置
        data[rear] = x; // 将元素插入队尾
    }
    void dequeue() {
        if (isEmpty()) {
            cout << "Queue is empty!" << endl;
            return;
        }
        front = (front + 1) % MAXSIZE; // 计算新的队头位置
    }
    int peek() {
        if (isEmpty()) {
            cout << "Queue is empty!" << endl;
            return -1;
        }
        return data[(front + 1) % MAXSIZE]; // 返回队头元素的值,但不删除它
    }
};

int main() {
    Queue q; // 创建一个队列对象
    q.enqueue(1); // 入队操作,将元素1插入队尾
    q.enqueue(2); // 入队操作,将元素2插入队尾
    cout << q.peek() << endl; // 获取队头元素的值,输出1
    q.dequeue(); // 出队操作,删除队头元素1
    cout << q.peek() << endl; // 获取队头元素的值,输出2
    return 0;
}
实例说明

在这个示例代码中,我们定义了一个名为Queue的类,该类包含了队列的基本操作函数,如入队、出队、判断队列是否为空或已满等。在主函数中,我们创建了一个Queue对象q,并对其进行了一些基本操作。例如,我们使用enqueue()函数将元素1和2插入队列中,使用peek()函数获取队头元素的值,使用dequeue()函数删除队头元素。

总结

队列的应用场景包括但不限于以下情况:

  1. 异步处理:比如用户注册后,需要发送注册邮件和注册短信。传统的做法有两种,串行方式和并行方式。串行方式是将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端。并行方式是将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。这种情况下,使用队列进行异步处理可以提高处理的时间性能。
  2. 应用解耦:将业务中依赖其他系统同时属于非核心或不重要的部分使用消息通知即可,无需同步等待其他系统的处理结果。比如电商网站在促销期间抢购订单,抢到的商品订单信息放入消息队列,出库、发货等后续会从队列里读取任务信息然后执行。
  3. 流量削锋:一般在秒杀或团抢活动中应用广泛。电商平台会举办一些活动比如秒杀和团购会吸引大量用户下订单,瞬间流量暴增。这种情况下,使用队列堆积缓存订单等信息,在下游系统有能力处理消息的时候再处理,避免下游订阅系统因突发流量崩溃。
  4. 消息通讯:消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。
相关推荐
薯条不要番茄酱1 小时前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
盼海4 小时前
排序算法(五)--归并排序
数据结构·算法·排序算法
搬砖的小码农_Sky10 小时前
C语言:数组
c语言·数据结构
先鱼鲨生11 小时前
数据结构——栈、队列
数据结构
一念之坤11 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
IT 青年12 小时前
数据结构 (1)基本概念和术语
数据结构·算法
熬夜学编程的小王12 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
liujjjiyun12 小时前
小R的随机播放顺序
数据结构·c++·算法
Reese_Cool14 小时前
【数据结构与算法】排序
java·c语言·开发语言·数据结构·c++·算法·排序算法
djk888814 小时前
.net将List<实体1>的数据转到List<实体2>
数据结构·list·.net