18-C++ 数据结构 - 队列

📖 一、队列的基本概念

1.1 队列的定义

队列是一种线性数据结构,用于存储一组连续的元素的特殊存储结构,它的主要特点是限定队列元素在一端插入,在另一端删除,满足先进先出(FIFO)。类似于排队买票,先来的人先买票,后来的人排在队尾,依次购买。

队头:指向队伍最前面的元素位置

队尾:指向队尾待插入元素的位置

初始队伍为空时,两者指向同一位置。

在这里插入图片描述

可见队列为空的标志为队头、队尾指向同一位置。

1.2 队列的常见基本操作

队列的常见基本操作包括:

  • 入队(Enqueue):将元素加入队列的末尾。
  • 出队(Dequeue):将队列头部的元素移除。
  • 队列是否为空(IsEmpty):判断队列是否为空。
  • 队列大小(Size):获取队列中元素的个数。
  • 获取队头元素(Front):查看队列头部的元素。

1.3 队列实现

数组方式

#include <cstdio>
using namespace std;

int n;
int q[1005];

int head = 0, tail = 0; // 记录队头队尾位置

void push(int x){
    // 入队
    q[tail++] = x;
}

int pop(){
    // 出队
    return q[head++];
}

int empty(){
    // 判空
    return head == tail;
}

int main(){
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        int a;
        scanf("%d", &a);
        push(a); // 入队
    }

    while (!empty()) {
        // 输出队列内所有元素
        printf("%d ", pop());
    }
    return 0;
}

STL方式

#include <cstdio>
#include <queue>
using namespace std;

int n;
queue<int> q; // 定义队列类型变量q
int main(){
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        int a;
        scanf("%d", &a);
        q.push(a); // 入队
    }
    // 输出队列内所有元素
    while (!q.empty()){ 
        // empty()用于判断队列是否为空
        printf("%d ", q.front()); // front()获取队头元素
        q.pop();                  // pop()删除队头元素
    }
    return 0;
}

💻 二、队列的顺序存储结构

2.1 顺序队列

顺序队列是通过数组实现的队列。我们可以使用一个数组和两个指针来表示队列。一个指针 front 指向队列头部,一个指针 rear 指向队列尾部。当进行入队操作时,rear 指针向后移动,并将元素加入到 rear 指针的位置;出队操作时,front 指针向后移动,将头部元素移除。

#include <iostream>
using namespace std;

const int MAX_SIZE = 100; // 队列的最大容量
int queue[MAX_SIZE]; // 队列的数组
int front = 0; // 队头指针
int rear = 0; // 队尾指针

// 入队操作
void enqueue(int x) {
    if ((rear + 1) % MAX_SIZE == front) {
        cout << "队列已满,无法入队!" << endl;
        return;
    }
    queue[rear] = x;
    rear = (rear + 1) % MAX_SIZE;
}

// 出队操作
void dequeue() {
    if (front == rear) {
        cout << "队列为空,无法出队!" << endl;
        return;
    }
    front = (front + 1) % MAX_SIZE;
}

// 获取队头元素
int getFront() {
    if (front == rear) {
        cout << "队列为空,无队头元素!" << endl;
        return -1;
    }
    return queue[front];
}

// 判断队列是否为空
bool isEmpty() {
    return front == rear;
}

// 获取队列大小
int size() {
    return (rear - front + MAX_SIZE) % MAX_SIZE;
}

int main() {
    enqueue(1);
    enqueue(2);
    enqueue(3);
    
    cout << "当前队头元素:" << getFront() << endl;
    cout << "队列大小:" << size() << endl;
    
    dequeue();
    cout << "当前队头元素:" << getFront() << endl;
    cout << "队列是否为空:" << (isEmpty() ? "是" : "否") << endl;
    
    return 0;
}

运行结果:

当前队头元素:1
队列大小:3
当前队头元素:2
队列是否为空:否

2.2 循环队列

循环队列是在顺序队列的基础上进行了优化,解决了顺序队列中数据搬移的问题。循环队列的实现中,当 rear 指针到达数组末尾时,如果还有空闲位置,将 rear 指针移到队列头部。

#include <iostream>
using namespace std;

const int MAX_SIZE = 100; // 队列的最大容量
int queue[MAX_SIZE]; // 队列的数组
int front = 0; // 队头指针
int rear = 0; // 队尾指针

