C/C++数据结构 – 队列 循环队列
快速入门
介绍
1. 队列的定义
队列是一种线性存储结构,每次对队列的增删操作如下
-
增:在队列尾部添加元素
-
删(取出):在队列头部删除元素
这种数据存储方式遵循“
先进先出
”(First In First Out)的原则,简称
FIFO
结构;
2.队列的相关概念
(1)队头
(2)队尾
(3)空队列
(4)满队列
3. 队列相关操作
(1)入队:push()
(2)出队:pop()
(3)统计队列元素个数:countSize()
(4)判断队列是否为空:isEmpty()
(5)获取队头: getFront()
(6)获取队尾:getBack()
示例代码1:C++库函数举例
C++队列queue模板类的定义在
<queue>
头文件中,queue 模板类需要两个模板参数,一个是
元素类型
,一个
容器类型
,元素类型是必要的,容器类型是可选的,默认为deque 类型。C++队列Queue是一种容器适配器,它给予程序员一种先进先出(FIFO)的数据结构。
1. 头文件,队列声明,队列方法
#include <queue>
queue<int> q;
int i = 10;
q.push(i) 在队尾压入新元素
q.pop() 删除队列首元素但不返回其值
q.size() 返回队列中元素的个数
q.empty() 如果队列为空返回true,否则返回false
q.front() 返回队首元素的值,但不删除该元素
q.back() 返回队列尾元素的值,但不删除该元素
2.示例
#include <iostream>
#include <queue>
#include <string>
using namespace std;
int main()
{
queue<int> my_q;
string log;
for (int i = 0; i < 10; i++) {
my_q.push(i);
}
cout << "the front of q is " << my_q.front() << endl; // 返回定义类型
cout << "the back of q is " << my_q.back() << endl; // 返回定义类型
log = my_q.empty() == true ? "empty":"not empty"; // 返回布尔
cout << "my_q is " << log << endl;
cout << "my_q size is " << my_q.size() << endl; // 返回整数
while(!my_q.empty()) {
cout << "cur pop data = " << my_q.front();
my_q.pop(); // 无返回值
cout << " is poped" << endl;
}
return 0;
}
示例代码2:C语言静态队列(循环队列,定长队列)
C语言中,如果采用固定长度的一维数组来实现队列,通常使用循环队列的形式,避免普通队列由于顺序存储导致执行操作POP出队时带来的时间花费问题:每次从数组头部删除元素(出队)后,需要将头部以后的所有元素往前移动一个位置,这是一个时间复杂度为O(n)的操作。
循环队列的具体原理可以参考:
https://blog.csdn.net/li1914309758/article/details/81363166
由于循环队列存在弊端:
当队空时:front=rear
当队满时:front=rear 亦成立
因此只凭等式front=rear无法判断队空还是队满。 有两种方法处理上述问题:
(1)另设一个标志位以区别队列是空还是满。
(2)少用一个元素空间,约定以“队列头指针front在队尾指针rear的下一个位置上”作为队列“满”状态的标志。即:
队空时: front=rear
队满时: (rear+1)%maxsize=front
1. 头文件定义
本示例代码采用第一种方式处理循环队列的队空队满问题。
typedef struct _queue {
enum QUEUE_TYPE type;
int qcapacity; // 容量
int qsize; // 当前队列数据的数量
int front; // 队头
int back; // 队尾
int *qdata;
} Queue;
2. 源文件
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "DH_queue.h"
static Queue *static_queue(int len)
{
Queue *queue = (Queue *)malloc(sizeof(Queue));
memset(queue, 0, sizeof(Queue));
queue->qcapacity = len;
queue->qsize = 0;
queue->front = 0;
queue->back = 0;
queue->qdata = (int *)malloc(sizeof(int) * len);
memset(queue->qdata, 0, sizeof(int) * len);
return queue;
}
static int static_countSize(Queue *q)
{
return q->qsize;
}
static bool static_isEmpty(Queue *q)
{
if (q->qsize == 0) {
return 1;
}
return 0;
}
static bool static_isFull(Queue *q)
{
if (q->qsize == q->qcapacity) {
return 1;
}
return 0;
}
static int static_getFront(Queue *q)
{
return q->qdata[q->front];
}
static int static_getBack(Queue *q)
{
int index = ((q->back == 0) ? q->qcapacity - 1 : q->back - 1);
return q->qdata[index];
}
static bool static_push(Queue *q, void *data)
{
if (q->qsize == q->qcapacity) {
printf("queue is full, push fail\n");
return false;
}
q->qdata[q->back] = *(int *)data;
q->qsize += 1;
q->back = (q->back + 1) % q->qcapacity;
printf("q->back = %d", q->back);
return true;
}
static bool static_pop(Queue *q, int *data)
{
if (q->qsize == 0) {
printf("queue is empty, pop fail\n");
return false;
}
int tmp = 0;
tmp = q->qdata[q->front];
q->qsize -= 1;
q->front = (q->front + 1) % q->qcapacity;
return true;
}
// 主函数:测试代码
int main()
{
// 创建队列
Queue *my_queue = static_queue(5);
// 入列
for (int i = 0; i < 6; i++) {
printf("= %d\n", static_push(my_queue, &i));
}
// 遍历
for (int i = 0; i < 5; i++) {
printf("%d\n", my_queue->qdata[i]);
}
// 队头和队尾
printf("my_q front = %d, get front = %d, back = %d, get back = %d\n", my_queue->front, static_getFront(my_queue), my_queue->back, static_getBack(my_queue));
// 容积和队列元素
printf("my_q capacity = %d, qsize = %d\n", my_queue->qcapacity, my_queue->qsize);
// 队空和队满
printf("my_q isEmpty = %d, isFull = %d\n", static_isEmpty(my_queue), static_isFull(my_queue));
// 出队列
for (int i = 0; i < 6; i++) {
printf("= %d\n", static_pop(my_queue, &i));
}
return 0;
}