1.队列的概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
队头(Front):允许删除的一端,又称队首。
队尾(Rear):允许插入的一端。
空队列:不包含任何元素的空表。
2.队列的常见操作
// 链式结构:表示队列
typedef struct QListNode
{
struct QListNode* _next;
QDataType _data;
}QNode;
// 队列的结构
typedef struct Queue
{
QNode* _front;
QNode* _rear;
}Queue;
// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDataType QueueFront(Queue* q);
// 获取队列队尾元素
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);
2.1初始化队列
void QueueInit(Queue* q)
{
assert(q);
q->_front = NULL;//队头
q->_rear = NULL;//队尾
q->size = 0;//队列元素个数
}
2.2队尾入队列
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
newnode->_next = NULL;
newnode->_data = data;
if (q->_rear == NULL)
{
q->_front = q->_rear = newnode;//如果开始队列为空,则最开始队头和队尾都指向新建节点
}
else {
q->_rear->_next= newnode;//接在队尾后面
q->_rear = newnode;//修改队尾指针
}
q->size++;//个数++
}
2.3队头出队
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
assert(q->size > 0);
if (q->_front != q->_rear)//队头不等于队尾时,free掉队头节点,修改队头指针
{
QNode* node = q->_front;
q->_front = node->_next;
free(node);
}
else//若队头指针等于队尾指针,就都free掉,指向NULL
{
free(q->_front);
q->_front = NULL;
q->_rear = NULL;
}
q->size--;
}
2.4获取队头元素、队尾元素、和队内个数
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
return q->_front->_data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
return q->_rear->_data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
return q->size;
}
2.5检验队列是否为空
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
return q->size==0;
}
2.6销毁队列
// 销毁队列
void QueueDestroy(Queue* q)
{
QNode* cur = q->_front;
while (cur)
{
QNode* next = cur->_next;
free(cur);
cur = next;
}
q->_front = NULL;
q->_rear = NULL;
}
综合:
#include"line.h"
void QueueInit(Queue* q)
{
assert(q);
q->_front = NULL;
q->_rear = NULL;
q->size = 0;
}
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
newnode->_next = NULL;
newnode->_data = data;
if (q->_rear == NULL)
{
q->_front = q->_rear = newnode;
}
else {
q->_rear->_next= newnode;
q->_rear = newnode;
}
q->size++;
}
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
assert(q->size > 0);
if (q->_front != q->_rear)
{
QNode* node = q->_front;
q->_front = node->_next;
free(node);
}
else
{
free(q->_front);
q->_front = NULL;
q->_rear = NULL;
}
q->size--;
}
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
return q->_front->_data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
return q->_rear->_data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
return q->size==0;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
QNode* cur = q->_front;
while (cur)
{
QNode* next = cur->_next;
free(cur);
cur = next;
}
q->_front = NULL;
q->_rear = NULL;
}
3.队列的实际运用
typedef int QDataType;
//队列结构体
typedef struct QListNode
{
struct QListNode* _next;
QDataType _data;
}QNode;
// 队列的结构
typedef struct Queue
{
QNode* _front;
QNode* _rear;
QDataType size;
}Queue;
// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDataType QueueFront(Queue* q);
// 获取队列队尾元素
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);
void QueueInit(Queue* q)
{
assert(q);
q->_front = NULL;
q->_rear = NULL;
q->size = 0;
}
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
newnode->_next = NULL;
newnode->_data = data;
if (q->_rear == NULL)
{
q->_front = q->_rear = newnode;
}
else {
q->_rear->_next= newnode;
q->_rear = newnode;
}
q->size++;
}
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
assert(q->size > 0);
if (q->_front != q->_rear)
{
QNode* node = q->_front;
q->_front = node->_next;
free(node);
}
else
{
free(q->_front);
q->_front = NULL;
q->_rear = NULL;
}
q->size--;
}
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
return q->_front->_data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
return q->_rear->_data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
return q->size==0;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
QNode* cur = q->_front;
while (cur)
{
QNode* next = cur->_next;
free(cur);
cur = next;
}
q->_front = NULL;
q->_rear = NULL;
}
//创建包含两个队列的结构体
typedef struct {
Queue q1;
Queue q2;
} MyStack;
//初始化
MyStack* myStackCreate()
{
MyStack* p = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&(p->q1));
QueueInit(&(p->q2));
return p;
}
//入栈
//推入数据:推入一个不为空的队列
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&(obj->q1)))
{
QueuePush(&(obj->q1),x);
}else{
QueuePush(&(obj->q2),x);
}
}
//出栈
//删除数据,将要不为空的队列的前size-1个数据推到空队中,在free掉剩余数据
int myStackPop(MyStack* obj) {
//假设发找到空队列和非空队列
Queue* empty = &(obj->q1);
Queue* nonempty = &(obj->q2);
if(!QueueEmpty(&(obj->q1)))
{
nonempty = &(obj->q1);
empty = &(obj->q2);
}
//推前size-1个数据到空队列中
while(QueueSize(nonempty)>1)
{
QueuePush(empty,QueueFront(nonempty));
QueuePop(nonempty);
}
//取数据,出队
int top = QueueFront(nonempty);
QueuePop(nonempty);
return top;
}
//取栈顶元素
//取不为空的队列的队尾元素
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1))
{
return QueueBack(&obj->q1);
}else{
return QueueBack(&obj->q2);
}
}
//检验栈是否为空
//检验两个队列是否为空
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&(obj->q1))&&QueueEmpty(&(obj->q2));
}
//销毁栈
//销毁两个队列,再销毁两个队列的结构体
void myStackFree(MyStack* obj) {
QueueDestroy(&(obj->q1));
QueueDestroy(&(obj->q2));
free(obj);
}
图例:
//循环队列
typedef struct {
int* a;
int head;//头下标
int tail;//队尾元素的下一个位置的下标
int n;//队列个数
} MyCircularQueue;
//判断循环队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* q)
{
if (q->head == q->tail)//当头下标==尾下标是,为空
{
return true;
}
return false;
}
//判断是否为满
bool myCircularQueueIsFull(MyCircularQueue* q) {
return (q->tail + 1) % (q->n + 1) == q->head;//当尾下标的下一个数据为投下标是,为满
}
//创建循环队列框架
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
q->a = NULL;
q->a = (int*)malloc(sizeof(int)*1000);
q->head = 0;
q->tail = 0;
q->n = k;
return q;
}
//插入数据
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
//判满
if (myCircularQueueIsFull(obj))return false;
obj->a[obj->tail] = value;
obj->tail++;
obj->tail = obj->tail % (obj->n + 1);
return true;
}
//出队
bool myCircularQueueDeQueue(MyCircularQueue* q) {
if (myCircularQueueIsEmpty(q))return false;
q->head++;
q->head = q->head % (q->n + 1);
return true;
}
//返回队头元素
int myCircularQueueFront(MyCircularQueue* obj) {
if (myCircularQueueIsEmpty(obj))return -1;
return obj->a[obj->head];
}
//返回队尾元素,有东西
int myCircularQueueRear(MyCircularQueue* obj) {
if (myCircularQueueIsEmpty(obj))return -1;
return obj->a[(obj->tail - 1 + obj->n + 1) % (obj->n + 1)];
}
//销毁队列
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
obj->a = NULL;
obj->head = 0;
obj->tail = 0;
obj->n = 0;
free(obj);
}
重点讲解:
判满:
返回队尾元素:下面是一个特例,对其他平常例子也是使用的