特点:先进先出 First In First Out (FIFO),一端只能进,一端只能出
术语:队头,队尾,空队列
1. 牺牲一个存储单元的队列
1.1 定义结构体
# define MaxSize 10
typedef struct {
int data[MaxSize]; // 使用静态数组来存储队列元素,分配内存空间
int rear, front; // 定义两个指针变量指向队头和队尾
} SqQueue; // Sq - sequence - 顺序
1.2 初始化队列
初始化队列时,默认队头队尾都指向索引为0的位置,front永远指向队头,而rear指向需要插入元素的位置
void InitSqQueue(SqQueue* Q){
Q->front = Q->rear = 0;
}
1.3 判空
这里不是存储真实指针,只是一个指针变量,用.来表示
bool EmptySqQueue(SqQueu Q){
return (Q.front == Q.rear);
}
1.4 入队
MaxSize=10,当队列长度为10时,rear刚好等于10,队列满,但是如果队头出队,则队列又未满,可以通过取余的方式,Q->rear = (Q->rear+1) % MaxSize
,即队尾递增的时候,加一再取模,将无线的整数映射到有限的整数集合中,那么,当rear的下一个位置是front,队尾的下一个位置是队头,则队满,因为如果rear=front就是为判空条件,而且rear永远指向下一个可以插入的元素,条件重合,固牺牲一个存储单元
bool EnQueue(SqQueue* Q, int x){
// 判断队满,(Q->rear + 1) % MaxSize是rear下一个要走的位置
if (((Q->rear + 1) % MaxSize) == Q->front) {
return false;
}
Q->data[Q->rear] = x;
Q->rear = (Q->rear + 1) % MaxSize;
return true;
}
1.5 出队
出队操作后,front指针同样也要取模操作,为了形成循环队列
bool DeQueue(SqQueue* Q, int* x){
// 判断队列空
if (Q->front == Q->rear){
return false;
}
*x = Q->data[Q->front];
Q->front = (Q->front + 1) % MaxSize;
}
1.6 获取队头元素
bool GetHead(SqQueue* Q, int* x){
if (Q->front == Q->rear){
return false;
}
*x = Q->data[Q->front];
return true;
}
1.7 判断已满
bool FullQueue(SqQueue* Q){
return (((Q->rear + 1) % MaxSize) == Q->front);
}
1.8 获取元素个数
公式:(rear + length - front) % length
int GetNodeNum(SqQueue* Q){
int num = (Q->rear + MaxSize - Q->front) % MaxSize;
return num;
}
2. 满队列 - 基于队列长度
在定义结构体时,增加一个size变量来存储当前队列的长度,初始化为0,入队时长度++,出队时长度–,判空则判断长度是否等于0且头尾指针指向同个节点,判满则判断长度是否等于队列最大长度,此时队满后,rear和front也指向同个节点
// ------- [结构体] ------
# define MaxSize 10
typedef struct {
int data[MaxSize];
int front, rear;
int size;
} SqQueue;
// ------- [初始化] ------
void InitSqQueue(SqQueue* Q) {
Q->front = Q->rear = 0;
Q->size = 0;
}
// ------- [入队] ------
bool EnSqQueue(SqQueue* Q, int x) {
if (Q->size == MaxSize) {
return false;
}
Q->data[Q->rear] = x;
Q->rear = (Q->rear + 1) % MaxSize;
Q->size++;
return true;
}
// ------- [出队] ------
bool DeSqQueue(SqQueue* Q, int* x) {
if (Q->front == Q->rear && Q->size == 0) {
return false;
}
*x = Q->data[Q->front];
Q->front = (Q->front + 1) % MaxSize;
Q->size--;
return true;
}
// ------- [判空] ------
bool IsEmpty(SqQueue* Q) {
return (Q->size == 0);
}
// ------- [判满] ------
bool IsFull(SqQueue* Q) {
return Q->size == MaxSize; // 队列已满返回true
}
// ------- [打印] ------
void PrintQueue(SqQueue* Q) {
if (IsEmpty(Q)) {
printf("Queue is empty!\n");
return;
}
printf("Queue elements: ");
for (int i = 0; i < Q->size; i++) {
printf("%d ", Q->data[(Q->front + i) % MaxSize]);
}
printf("\n");
}
// 测试代码
int main() {
SqQueue queue;
InitSqQueue(&queue); // 初始化队列
// 入队操作
for (int i = 0; i < 5; i++) {
if (EnSqQueue(&queue, i)) { printf("Enqueued - 入队: %d\n", i); }
else { printf("Queue is full!\n"); }
}
PrintQueue(&queue); // 打印队列元素
// 出队操作
int value;
for (int i = 0; i < 3; i++) {
if (DeSqQueue(&queue, &value)) { printf("Dequeued - 出队: %d\n", value); }
else { printf("Queue is empty!\n"); }
}
PrintQueue(&queue); // 打印队列元素
// 再次入队
for (int i = 5; i < 10; i++) {
if (EnSqQueue(&queue, i)) { printf("Enqueued - 入队: %d\n", i); }
else { printf("Queue is full!\n"); }
}
PrintQueue(&queue); // 打印队列元素
// 继续出队操作
while (!IsEmpty(&queue)) {
if (DeSqQueue(&queue, &value)) { printf("Dequeued - 出队: %d\n", value); }
}
PrintQueue(&queue); // 打印队列元素
return 0;
}
3. 满队列 - 基于flag变量
每次入队时,flag=1,每次出队时,flag=0,当操作到 front=rear 时,可以依靠flag来判断最后一次操作时插入还是删除,初始化flag=0
// ------- [结构体] ------
# define MaxSize 10
typedef struct {
int data[MaxSize];
int front, rear;
int flag;
} SqQueue;
// ------- [初始化] ------
void InitSqQueue(SqQueue* Q) {
Q->front = Q->rear = 0;
Q->flag = 0;
}
// ------- [入队] ------
bool EnSqQueue(SqQueue* Q, int x) {
if (Q->rear == Q->front && Q->flag == 1) { // 队满判断
return false;
}
Q->data[Q->rear] = x;
Q->rear = (Q->rear + 1) % MaxSize;
Q->flag = 1;
return true;
}
// ------- [出队] ------
bool DeSqQueue(SqQueue* Q, int* x) {
if (Q->front == Q->rear && Q->flag== 0) { // 队空判断
return false;
}
*x = Q->data[Q->front];
Q->front = (Q->front + 1) % MaxSize;
Q->flag = 0;
return true;
}
// ------- [判空] ------
bool IsEmpty(SqQueue* Q) {
return (Q->front == Q->rear && Q->flag == 0);
}
// ------- [判满] ------
bool IsFull(SqQueue* Q) {
return (Q->front == Q->rear && Q->flag == 1);
}
// ------- [打印] ------
void PrintQueue(SqQueue* Q) {
if (IsEmpty(Q)) {
printf("Queue is empty!\n");
return;
}
printf("Queue elements: ");
SqQueue* pointer = Q;
for (int i = 0; i < ((Q->rear + MaxSize - Q->front) % MaxSize); i++) {
printf("%d ", Q->data[(Q->front + i) % MaxSize]);
}
printf("\n");
}
// 测试代码
int main() {
SqQueue queue;
InitSqQueue(&queue); // 初始化队列
// 入队操作
for (int i = 0; i < 5; i++) {
if (EnSqQueue(&queue, i)) { printf("Enqueued - 入队: %d\n", i); }
else { printf("Queue is full!\n"); }
}
PrintQueue(&queue); // 打印队列元素
// 出队操作
int value;
for (int i = 0; i < 3; i++) {
if (DeSqQueue(&queue, &value)) { printf("Dequeued - 出队: %d\n", value); }
else { printf("Queue is empty!\n"); }
}
PrintQueue(&queue); // 打印队列元素
// 再次入队
for (int i = 5; i < 10; i++) {
if (EnSqQueue(&queue, i)) { printf("Enqueued - 入队: %d\n", i); }
else { printf("Queue is full!\n"); }
}
PrintQueue(&queue); // 打印队列元素
// 继续出队操作
while (!IsEmpty(&queue)) {
if (DeSqQueue(&queue, &value)) { printf("Dequeued - 出队: %d\n", value); }
}
PrintQueue(&queue); // 打印队列元素
return 0;
}