// 入队操作
void enqueue(int x) {
    if ((rear + 1) % MAX_SIZE == front) {
        cout << "队列已满,无法入队!" << endl;
        return;
    }
    queue[rear] = x;
    rear = (rear + 1) % MAX_SIZE;
}

// 出队操作
void dequeue() {
   

 if (front == rear) {
        cout << "队列为空,无法出队!" << endl;
        return;
    }
    front = (front + 1) % MAX_SIZE;
}

// 获取队头元素
int getFront() {
    if (front == rear) {
        cout << "队列为空,无队头元素!" << endl;
        return -1;
    }
    return queue[front];
}

// 判断队列是否为空
bool isEmpty() {
    return front == rear;
}

// 获取队列大小
int size() {
    return (rear - front + MAX_SIZE) % MAX_SIZE;
}

int main() {
    enqueue(1);
    enqueue(2);
    enqueue(3);
    
    cout << "当前队头元素:" << getFront() << endl;
    cout << "队列大小:" << size() << endl;
    
    dequeue();
    cout << "当前队头元素:" << getFront() << endl;
    cout << "队列是否为空:" << (isEmpty() ? "是" : "否") << endl;
    
    return 0;
}

运行结果:

当前队头元素:1
队列大小:3
当前队头元素:2
队列是否为空:否

2.3 循环队列常见基本算法

  • 判空:当 front 和 rear 指针相等时,队列为空。
  • 判满:当 (rear + 1) % MAX_SIZE 等于 front 时,队列为满。
  • 入队:将元素放入 rear 指针的位置,并将 rear 指针后移一位。如果队列已满,则无法入队。
  • 出队:将 front 指针后移一位,表示出队操作。

💡 三、队列的链式存储结构

3.1 链队列

链队列是通过链表实现的队列。每个节点包含一个元素和一个指向下一个节点的指针。链队列没有固定的大小限制,可以根据实际情况动态调整大小。

#include <iostream>
using namespace std;

struct Node {
    int data;
    Node* next;
};

class Queue {
private:
    Node* front; // 队头指针
    Node* rear; // 队尾指针
public:
    // 构造函数
    Queue() {
        front = NULL;
        rear = NULL;
    }
    
    // 判断队列是否为空
    bool isEmpty() {
        return front == NULL;
    }
    
    // 入队操作
    void enqueue(int x) {
        Node* newNode = new Node;
        newNode->data = x;
        newNode->next = NULL;
        
        if (isEmpty()) {
            front = rear = newNode;
        } else {
            rear->next = newNode;
            rear = newNode;
        }
    }
    
    // 出队操作
    void dequeue() {
        if (isEmpty()) {
            cout << "队列为空,无法出队!" << endl;
            return;
        }
        
        Node* temp = front;
        front = front->next;
        delete temp;
    }
    
    // 获取队头元素
    int getFront() {
        if (isEmpty()) {
            cout << "队列为空,无队头元素!" << endl;
            return -1;
        }
        return front->data;
    }
    
    // 获取队列大小
    int size() {
        int count = 0;
        Node* current = front;
        while (current != NULL) {
            count++;
            current = current->next;
        }
        return count;
    }
};

int main() {
    Queue q;
    q.enqueue(1);
    q.enqueue(2);
    q.enqueue(3);
    
    cout << "当前队头元素:" << q.getFront() << endl;
    cout << "队列大小:" << q.size() << endl;
    
    q.dequeue();
    cout << "当前队头元素:" << q.getFront() << endl;
    cout << "队列是否为空:" << (q.isEmpty() ? "是" : "否") << endl;
    
    return 0;
}

运行结果:

当前队头元素:1
队列大小:3
当前队头元素:2
队列是否为空:否

3.2 链队列常见基本算法

  • 判空:当 front 指针为空时,队列为空。
  • 入队:创建新节点,将元素放入新节点中,并将新节点加入到队尾,并移动 rear 指针。
  • 出队:移动 front 指针,删除队头节点。
  • 获取队头元素:返回 front 指针指向节点的元素值。

📝 总结

队列是一种非常常用的数据结构,具有先进先出的特点。队列可以通过顺序存储结构和链式存储结构实现,分别对应顺序队列和链队列。我们可以根据实际情况选择不同的实现方式。掌握队列的基本操作和算法,将对解决一些实际问题有很大的帮助。

⭐️希望本篇文章对你有所帮助。

⭐️如果你有任何问题或疑惑,请随时提问。

⭐️感谢阅读!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逸峰轻云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值