🌠作者:@阿亮joy.
🎆专栏:《数据结构与算法要啸着学》
🎇座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根
👉队列的概念及结构👈
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的原则
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
队列的结构在生活中非常地常见,比如排队时的抽号机就是一个典型的队列结构。那队列如何实现呢?我们一起来看一下。
👉队列的实现👈
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些。因为如果使用数组的结构,出队列在数组头上出数据,需要挪动数据,时间复杂度为
O(N)
,效率会比较低。
Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int QDataType;
typedef struct QueueNode
{
QDataType data;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* head; // 头指针
QNode* tail; // 尾指针
int size; // 节点的个数
}Queue;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);
队列要实现的函数接口有:初始化队列、销毁队列、数据入队、数据出队、返回队头的数据、返回队尾的数据、判断队列是否为空以及队列中数据的个数。这些接口实现起来也不是很难,我们一起来看一下。
Queue.c
#include "Queue.h"
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* del = cur;
cur = cur->next;
free(del);
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
else
{
newnode->data = x;
newnode->next = NULL;
}
// 队列中没有节点
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
// 队列中只有一个节点
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* del = pq->head;
pq->head = pq->head->next;
free(del);
//del = NULL;
}
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;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->size == 0;
//return pq->head == NULL && pq->tail == NULL;
}
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
初始化队列
头指针和尾指针都指向空,队列元素个数初始化为0
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
销毁队列
利用
while
循环将申请的节点一一释放掉,然后头指针pq->head
和尾指针pq->tail
指向空,栈的数据个数置为 0pq->size = 0
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* del = cur;
cur = cur->next;
free(del);
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
数据入队
1.申请新的节点
newnode
newnode->data = x,newnode->next = NULL
2.数据入队:当pq->tail == NULL
时,队列中没有节点,那么头指针和尾指针都赋值为newnode
pq->head = pq->tail = newnode
;当pq->tail != NULL
时,队列中有节点,那么尾部链接上新节点newnode
,然后newnode
成为新的尾结点。
3.队列数据个数加一pq->size++
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
else
{
newnode->data = x;
newnode->next = NULL;
}
// 队列中没有节点
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
数据出队
1.判断队列是否为空
2.数据出队:当pq->head->next == NULL
时,队列中只有一个节点,释放该节点,头指针和尾指针都指向空;当pq->head->next != NULL
时,释放让头指针指向当前节点的下一个节点,释放原来的头节点
3.队列数据个数减一pq->size--
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
// 队列中只有一个节点
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* del = pq->head;
pq->head = pq->head->next;
free(del);
//del = NULL;
}
pq->size--;
}
返回队头数据
先判断队列是否为空,不为空时,返回队头数据。
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
返回队尾数据
先判断队列是否为空,不为空时,返回队尾数据。
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
判断队列是否为空
判断队列是否为空有两种方式:1.判断
pq->size
等不等于 0;2.判断头指针pq->head
和尾指针pq->tail
是否等于空指针NULL
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->size == 0;
//return pq->head == NULL && pq->tail == NULL;
}
队列中数据的个数
直接返回队列数据的个数
pq->size
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
Test.c
以下为测试函数接口的代码,大家可以参考一下。需要注意的是,打印队列中的数据是通过打印队头数据、Pop
掉队头数据的方式来实现的。
#include "Queue.h"
void QueueTest()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
printf("%d ", QueueFront(&q));
QueuePop(&q);
printf("%d ", QueueFront(&q));
QueuePop(&q);
QueuePush(&q, 4);
QueuePush(&q, 5);
QueuePush(&q, 6);
while (!QueueEmpty(&q))
{
printf("%d ", QueueFront(&q));
QueuePop(&q);
}
printf("\n");
QueueDestroy(&q);
}
int main()
{
QueueTest();
return 0;
}
文章来源:https://www.toymoban.com/news/detail-471469.html
👉总结👈
本篇博客主要讲解了队列的实现,最重要的函数接口是数据入队和数据出队。在下一篇博客,本人将给大家带来几道 OJ 题,大家可以期待一下。以上就是本篇博客的全部内容了,如果大家觉得有收获的话,可以点个三连支持一下!谢谢大家啦!💖💝❣️文章来源地址https://www.toymoban.com/news/detail-471469.html
到了这里,关于【数据结构与算法】队列的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!