您的位置:首页 > 教育 > 培训 > 下载软件的网站推荐_微站设计_推广普通话文字内容_知乎营销平台

下载软件的网站推荐_微站设计_推广普通话文字内容_知乎营销平台

2025/5/1 3:18:49 来源:https://blog.csdn.net/2401_86940607/article/details/147027553  浏览:    关键词:下载软件的网站推荐_微站设计_推广普通话文字内容_知乎营销平台
下载软件的网站推荐_微站设计_推广普通话文字内容_知乎营销平台

前言

本文介绍队列的基本知识,包括概念、初始化、销毁、入队、出队、求队首队尾值以及计算有效元素个数

队列

    • 前言
    • 正文
      • 1概念与结构
    • 2.常见操作基本实现
      • Queue.h
      • Queue.c
        • 初始化与销毁
        • 入队
        • 判断队列是否为空
        • 出队
        • 取队头或队尾数据
        • 队列中的有效元素
      • test.c
    • 结语

正文

1概念与结构

概念:只允许在一端进行插入的数据操作,在另一端进行删除数据操作的特殊线性表
队列具有先入先出
入队列:进行插入的一段称为队尾
出队列:进行删除操作的一段称为队头
队列
那么队列的底层结构如何选选择?数组or链表

数组
入队,可以直接找到,时间复杂度为O(1)
出队,需要遍历,时间复杂度为O(N)
链表
出队,对头出队,O(1)
入队,需要找到尾指针,O(N)

这样看来似乎哪个都行没有区别,但是,对于链表而言,如果我们直接定义一个队尾的指针,时间复杂度岂不是O(1).
代码如下:

//队列结点的结构
typedef struct QueueNode
{QDataType data;struct QueueNode* next;
}QueueNode;
//队列的结构
typedef struct Queue
{QueueNode* phead;QueueNode* ptail;
}Queue;

2.常见操作基本实现

本文依旧是多文件形式

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;
}QueueNode;
//队列的结构
typedef struct Queue
{QueueNode* phead;QueueNode* ptail;//int size; //队列中有效数据个数
}Queue;//初始化
void QueueInit(Queue* pq);
//销毁队列
void QueueDestroy(Queue* pq);//入队——队尾
void QueuePush(Queue* pq, QDataType x);//出队——队头
void QueuePop(Queue* pq);//队列判空
bool QueueEmpty(Queue* pq);//队列有效元素个数
int QueueSize(Queue* pq);//取队头数据
QDataType QueueFront(Queue* pq);//取队尾数据
QDataType QueueBack(Queue* pq);

Queue.c

初始化与销毁

初始化:令phead和ptail为NULL
销毁:定义pcur指针,保存pcur->next,然后逐个销毁pcur。

//初始化
void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;//pz->size = 0;
}//销毁队列
void QueueDestroy(Queue* pq)
{assert(pq);QueueNode* pcur = pq->phead;while (pcur){QueueNode* next = pcur->next;free(pcur);pcur = next;}pq->phead = pq->ptail = NULL;//pq->size = 0;
}
入队

在这里插入图片描述
定义一个新结点,插入队尾入队

//入队——队尾
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->phead == NULL){pq->phead = pq->ptail = newnode;}//队列非空else {pq->ptail->next = newnode;pq->ptail = pq->ptail->next;}//pq->size++
}
判断队列是否为空
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;
}
出队

只有一个结点phead和ptail置为空,
有多个结点,因为对头出队,所有先要保存头结点的下一个指针phead->next,释放头指针phead,让phead->next成为新的头指针

//出队——对头
void QueuePop(Queue* pq)
{assert(!QueueEmpty(pq));//只有一个结点,phead和ptail都置为空if (pq->phead == pq->ptail){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QueueNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}//pq->size--;
}
取队头或队尾数据

注意:这里是拿出来用并不是销毁,该数据还在队列中
直接返回对应位置的data值即可

//取队头数据
QDataType QueueFront(Queue* pq)
{assert(!QueueEmpty(pq));return pq->phead->data;
}//取队尾数据
QDataType QueueBack(Queue* pq)
{assert(!QueueEmpty(pq));return pq->ptail->data;
}
队列中的有效元素

见代码

//队列有效元素个数
int QueueSize(Queue* pq)
{assert(pq);//方法一:遍历列表——适用于不频繁调用队列有效数据个数的场景(空间复杂度较高O(N))QueueNode* pcur = pq->phead;int size = 0;while (pcur){size++;pcur = pcur->next;}return size;//方法二:遍历链表——适用于频繁调用队列有效数据个数的场景//return pq->size;
}

test.c

用于测试

#include"Queue.h"void test()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePop(&q);int front = QueueFront(&q);int rear = QueueBack(&q);printf("front:%d\n", front);printf("rear:%d\n", rear);printf("size:%d", QueueSize(&q));QueueDestroy(&q);
}int main()
{test();return 0;
}

结语

这篇介绍链表的基本实现,但如需要进一步来学习栈与队列,请关注下一篇栈与队列OJ,希望三连支持一下谢谢。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com