赞
踩
目录
之前我们了解到栈是一种特殊的线性表,现在我们来介绍另外一种特殊的线性表队列,队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。
实际中我们有时还会使用一种队列叫循环队列。操作系统中生产者消费者模型 时可以就会使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。
- typedef int QDataType;
-
- //队列节点
- typedef struct QueueNode {
- QDataType data;
- struct QueueNode* next;
- }QNode;
-
- //队列结构
- typedef struct Queue {
- QNode* phead;//头节点
- QNode* ptail;//尾节点
- int sz;
- }Queue;
-
- //初始化队列
- void QueueInit(Queue* pq);
-
- //入队列(队尾)
- void QueuePush(Queue* pq,QDataType x);
-
- //出队列(队头)
- void QueuePop(Queue* pq);
-
- //获取队列头部元素
- QDataType QueueFront(Queue* pq);
-
- //获取队列尾部元素
- QDataType QueueBack(Queue* pq);
-
- //获取队列有效元素个数
- int QueueSize(Queue* pq);
-
- //判断队列是否为空
- bool QueueEmpty(Queue* pq);
-
- //销毁队列
- void QueueDestroy(Queue* pq);
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
由于我们用链表来实现队列,为了更好的完成队列操作,我们定义了一个结构体来表示队列的队头和队尾。
- //队列结构
- typedef struct Queue {
- QNode* phead;//头节点
- QNode* ptail;//尾节点
- int sz;
- }Queue;
- void QueueInit(Queue* pq) {
- assert(pq);
- pq->phead = NULL;
- pq->ptail = NULL;
- pq->sz = 0;
- }
我们把队列的头和尾都置为空,队长置为零。
- void QueuePush(Queue* pq, QDataType x) {
- assert(pq);
-
- //创建新节点
- QNode* newNode = (QNode*)malloc(sizeof(QNode));
- if (newNode == NULL)
- {
- perror("malloc fail");
- }
- newNode->data = x;
- newNode->next = NULL;
-
- //从队尾插入
- if (pq->phead == NULL)
- {
- pq->phead = pq->ptail = newNode;
- }
- else
- {
- pq->ptail->next= newNode;
- pq->ptail = newNode;
- }
-
- //长度加一
- pq->sz++;
-
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
我们先创建要插入的新的节点,然后从队列的队尾插入(即链表的尾插),最后队列长度加一。
- void QueuePop(Queue* pq) {
- assert(pq);
- assert(pq->phead != NULL);//队列不为空
-
-
- if (pq->phead == pq->ptail)
- {
- free(pq->ptail);
- pq->phead = pq->ptail = NULL;
- }
- else
- {
- QNode* next = pq->phead->next;;
- free(pq->phead);
- pq->phead = next;
- }
- pq->sz--;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
出队列从队头开始出去,但是我们这里需要分成两种情况讨论,第一种就是队列只有一个元素,我们要把头尾同时置为空,不然有野指针出现。第二种就是链表的头删操作。
- QDataType QueueBack(Queue* pq) {
- assert(pq);
- assert(pq->phead != NULL);
-
- return pq->ptail->data;
- }
我们先判断队列是否为空,然后直接返回尾部节点元素即可。
- QDataType QueueFront(Queue* pq) {
- assert(pq);
- assert(pq->phead != NULL);
-
- return pq->phead->data;
-
-
- }
我们先判断队列是否为空,然后直接返回头部节点元素即可。
- int QueueSize(Queue* pq) {
-
- assert(pq);
-
- return pq->sz;
- }
- bool QueueEmpty(Queue* pq) {
-
- assert(pq);
-
- return pq->phead == NULL;
-
- }
直接返回,如果头节点等于空,即返回true,反之返回false。
- void QueueDestroy(Queue* pq) {
- assert(pq);
-
- QNode* cur = pq->phead;
- while (cur)
- {
- QNode* next =cur->next;
- free(cur);
- cur = next;
- }
- pq->phead = pq->ptail = NULL;
- pq->sz = 0;
- }
和链表销毁差不多,我们要依次销毁每一个创建的节点。
- #pragma once
- #define _CRT_SECURE_NO_WARNINGS 1
- #include<stdio.h>
- #include<assert.h>
- #include<stdbool.h>
- #include<stdlib.h>
-
- typedef int QDataType;
-
- //队列节点
- typedef struct QueueNode {
- QDataType data;
- struct QueueNode* next;
- }QNode;
-
- //队列结构
- typedef struct Queue {
- QNode* phead;//头节点
- QNode* ptail;//尾节点
- int sz;
- }Queue;
-
- //初始化队列
- void QueueInit(Queue* pq);
-
- //入队列(队尾)
- void QueuePush(Queue* pq,QDataType x);
-
- //出队列(队头)
- void QueuePop(Queue* pq);
-
- //获取队列头部元素
- QDataType QueueFront(Queue* pq);
-
- //获取队列尾部元素
- QDataType QueueBack(Queue* pq);
-
- //获取队列有效元素个数
- int QueueSize(Queue* pq);
-
- //判断队列是否为空
- bool QueueEmpty(Queue* pq);
-
- //销毁队列
- void QueueDestroy(Queue* pq);
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Queue.c
- #include"Queue.h"
-
- //初始化队列
- void QueueInit(Queue* pq) {
- assert(pq);
- pq->phead = NULL;
- pq->ptail = NULL;
- pq->sz = 0;
- }
-
- //入队列(队尾)
- void QueuePush(Queue* pq, QDataType x) {
- assert(pq);
-
- //创建新节点
- QNode* newNode = (QNode*)malloc(sizeof(QNode));
- if (newNode == NULL)
- {
- perror("malloc fail");
- }
- newNode->data = x;
- newNode->next = NULL;
-
- if (pq->phead == NULL)
- {
- pq->phead = pq->ptail = newNode;
- }
- else
- {
- pq->ptail->next= newNode;
- pq->ptail = newNode;
- }
-
- //长度加一
- pq->sz++;
-
- }
-
- //出队列(队头)
- void QueuePop(Queue* pq) {
- assert(pq);
- assert(pq->phead != NULL);
-
-
- if (pq->phead == pq->ptail)
- {
- free(pq->ptail);
- pq->phead = pq->ptail = NULL;
- }
- else
- {
- QNode* next = pq->phead->next;;
- free(pq->phead);
- pq->phead = next;
- }
- pq->sz--;
- }
-
- //获取队列头部元素
- QDataType QueueFront(Queue* pq) {
- assert(pq);
- assert(pq->phead != NULL);
-
- return pq->phead->data;
-
-
- }
-
- //获取队列尾部元素
- QDataType QueueBack(Queue* pq) {
- assert(pq);
- assert(pq->phead != NULL);
-
- return pq->ptail->data;
- }
-
- //获取队列有效元素个数
- int QueueSize(Queue* pq) {
-
- assert(pq);
-
- return pq->sz;
- }
-
- //判断队列是否为空
- bool QueueEmpty(Queue* pq) {
-
- assert(pq);
-
- return pq->phead == NULL;
-
- }
-
- //销毁队列
- void QueueDestroy(Queue* pq) {
- assert(pq);
-
- QNode* cur = pq->phead;
- while (cur)
- {
- QNode* next =cur->next;
- free(cur);
- cur = next;
- }
- pq->phead = pq->ptail = NULL;
- pq->sz = 0;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
test.c
- #include"Queue.h"
-
- int main() {
- Queue pq;
- QueueInit(&pq);
- QueuePush(&pq, 1);
- QueuePush(&pq, 2);
- QueuePush(&pq, 3);
-
- int data = QueueFront(&pq);
- printf("%d ", data);
- QueuePop(&pq);
-
- QueuePush(&pq, 4);
- QueuePush(&pq, 5);
-
- while (!QueueEmpty(&pq)) {
- int data = QueueFront(&pq);
- printf("%d ", data);
- QueuePop(&pq);
- }
-
-
-
- QueueDestroy(&pq);
-
-
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
以上我们讲了队列一种特殊的线性表,讲了队列的概念和具体实现,希望对你有所帮助。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。