数据结构与算法学习笔记三---循环队列的表示和实现(C++)

目录

前言

1.为什么要使用循环队列

2.队列的顺序存储方式的实现

1.定义

2.队列初始化

3.销毁

4.清空队列

5.队列是否为空

6.队列长度

7.队头

8.入队

9.出队

10.遍历队列

11.完整代码

3.参考资料


前言

    这篇文章介绍循环队列的表示和用法

1.为什么要使用循环队列

        在上一篇文章中,我们知道了顺序的循环表示和实现方法。但是我们会发现当我们在操作顺序链表的时候,我们频繁的操作顺序队列,而队列又不为空的时候,出队列的一些存储空间会变得不可用。

        如下图所示,当我rear=3,front=2的时候,顺序队列中至少有连个存储空间空间是不可以使用的,这无疑会浪费一些存储空间。那么有没有办法让我们在出队列之后,重复利用之前存储空间呢,答案是有的。

        图1.顺序队列的出队列和入队列操作示意图

        这里借鉴了网上老师的三种解决方案:

        1.使用计数器记录队列中的元素个数

        2.加标志位,删除的时候标志位置1,插入置0,当front = rear并且标志位为0,表示队列为空,当front=rear并且标志位为1的时候,表示队列经满。

        3.认为浪费一个存储空间,改成一个循环队列来实现。

        这里下面代码的表示和实现采用的第三种方案。

        关于循环队列的理解,感觉严蔚敏老师的讲解还是不错的,直接贴个图吧。

图2.严蔚敏老师数据结构与算法中关于循环队列的思路

2.队列的顺序存储方式的实现

1.定义

struct CircularQueue {
    int *base;
    int front;
    int rear;
    int maxSize; // 队列的最大容量
};

2.队列初始化

// 队列初始化
Status initQueue(CircularQueue &circularQueue, int maxSize) {
    circularQueue.base = new int[maxSize]; // 为循环队列分配内存
    if (!circularQueue.base) {
        return 0; // 内存分配失败
    }
    circularQueue.front = circularQueue.rear = 0; // 初始化队首和队尾指针
    circularQueue.maxSize = maxSize;
    return 1; // 初始化成功
}

3.销毁

// 销毁队列
void destroyQueue(CircularQueue &circularQueue) {
    if (circularQueue.base) {
        delete[] circularQueue.base; // 释放内存
        circularQueue.base = nullptr; // 将指针置为空
    }
}

4.清空队列

// 清空队列
void clearQueue(CircularQueue &circularQueue) {
    circularQueue.front = circularQueue.rear = 0; // 重置队首和队尾指针
}

5.队列是否为空

// 判断队列是否为空
bool isEmptyQueue(CircularQueue &circularQueue) {
    return circularQueue.front == circularQueue.rear; // 当队首和队尾指针相同时,队列为空
}

6.队列长度

// 获取队列长度
int queueLength(CircularQueue &circularQueue) {
    return (circularQueue.rear - circularQueue.front + circularQueue.maxSize) % circularQueue.maxSize;
}

7.队头

// 获取队首元素
Status getQueueFront(CircularQueue &circularQueue, int &frontElement) {
    if (isEmptyQueue(circularQueue)) {
        return 0; // 队列为空
    }
    frontElement = circularQueue.base[circularQueue.front];
    return 1; // 成功获取队首元素
}

8.入队

// 入队
bool enQueue(CircularQueue &circularQueue, int element) {
    // 检查队列是否已满
    if ((circularQueue.rear + 1) % circularQueue.maxSize == circularQueue.front) {
        return false; // 队列已满
    }
    // 入队操作
    circularQueue.base[circularQueue.rear] = element;
    circularQueue.rear = (circularQueue.rear + 1) % circularQueue.maxSize; // 移动队尾指针
    return true; // 入队成功
}

9.出队

// 出队
bool deQueue(CircularQueue &circularQueue, int &element) {
    // 检查队列是否为空
    if (isEmptyQueue(circularQueue)) {
        return false; // 队列为空,无法出队
    }
    // 出队操作
    element = circularQueue.base[circularQueue.front];
    circularQueue.front = (circularQueue.front + 1) % circularQueue.maxSize; // 移动队首指针
    return true; // 出队成功
}

10.遍历队列

// 遍历队列
void traverseQueue(CircularQueue &circularQueue) {
    // 遍历队列并打印元素
    int i = circularQueue.front;
    while (i != circularQueue.rear) {
        cout << circularQueue.base[i] << " ";
        i = (i + 1) % circularQueue.maxSize;
    }
    cout << endl;
}

11.完整代码

#include <iostream>
using namespace std;

typedef int Status;

struct CircularQueue {
    int *base;
    int front;
    int rear;
    int maxSize; // 队列的最大容量
};

// 队列初始化
Status initQueue(CircularQueue &circularQueue, int maxSize) {
    circularQueue.base = new int[maxSize]; // 为循环队列分配内存
    if (!circularQueue.base) {
        return 0; // 内存分配失败
    }
    circularQueue.front = circularQueue.rear = 0; // 初始化队首和队尾指针
    circularQueue.maxSize = maxSize;
    return 1; // 初始化成功
}

