本文主要使用C语言实现队列(尾插和头删)
文章目录
前言
什们叫做队列
- 队列
- 只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列。
进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头
- 只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列。
队列的实现
但是有人就会说,那是队列的话,尾插不也是很难吗?错了,我们可以定义一个头指针,一个尾指针,然后我们在尾插的时候我们直接用尾插就好了。
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低
创建工程文件还是三个文件
Queue.c
,用来编写队列的函数内容
Queue.h
用来包含函数的头文件
test.c
用来测试函数。
(1)创建一个链式结构-表示队列
typedef int QDtataType;
//队列的链式结构
typedef struct QueueNode
{
QDtataType data;
struct QueueNode* next;
}QNode;
(2)队列的结构
我们队列包括,一个头和一个尾,来控制头插和尾插,还有一个sz知道队列的大小,我们要控制多个变量,我们就用结构体来控制,所以队列的结构如下。
//队列的结构
typedef struct Queue
{
QNode* front;
QNode* rear;
int size;
}Queue;
这里的有点乱,我们画个图详细剖析一下
(3)队列的初始化
//队列的初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->front = pq->rear = NULL;
pq->size = 0;
}
(4)队列的销毁
//队列销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->front;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->front = pq->rear = NULL;
pq->size = 0;
}
(5)队列的插入<队尾入队列>
//队列的插入
//尾插
void QueuePush(Queue* pq, QDtataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->rear == NULL)
{
pq->front = pq->rear = newnode;
}
else
{
pq->rear->next = newnode; //尾插
pq->rear = newnode;//更新头的位置
}
pq->size++;
}
(6)判断队列是否为空
//队列的判空
int QueueEmpty(Queue* pq)
{
assert(pq);
return pq->front == NULL && pq->rear == NULL;
//return pq->size == 0; //这样也行,但是,这个size是我们自己加到队列里面的,是为了方便求队列元素的个数
}
(7)队列的删除<队头出队列>
//队列的删除
//头删
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
if (pq->front->next == NULL)
{
free(pq->front);
pq->front = pq->rear = NULL;
}
else
{
QNode* next = pq->front->next; //保存头的下一个
free(pq->front); //删除头
pq->front = next; //更新头
}
pq->size--;
}
(8)队列的大小
//队列的大小
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
(9)取队头数据
//获取队头数据
QDtataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->front->data;
}
(10)取队尾数据
//获取队尾数据
QDtataType QueueRear(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->rear->data;
}
程序源码
Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
typedef int QDtataType;
//队列的链式结构
typedef struct QueueNode
{
QDtataType data;
struct QueueNode* next;
}QNode;
//队列的结构
typedef struct Queue
{
QNode* front;
QNode* rear;
int size;
}Queue;
//队列的初始化
void QueueInit(Queue* pq);
//队列销毁
void QueueDestroy(Queue* pq);
//队列的插入
void QueuePush(Queue* pq, QDtataType x);
//队列的删除
void QueuePop(Queue* pq);
//队列的判空
int QueueEmpty(Queue* pq);
//队列的大小
int QueueSize(Queue* pq);
//获取队头数据
QDtataType QueueFront(Queue* pq);
//获取队尾数据
QDtataType QueueRear(Queue* pq);
Queue.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "queue.h"
//队列的初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->front = pq->rear = NULL;
pq->size = 0;
}
//队列销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->front;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->front = pq->rear = NULL;
pq->size = 0;
}
//队列的插入
//尾插
void QueuePush(Queue* pq, QDtataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->rear == NULL)
{
pq->front = pq->rear = newnode;
}
else
{
pq->rear->next = newnode; //尾插
pq->rear = newnode;//更新头的位置
}
pq->size++;
}
//队列的判空
int QueueEmpty(Queue* pq)
{
assert(pq);
return pq->front == NULL && pq->rear == NULL;
//return pq->size == 0; //这样也行,但是,这个size是我们自己加到队列里面的,是为了方便求队列元素的个数
}
//队列的删除
//头删
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
if (pq->front->next == NULL)
{
free(pq->front);
pq->front = pq->rear = NULL;
}
else
{
QNode* next = pq->front->next; //保存头的下一个
free(pq->front); //删除头
pq->front = next; //更新头
}
pq->size--;
}
//队列的大小
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
//获取队头数据
QDtataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->front->data;
}
//获取队尾数据
QDtataType QueueRear(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->rear->data;
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "queue.h"
void test()
{
Queue pq;
QueueInit(&pq);
QueuePush(&pq, 1);
QueuePush(&pq, 2);
QueuePush(&pq, 3);
printf("size=%d\n", QueueSize(&pq));
printf("%d\n", QueueFront(&pq));
printf("%d\n", QueueRear(&pq));
QueuePop(&pq);
QueuePop(&pq);
QueueDestroy(&pq);
}
int main()
{
test();
return 0;
}