📜  数据结构-队列(1)

📅  最后修改于: 2023-12-03 15:10:20.053000             🧑  作者: Mango

数据结构 - 队列

简介

队列(Queue)是一种先进先出(FIFO, First-In-First-Out)的线性数据结构。它只允许在队列的前端(称为队头)进行删除操作,在队列的后端(称为队尾)进行插入操作。队列是一种比较基础的数据结构,应用非常广泛,比如操作系统中进程调度和线程池等。

实现

一般来说,队列可以使用数组或链表实现。本文介绍基于链表实现队列。

队列数据结构
struct Node {
    int data;
    Node *next;
};

class Queue {
private:
    Node *front;
    Node *rear;
    int size;

public:
    Queue() {
        front = nullptr;
        rear = nullptr;
        size = 0;
    }

    ~Queue() {
        Node *p = front;
        Node *q;
        while (p != nullptr) {
            q = p->next;
            delete p;
            p = q;
        }
    }

    bool isEmpty() {
        return size == 0;
    }

    int getSize() {
        return size;
    }

    bool enqueue(int data) {
        Node *node = new Node();
        if (node == nullptr) {
            return false;
        }
        node->data = data;
        node->next = nullptr;
        if (isEmpty()) {
            front = node;
            rear = node;
        } else {
            rear->next = node;
            rear = rear->next;
        }
        size++;
        return true;
    }

    bool dequeue(int &data) {
        if (isEmpty()) {
            return false;
        }
        Node *node = front;
        data = node->data;
        front = front->next;
        delete node;
        size--;
        return true;
    }

    bool peek(int &data) {
        if (isEmpty()) {
            return false;
        }
        data = front->data;
        return true;
    }
};

队列实现中,关键字是front和rear:front指向队首,rear指向队尾。enqueue操作将新元素放在队尾,并更新rear;dequeue操作将队首元素出队,并更新front。

应用
队列的应用场景
  • 操作系统中进程调度和线程池。
  • 基于队列的消息中间件,如Kafka、RocketMQ等。
  • 利用队列实现循环缓冲区。
经典问题:循环队列

循环队列(Circular Queue)是一种使用环形数组实现的队列,可以避免因元素删除导致的空间浪费。以下为循环队列的实现代码。

队列数据结构:

class CircularQueue {
private:
    int *data;
    int front;
    int rear;
    int capacity;

public:
    CircularQueue(int capacity) {
        data = new int[capacity];
        front = 0;
        rear = 0;
        this->capacity = capacity;
    }

    ~CircularQueue() {
        delete[] data;
    }

    bool isEmpty() {
        return front == rear;
    }

    bool isFull() {
        return (rear + 1) % capacity == front;
    }

    int getSize() {
        return (rear - front + capacity) % capacity;
    }

    bool enqueue(int value) {
        if (isFull()) {
            return false;
        }
        data[rear] = value;
        rear = (rear + 1) % capacity;
        return true;
    }

    bool dequeue(int &value) {
        if (isEmpty()) {
            return false;
        }
        value = data[front];
        front = (front + 1) % capacity;
        return true;
    }

    bool peek(int &value) {
        if (isEmpty()) {
            return false;
        }
        value = data[front];
        return true;
    }
};

循环队列中,队尾指针rear和队首指针front之间的差值必须小于队列的容量capacity,因为如果rear+1%capacity==front,就说明队列已经满了,不能再添加元素。循环队列数据结构中,getSize计算的公式是(rear-front+capacity)%capacity,这是为了保证当rear小于front时,值依然为正,而不是负数。

总结

队列是一种非常基础的数据结构,它的应用非常广泛。在实际开发中,我们可以通过数组或链表实现队列,并根据实际需要选择使用普通队列或循环队列。