栈和队列是两个相似又相反的数据结构类型,但是受限于写栈的时候作者的时间和精力紧张就没有将两者放到一起,所以本篇我们将接着栈的内容继续深入学习与栈相对的另一种数据结构:队列
作者的个人gitee:楼田莉子 (riko-lou-tian) - Gitee.com
目录
概念
只允许一端插入数据操作,另一端进行删除操作的特殊线性表。
栈遵循“后进先出”,而队列遵循”先进先出“的原则
入队列:进行插入操作的一端是队尾
出队列:进行删除操作的一端是队头
底层结构是这样的
我们要用一个单链表实现队列。先确认一个单链表
队列结构的实现
因为队列是通过类似链表的结构模拟的,所以我们需要先定义一个”结点“的结构
typedef int QTypeData;
//队列结点结构
typedef struct queuenode
{
QTypeData data;
struct queuenode* next;
}QN;
接下来我们根据结点定义队列的结构
//队列结构
typedef struct queue
{
QN* phead;//队头指针
QN* ptail;//队尾指针
//频繁调用的时候需要用到size
//int size;//队列长度
}queue;
这样就完成了。
初始化队列
接下来我们要初始化队列
//初始化队列
void initqueue(queue* pq)
{
assert(pq!= NULL);
pq->phead = pq->ptail = 0;
}
入队
//入队-队尾入队
void enqueue(queue* pq, QTypeData data)
{
assert(pq!= NULL);
QN*new_node=(QN*)malloc(sizeof(QN));
//队列空间申请失败
if (new_node == NULL)
{
perror("malloc 失败");
exit(1);
}
new_node->data = data;
new_node->next = NULL;
//判断队列是否为空
if (pq->phead==NULL)
{
//队列为空,则new_node既是头结点也是尾结点
pq->phead = pq->ptail = new_node;
}
else
{
//队列不为空,则new_node是尾结点
pq->ptail->next = new_node;
pq->ptail = pq->ptail->next;
}
//方式二:
//++pq->size;
}
判断队列是否为空
出队的时候需要判断链表是否为空否则就会导致野指针的问题,因此在写出队列之前我们要先写一个判断队列是否为空的函数。
C语言中bool类型的函数必须包含头文件<stdbool.h>
//判断队列是否为空
bool isempty(queue* pq)
{
assert(pq!= NULL);
return pq->phead == NULL;
}
出队
//出队—队头出队
void dequeue(queue* pq)
{
assert(!isempty(pq));
if (pq->phead == pq->ptail)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
QN*next=pq->phead->next;
free(pq->phead);
pq->phead=next;
}
//方式二:
//--pq->size;
}
取数据
取队头数据
//取队头数据
QTypeData gethead(queue* pq)
{
assert(!isempty(pq));
return pq->phead->data;
}
取队尾数据
//取队尾数据
QTypeData gettail(queue* pq)
{
assert(!isempty(pq));
return pq->ptail->data;
}
size()
//取队列长度
int size(queue* pq)
{
QN* new_node = pq->phead;
int count = 0;
while (new_node != NULL)
{
count++;
new_node = new_node->next;
}
return count;
}
测试:
void que_test1()
{
queue q;
initqueue(&q);//初始化队列
enqueue(&q, 1);//入队
enqueue(&q, 2);
enqueue(&q, 3);
enqueue(&q, 4);
dequeue(&q);//出队
int x=gethead(&q);//获取队首元素
printf("x=%d\n", x);
int y=gettail(&q);//获取队尾元素
printf("y=%d\n", y);
//队列长度
printf("size=%d\n",size(&q));
destroyqueue(&q);//销毁队列
}
int main()
{
que_test1();
return 0;
}
结果为:
源代码:
queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int QTypeData;
//队列结点结构
typedef struct queuenode
{
QTypeData data;
struct queuenode* next;
}QN;
//队列结构
typedef struct queue
{
QN* phead;//队头指针
QN* ptail;//队尾指针
//频繁调用的时候需要用到size
//int size;//队列长度
}queue;
//初始化队列
void initqueue(queue* pq);
//入队
void enqueue(queue* pq, QTypeData data);
//出队
void dequeue(queue* pq);
//判断队列是否为空
bool isempty(queue* pq);
//取队头数据
QTypeData gethead(queue* pq);
//取队尾数据
QTypeData gettail(queue* pq);
//销毁队列
void destroyqueue(queue* pq);
//取队列长度
int size(queue* pq);
queue.c
#define _CRT_SECURE_NO_WARNINGS
#include"queue.h"
//初始化队列
void initqueue(queue* pq)
{
assert(pq!= NULL);
pq->phead = pq->ptail = 0;
}
//入队-队尾入队
void enqueue(queue* pq, QTypeData data)
{
assert(pq!= NULL);
QN*new_node=(QN*)malloc(sizeof(QN));
//队列空间申请失败
if (new_node == NULL)
{
perror("malloc 失败");
exit(1);
}
new_node->data = data;
new_node->next = NULL;
//判断队列是否为空
if (pq->phead==NULL)
{
//队列为空,则new_node既是头结点也是尾结点
pq->phead = pq->ptail = new_node;
}
else
{
//队列不为空,则new_node是尾结点
pq->ptail->next = new_node;
pq->ptail = pq->ptail->next;
}
//方式二:
//++pq->size;
}
//判断队列是否为空
bool isempty(queue* pq)
{
assert(pq!= NULL);
return pq->phead == NULL;
}
//出队—队头出队
void dequeue(queue* pq)
{
assert(!isempty(pq));
if (pq->phead == pq->ptail)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
QN*next=pq->phead->next;
free(pq->phead);
pq->phead=next;
}
//方式二:
//--pq->size;
}
//取队头数据
QTypeData gethead(queue* pq)
{
assert(!isempty(pq));
return pq->phead->data;
}
//取队尾数据
QTypeData gettail(queue* pq)
{
assert(!isempty(pq));
return pq->ptail->data;
}
//销毁队列
void destroyqueue(queue* pq)
{
assert(pq != NULL);
QN* new_node = pq->phead;
while (new_node != NULL)
{
QN*next=new_node->next;
free(new_node);
new_node=next;
}
pq->phead = pq->ptail = NULL;
}
//取队列长度
int size(queue* pq)
{
assert(!isempty(pq));
//适用于不频繁调用的情况
QN* new_node = pq->phead;
int count = 0;
while (new_node != NULL)
{
count++;
new_node = new_node->next;
}
return count;
//适用于频繁调用的情况
//return pq->size;
//但是出队列size--
}
test.c
#define _CRT_SECURE_NO_WARNINGS
#include"queue.h"
void que_test1()
{
queue q;
initqueue(&q);//初始化队列
enqueue(&q, 1);//入队
enqueue(&q, 2);
enqueue(&q, 3);
enqueue(&q, 4);
dequeue(&q);//出队
int x=gethead(&q);//获取队首元素
printf("x=%d\n", x);
int y=gettail(&q);//获取队尾元素
printf("y=%d\n", y);
//队列长度
printf("size=%d\n",size(&q));
destroyqueue(&q);//销毁队列
}
int main()
{
que_test1();
return 0;
}
本篇内容到这里就结束了,求一个点赞,谢谢
封面图自取: