定义
队列是只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
实现
队列可以数组和链表的结构实现,使用链表的结构实现好一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低
代码
此处我们使用链表实现一个支持动态增长的栈
Queue.h
#include<stdio.h>
#include<string.h>
#include<assert.h>
typedef int DataType;
typedef struct QueueNode
{
DataType _data;
struct QueueNode* _next;
}QueueNode;
typedef struct Queue
{
QueueNode* _front; // 队头
QueueNode* _rear; // 队尾
}Queue;
void QueueInit(Queue* q);//初始化
void QueueDestroy(Queue* q);//销毁
void QueuePush(Queue* q, DataType x);//插入
void QueuePop(Queue* q);//删除
DataType QueueFront(Queue* q);//返回队头元素
DataType QueueBack(Queue* q);//返回队尾元素
int QueueEmpty(Queue* q);//判空
int QueueSize(Queue* q);//计算长度
void QueuePrint(Queue* q);//输出
Queue.c
#include "Queue.h"
//队列
void QueueInit(Queue* q)//初始化
{
assert(q);
q->_front = NULL;
q->_rear = NULL;
}
void QueueDestroy(Queue* q)//销毁
{
assert(q);
QueueNode* cur = q->_front;
while (cur)
{
QueueNode* next = cur->_next;
free(cur);
cur = next;
}
q->_front = q->_rear = NULL;
}
void QueuePush(Queue* q, DataType x)//插入
{
assert(q);
QueueNode* newNode = (Queue*)malloc(sizeof(QueueNode));
newNode->_data = x;
newNode->_next = NULL;
if (q->_front == NULL)
{
q->_front = q->_rear = newNode;
}
else
{
q->_rear->_next = newNode;
q->_rear = q->_rear->_next;
}
}
void QueuePop(Queue* q)//删除
{
assert(q);
if (q->_front)
{
QueueNode* next = q->_front->_next;
free(q->_front);
q->_front = next;
if (q->_front == NULL)
q->_rear = NULL;
}
}
DataType QueueFront(Queue* q)//返回队头元素
{
assert(q);
if (q->_front)
return q->_front->_data;
return -1;
}
DataType QueueBack(Queue* q)//返回队尾元素
{
assert(q);
if (q->_rear)
return q->_rear->_data;
return -1;
}
int QueueEmpty(Queue* q)//判空
{
assert(q);
if (q->_front == NULL)
return 1;
else
return 0;
}
int QueueSize(Queue* q)//计算长度
{
int n = 0;
QueueNode* cur = q->_front;
while (cur)
{
++n;
cur = cur->_next;
}
return n;
}
void QueuePrint(Queue* q)//输出
{
assert(q);
QueueNode* cur = q->_front;
while (cur)
{
printf("%d ", cur->_data);
cur = cur->_next;
}
printf("\n");
}
void test()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePrint(&q);
QueueDestroy(&q);
}
int main()
{
test();
return 0;
}
运用
设计循环队列
循环队列是一种线性数据结构,其操作表现基于先进先出原则,并且队尾被连接在队首之后以形成一个循环,即环形缓冲器
循环队列的关键在于模拟循环,处理数组边界
typedef struct {
int *data;
int head;
int tail;
int cap;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) //设置队长k
{
MyCircularQueue *queue = (MyCircularQueue *)malloc(sizeof(MyCircularQueue));
queue -> data = (int *)malloc((k + 1) * sizeof(int)); //模拟动态数组,留出一位空闲
queue -> head = 0;
queue -> tail = 0;
queue -> cap = k + 1;
return queue;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) //判空
{
if(obj -> head == obj -> tail)
{
return true;
}
return false;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) //判满
{
if(obj -> head == (obj -> tail + 1) % (obj -> cap))
{
return true;
}
return false;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)//插入
{
if(myCircularQueueIsFull(obj) == true)
{
return false;
}
obj -> data[obj -> tail] = value;//First In
obj -> tail = (obj -> tail + 1) % (obj -> cap); //索引 + 1,并且要注意取模计算,实现循环队列
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)//删除
{
if(myCircularQueueIsEmpty(obj) == true)
{
return false;
}
obj -> head = (obj -> head + 1) % (obj -> cap);
return true;
}
int myCircularQueueFront(MyCircularQueue* obj)// 从队首获取元素
{
if(myCircularQueueIsEmpty(obj) == true)
{
return -1;
}
else
{
return obj ->data[obj -> head];
}
}
int myCircularQueueRear(MyCircularQueue* obj) // 从队尾获取元素
{
if(myCircularQueueIsEmpty(obj) == true)
{
return -1;
}
return obj -> data[(obj-> tail - 1 + obj -> cap) % (obj -> cap)]; //注意处理
}
void myCircularQueueFree(MyCircularQueue* obj)//销毁
{
free(obj -> data);
obj -> data = NULL;
free(obj);
obj = NULL;
}