一. 队列概念
只允许在一端进行数据插入,在另一端进行数据删除操作的特殊线性表
队首:进行数据删除操作的一端
队尾:进行数据插入操作的一端
特性:先入先出(FOFI)
二. 顺序队列两种定义方式
顺序表定义的队列数据结构
#define Datatype char // 队列中存储数据的类型
#define MAX_SIZE 100 // 队列最大长度
typedef struct SeqQueue {
Datatype data[MAX_SIZE];
int head;
int tail;
// 代表当前占用空间
int size;
}SeqQueue;
队首固定
队列的队首固定,入队列时队尾向后增长,出队列时,将队首元素出队列,队首之后的元素前移
队首移动
队列的队首不固定,入队列时队尾向后增长,出队列时,对首元素出队列,队首向后移动一个位置
顺序队列的假溢出问题
顺序队列因多次入队列和出队列操作后出现的尚有存储空间但不能再进行入队列操作的溢出。
即当队列出队列操作进行了若干次时,队首之前的位置其实已经空闲了,这时队尾移动到定义的数组最大长度MAX_SIZE-1下标
假溢出问题解决方法
因为顺序表天生具有的缺陷,所以为了解决这个问题,我们应该将顺序表队列改造成循环队列,即:
当队尾移动到MAX_SIZE-1时,判断队首位置,如果队首不为0,便将队尾置1
三. 相关函数
由于队列的特殊性,所以它的操作只有
void LinkQueueInit(LinkQueue* queue);// 初始化队列
void LinkQueueDestroy(LinkQueue* queue);// 销毁队列
int LinkQueuePush(LinkQueue* queue, Datatype value);// 入队列,尾插
int LinkQueuePop(LinkQueue* queue);// 出队列,头删
int LinkQueueTop(LinkQueue* queue, Datatype* value);// 取队首元素
SeqQueue.h
#pragma once
// 顺序表实现的队列,后进先出
#include <stdlib.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#define Datatype char
#define MAX_SIZE 100
typedef struct SeqQueue {
Datatype data[MAX_SIZE];
int head;
int tail;
// 代表当前占用空间
int size;
}SeqQueue;
// 初始化队列
void SeqQueueInit(SeqQueue* queue);
// 销毁队列
void SeqQueueDestroy(SeqQueue* queue);
// 入队列,尾插
int SeqQueuePush(SeqQueue* queue, Datatype value);
// 出队列,头删
int SeqQueuePop(SeqQueue* queue);
// 取队首元素
int SeqQueueTop(SeqQueue* queue, Datatype* value);
SeqQueue.c
#include "SeqQueue.h"
// 初始化队列
void SeqQueueInit(SeqQueue* queue) {
// 非法输入
if(queue == NULL) {
perror("Init");
return;
}
queue->head = queue->tail = 0;
queue->size = 0;
}
// 销毁队列
void SeqQueueDestroy(SeqQueue* queue) {
// 非法输入
if(queue == NULL) {
perror("Destroy");
return;
}
queue->tail = queue->head = queue->size = 0;
}
// 入队列,尾插
int SeqQueuePush(SeqQueue* queue, Datatype value) {
// 非法输入
if(queue == NULL) {
perror("Push");
return;
}
// 1. 队列未满
if(queue->size < MAX_SIZE-1) {
// a. 已达到数组最后一个元素,从数组头开始存储
if(queue->tail == MAX_SIZE-1) {
queue->tail = 0;
queue->data[queue->tail++] = value;
queue->size++;
}else {
// b. 未达到,继续向后存储
queue->data[queue->tail++] = value;
queue->size++;
}
}else {
// 2. 队列满
// a. 尾插失败
return 0;
}
return 1;
}
// 出队列,头删
int SeqQueuePop(SeqQueue* queue) {
// 非法输入
if(queue == NULL) {
perror("Pop");
return 0;
}
// 空队列
if(queue->size == 0) {
return 0;
}
if(queue->head == MAX_SIZE-1) {
queue->head = 0;
}else {
queue->head++;
queue->size--;
}
return 1;
}
// 取队首元素
int SeqQueueTop(SeqQueue* queue, Datatype* value) {
// 非法输入
if(queue==NULL || value==NULL) {
perror("Top");
return 0;
}
// 空队列
if(queue->size == 0) {
return 0;
}
*value = queue->data[queue->tail-1];
return 1;
}
/* ************************************************
* ******************** test**********************
* ***********************************************/
#if 1
#include <stdio.h>
#define FUNCTION() printf("\n================ %s ===============\n", __FUNCTION__)
// 队列打印
void print(SeqQueue queue, const char* msg) {
printf("\n%s\n", msg);
int i = 0 ;
int index = queue.head;
printf("head = %d, 队首:>\n", i);
for( ; i < queue.size; i++) {
if(index == MAX_SIZE) {
index = 0;
}
printf("%c\n", queue.data[index]);
index++;
}
}
// 入队列测试
void TestPush() {
FUNCTION();
SeqQueue queue;
SeqQueueInit(&queue);
SeqQueuePush(&queue, 'a');
SeqQueuePush(&queue, 'b');
SeqQueuePush(&queue, 'c');
SeqQueuePush(&queue, 'd');
print(queue, "入队列1,2,3,4");
}
// 出队列测试
void TestPop() {
FUNCTION();
SeqQueue queue;
SeqQueueInit(&queue);
SeqQueuePush(&queue, 'a');
SeqQueuePush(&queue, 'b');
SeqQueuePush(&queue, 'c');
SeqQueuePush(&queue, 'd');
print(queue, "队列初始化");
int ret = SeqQueuePop(&queue);
SeqQueuePop(&queue);
print(queue, "出队列两个");
SeqQueuePop(&queue);
print(queue, "出队列一个");
SeqQueuePop(&queue);
print(queue, "出队列一个");
SeqQueuePop(&queue);
print(queue, "空队列出队列");
}
// 取栈顶元素测试
void TestTop() {
FUNCTION();
SeqQueue queue;
SeqQueueInit(&queue);
SeqQueuePush(&queue, 'a');
SeqQueuePush(&queue, 'b');
SeqQueuePush(&queue, 'c');
SeqQueuePush(&queue, 'd');
print(queue, "队列初始化");
Datatype value;
SeqQueueTop(&queue, &value);
printf("top is %c\n", value);
// 销毁队列
SeqQueueDestroy(&queue);
print(queue, "销毁队列");
}
int main() {
TestPush();
TestPop();
TestTop();
return;
}
#endif