C++的数据结构(四):队列

在数据结构中,队列(Queue)是一种特殊的线性表,只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。队列中没有元素时,称为空队列。队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以又称为先进先出(FIFO---First In First Out)的线性表。

队列通常使用链表或数组来实现。在链表中,我们通常使用两个指针,一个指向队首,另一个指向队尾,以方便进行入队和出队操作。在数组中,我们通常维护两个变量,一个指向队首元素的位置,另一个指向队尾元素的后一个位置,即队列的下一个空位。

除了基本的队列外,还有一些特殊的队列类型,如循环队列和双端队列。

  1. 循环队列:为了避免队满时无法入队以及队空时无法出队的问题,我们可以使用循环队列。循环队列将数组的首尾相连,形成一个环,当队尾指针到达数组的末尾时,下一个位置就是数组的开始。

  2. 双端队列:双端队列允许在队列的两端进行入队和出队操作。这使得双端队列不仅具有队列的特性,还具有栈的特性。

入队与出队操作如下:

  1. 入队操作:在队列的尾部插入一个新元素。在循环队列中,如果队尾指针到达数组的末尾,则将其重置为数组的开始位置,然后插入新元素。

  2. 出队操作:从队列的头部删除一个元素。在循环队列中,如果队头指针到达数组的末尾,则将其重置为数组的开始位置,然后删除元素。

以下是一个使用数组实现的循环队列的C++代码示例,代码如下:

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

const int MAX_SIZE = 10; // 队列的最大容量

class CircularQueue {
private:
    int front; // 队首指针
    int rear; // 队尾指针
    int queue[MAX_SIZE]; // 队列数组

public:
    CircularQueue() {
        front = rear = -1; // 初始化队列为空
    }

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

    // 判断队列是否已满
    bool isFull() {
        return (rear + 1) % MAX_SIZE == front;
    }

    // 入队操作
    void enqueue(int value) {
        if (isFull()) {
            cout << "Queue is full. Cannot enqueue." << endl;
            return;
        }
        if (isEmpty()) {
            front = 0;
        }
        rear = (rear + 1) % MAX_SIZE;
        queue[rear] = value;
    }

    // 出队操作
    void dequeue() {
        if (isEmpty()) {
            cout << "Queue is empty. Cannot dequeue." << endl;
            return;
        }
        if (front == rear) { // 如果队列中只有一个元素
            front = rear = -1;
        } else {
            front = (front + 1) % MAX_SIZE;
        }
    }

    // 获取队首元素
    int peekFront() {
        if (isEmpty()) {
            cout << "Queue is empty." << endl;
            return -1;
        }
        return queue[front];
    }

    // 获取队尾元素
    int peekRear() {
        if (isEmpty()) {
            cout << "Queue is empty." << endl;
            return -1;
        }
        return queue[rear];
    }

    // 打印队列元素
    void printQueue() {
        if (isEmpty()) {
            cout << "Queue is empty." << endl;
            return;
        }
        cout << "Queue elements: ";
        int current = front;
        do {
            cout << queue[current] << " ";
            current = (current + 1) % MAX_SIZE;
        } while (current != front);
        cout << endl;
    }
};

int main() {
    CircularQueue q;

    // 入队操作
    q.enqueue(1);q.enqueue(2);
q.enqueue(3);
q.enqueue(4);
q.enqueue(5);

// 打印队列元素
q.printQueue(); // 应输出:Queue elements: 1 2 3 4 5 

// 出队操作
q.dequeue();
q.dequeue();

// 打印队列元素
q.printQueue(); // 应输出:Queue elements: 3 4 5 

// 获取队首元素
cout << "Front element: " << q.peekFront() << endl; // 应输出:Front element: 3

// 获取队尾元素
cout << "Rear element: " << q.peekRear() << endl; // 应输出:Rear element: 5

// 再次入队操作
q.enqueue(6);
q.enqueue(7);
q.enqueue(8);

// 打印队列元素
q.printQueue(); // 应输出:Queue elements: 3 4 5 6 7 8

return 0;
}

结果如下所示:

注意循环队列满的情况:由于我们在这里使用了一个固定大小的数组,并且队列大小已经达到了最大值,所以再试图入队会导致队列满。在实际应用中,可能需要一个动态大小的队列或者其他机制来处理队列满的情况。

本文详细介绍了C++中的队列概念,特别是先进先出(FIFO)的数据结构。队列有多种类型,包括循环队列和双端队列等。我们通过实现一个循环队列的示例,展示了队列的基本操作,如入队、出队、查看队首和队尾元素等。循环队列通过模运算实现了空间的循环使用,提高了队列的利用率。然而,循环队列的实现也有其局限性,如需要预先确定队列的最大容量,当队列满时可能无法继续入队等。在实际应用中,需要根据具体需求选择合适的队列实现方式。

相关推荐
杰克尼6 小时前
BM5 合并k个已排序的链表
数据结构·算法·链表
xiaolang_8616_wjl7 小时前
c++文字游戏_闯关打怪
开发语言·数据结构·c++·算法·c++20
hqxstudying8 小时前
Java创建型模式---单例模式
java·数据结构·设计模式·代码规范
sun0077008 小时前
数据结构——栈的讲解(超详细)
数据结构
ゞ 正在缓冲99%…12 小时前
leetcode918.环形子数组的最大和
数据结构·算法·leetcode·动态规划
努力写代码的熊大14 小时前
单链表和双向链表
数据结构·链表
Orlando cron15 小时前
数据结构入门:链表
数据结构·算法·链表
许愿与你永世安宁20 小时前
力扣343 整数拆分
数据结构·算法·leetcode
Heartoxx21 小时前
c语言-指针(数组)练习2
c语言·数据结构·算法
杰克尼1 天前
1. 两数之和 (leetcode)
数据结构·算法·leetcode