// 销毁队列
void destroyQueue(CircularQueue &circularQueue) {
    if (circularQueue.base) {
        delete[] circularQueue.base; // 释放内存
        circularQueue.base = nullptr; // 将指针置为空
    }
}

// 清空队列
void clearQueue(CircularQueue &circularQueue) {
    circularQueue.front = circularQueue.rear = 0; // 重置队首和队尾指针
}

// 判断队列是否为空
bool isEmptyQueue(CircularQueue &circularQueue) {
    return circularQueue.front == circularQueue.rear; // 当队首和队尾指针相同时,队列为空
}

// 获取队列长度
int queueLength(CircularQueue &circularQueue) {
    return (circularQueue.rear - circularQueue.front + circularQueue.maxSize) % circularQueue.maxSize;
}

// 获取队首元素
Status getQueueFront(CircularQueue &circularQueue, int &frontElement) {
    if (isEmptyQueue(circularQueue)) {
        return 0; // 队列为空
    }
    frontElement = circularQueue.base[circularQueue.front];
    return 1; // 成功获取队首元素
}

// 入队
bool enQueue(CircularQueue &circularQueue, int element) {
    // 检查队列是否已满
    if ((circularQueue.rear + 1) % circularQueue.maxSize == circularQueue.front) {
        return false; // 队列已满
    }
    // 入队操作
    circularQueue.base[circularQueue.rear] = element;
    circularQueue.rear = (circularQueue.rear + 1) % circularQueue.maxSize; // 移动队尾指针
    return true; // 入队成功
}

// 出队
bool deQueue(CircularQueue &circularQueue, int &element) {
    // 检查队列是否为空
    if (isEmptyQueue(circularQueue)) {
        return false; // 队列为空,无法出队
    }
    // 出队操作
    element = circularQueue.base[circularQueue.front];
    circularQueue.front = (circularQueue.front + 1) % circularQueue.maxSize; // 移动队首指针
    return true; // 出队成功
}

// 遍历队列
void traverseQueue(CircularQueue &circularQueue) {
    // 遍历队列并打印元素
    int i = circularQueue.front;
    while (i != circularQueue.rear) {
        cout << circularQueue.base[i] << " ";
        i = (i + 1) % circularQueue.maxSize;
    }
    cout << endl;
}

int main() {
    CircularQueue circularQueue;
    int maxSize = 10; // 队列的最大容量
    initQueue(circularQueue, maxSize); // 初始化循环队列

    // 测试入队
    for (int i = 1; i <= 5; ++i) {
        enQueue(circularQueue, i * 10);
    }

    // 输出队列元素
    cout << "队列元素:";
    traverseQueue(circularQueue);

    // 获取队首元素
    int frontElement;
    if (getQueueFront(circularQueue, frontElement)) {
        cout << "队首元素:" << frontElement << endl;
    }

    // 测试出队
    int element;
    for (int i = 0; i < 3; ++i) {
        if (deQueue(circularQueue, element)) {
            cout << "出队元素:" << element << endl;
        }
    }

    // 输出队列元素
    cout << "队列元素:";
    traverseQueue(circularQueue);

    // 判断队列是否为空
    if (isEmptyQueue(circularQueue)) {
        cout << "队列为空" << endl;
    } else {
        cout << "队列不为空" << endl;
    }

    // 获取队列长度
    cout << "队列长度:" << queueLength(circularQueue) << endl;

    // 清空队列
    clearQueue(circularQueue);

    // 判断清空后队列是否为空
    if (isEmptyQueue(circularQueue)) {
        cout << "清空队列后,队列为空" << endl;
    } else {
        cout << "清空队列后,队列不为空" << endl;
    }

    // 销毁队列
    destroyQueue(circularQueue);

    return 0;
}

3.参考资料

1.B站上看到的一个老师的讲解

2.数据结构C语言版(1997年清华大学出版社出版的图书)_百度百科

最近更新

  1. TCP协议是安全的吗?

    2024-05-12 07:54:10       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-12 07:54:10       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-12 07:54:10       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-12 07:54:10       18 阅读

热门阅读

  1. 第十七章 数据管理和组织变革管理练习

    2024-05-12 07:54:10       12 阅读
  2. go语言map底层及扩容机制原理详解(上)

    2024-05-12 07:54:10       10 阅读
  3. leetcode 1749.任意子数组和的绝对值的最大值

    2024-05-12 07:54:10       9 阅读
  4. PHP类和对象概念及用法

    2024-05-12 07:54:10       9 阅读
  5. C++Primer Plus第三章编程练习4

    2024-05-12 07:54:10       9 阅读
  6. Node.js -- 会话控制

    2024-05-12 07:54:10       8 阅读
  7. iOS 如何让超出父视图的部分响应事件

    2024-05-12 07:54:10       11 阅读
  8. 电商平台遭遇DDOS、CC攻击有什么防护方案

    2024-05-12 07:54:10       9 阅读
  9. Lucene 英文词根处理

    2024-05-12 07:54:10       11 阅读
  10. 十分钟“手撕”内部类+static在内部类的使用

    2024-05-12 07:54:10       11 阅读