队列的概念以及结构
队列也是一种操作受限的线性表,只允许在表的一端进行插入,另一端进行删除。队列中插入元素称为入队或进队;删除元素称为出队或离队。队列的操作特性是先进先出。
队头:允许删除的一端。
队尾:允许插入的一端。
队列的实现
分为三个文件实现:queue.h
、queue.c
、test.c
- queue.h
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDatatype;
typedef struct QueueNode
{
QDatatype data;
struct QueueNode* next;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
int size;
}Queue;
//初始化
void QueueInit(Queue* pq);
// ⼊队列,队尾
void QueuePush(Queue* pq, QDatatype x);
//队列判空
bool QueueEmpty(Queue* pq);
// 出队列,队头
void QueuePop(Queue* pq);
//取队头数据
QDatatype QueueFront(Queue* pq);
//取队尾数据
QDatatype QueueBack(Queue* pq);
//队列有效元素个数
int QueueSize(Queue* pq);
//销毁队列
void QueueDestroy(Queue* pq);
与之前的线性表实现不同的是,队列的实现需要两个struct
结构来实现
- queue.c
队列的初始化
思路:将pq
的size
赋值为0,head
和tail
置空
void QueueInit(Queue* pq)
{
assert(pq);
pq->size = 0;
pq->head = pq->tail = NULL;
}
入队
思路:
- 创建新结点
newnode
- 若此时队列为空,则将
pq
的head
和tail
都赋值为newnode
;若不为空,则将newnode
尾插到tail后 - 将
size++
void QueuePush(Queue* pq, QDatatype x)
{
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
if (newnode == NULL)
{
perror("malloc fail!");
exit(1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = pq->tail->next;
}
pq->size++;
}
出队
思路:
- 判断队列是否为空
- 若只有一个数据,则将
pq
的head
进行free
,并将pq
的head
和tail
置空;若有多个数据,则创建新变量next
,将next
赋值为pq
的head
的next
,再将pq
的head
进行free
并置空 - 将
pq
的size--
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL;
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
if (pq->head == pq->tail)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QueueNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
取队头数据
QDatatype QueueFront(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
return pq->head->data;
}
取队尾数据
QDatatype QueueBack(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
return pq->tail->data;
}
队列有效元素个数
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
销毁队列
思路:
- 判断队列不为空
- 创建新结点
pcur
代替pq
的head
进行遍历 - 创建新结点
next
赋值为pcur
的next
,将pcur
进行free
并赋值为next
,直到运行到NULL
- 将
pq
的head
和tail
置空,将size
赋值为0
void QueueDestroy(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
QueueNode* pcur = pq->head;
while (pcur)
{
QueueNode* next = pcur->next;
free(pcur);
pcur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
- test.c
#include"queue.h"
void Test()
{
Queue pq;
QueueInit(&pq);
QueuePush(&pq,1);
QueuePush(&pq, 2);
QueuePush(&pq, 3);
QueuePush(&pq, 4);
QueuePop(&pq);
QDatatype tmp= QueueFront(&pq);
printf("QueueFront=%d\n",tmp);
QDatatype tmp2 = QueueBack(&pq);
printf("QueueBack=%d\n", tmp2);
QDatatype tmp3 = QueueSize(&pq);
printf("size=%d\n", tmp3);
QueueDestroy(&pq);
}
int main()
{
Test();
return 0;
}