数据结构与算法学习笔记三---队列的表示和实现(C语言)

目录

前言

1.定义         

2.队列的表示和实现

1.链队列

1.定义

2.初始化

3.入队

4.出队

5.队列为空

6.队列长度

7.清空队列

8.获取队首元素

9.完整代码

2.顺序队列

1.定义

2.初始化

3.入队

4.出队

5.队列为空

6.队列长度

7.清空队列

8.获取队首元素

9.完整代码


前言

        这篇博客主要讲队列的用法。

1.定义         

        队列是一种常见的数据结构,它按照先进先出(FIFO,First In First Out)的原则管理元素。队列可以被看作是一个有限长度的线性表,它有两个主要的操作:入队和出队。

1. 入队(enqueue):将新元素添加到队列的末尾。
2. 出队(dequeue):从队列的头部移除并返回元素。

        队列的特点是只能在队列的一端进行插入(入队),在另一端进行删除(出队)。这种操作方式保证了队列中的元素按照其添加的顺序被处理。除了入队和出队操作,队列通常还包括以下常用操作:

1.队列是否为空(isEmpty):判断队列中是否有元素。
2.队列的长度(size):返回队列中元素的数量。
3.获取队首元素(front):返回队列中的第一个元素,但不从队列中移除它。

         队列的应用十分广泛,例如:

1.在计算机科学中,队列常用于实现广度优先搜索算法(BFS)、任务调度等。
2.在操作系统中,队列可用于实现进程调度、缓存管理等。
3. 在网络通信中,队列用于数据包的传输与接收。
4.在生活中,队列的概念也常见于排队等待购票、排队买东西等场景。

2.队列的表示和实现

        队列可以分别使用顺存和链式两种存储方式实现。

1.链队列

        使用链式存储结构表示队列。

1.定义

        和单链表的定义相同,我们需要定义队列的指针域和值域。

// 节点类型定义
typedef struct QNode{
    int data;//元素
    struct QNode * next;//指向下一个节点的指针
}QNode,*QueuePtr;

typedef struct {
    QueuePtr front; // 队首指针
    QueuePtr rear;  // 队尾指针
}LinkQueue;

2.初始化

        初始化队列的时候,首先给队列分配存储空间,然后设置队首指针和队尾指针

// 初始化队列
int initQueue(LinkQueue *queue) {
    queue->front = queue->rear = (QueuePtr)malloc(sizeof(QNode));
    if (!queue->front) {
        return 0;
    }
    queue->front->next = NULL;
    return 1;
}

3.入队

        入队的时候,首先生成一个新节点,节点的值域指向我们传递的数据元素,然后把新节点插入到队尾。

// 入队
int EnQueue(LinkQueue *queue, int element) {
    QueuePtr newNode = (QueuePtr)malloc(sizeof(QNode)); // 新节点
    if (!newNode) { // 存储分配失败
        return 0;
    }
    newNode->data = element;
    newNode->next = NULL;
    queue->rear->next = newNode; // 新节点插入到队列尾部
    queue->rear = newNode;       // 更新队尾指针
    return 1;
}

4.出队

        出队列的时候,修改队首指针。这里要注意的是如果队列中只有一个数据元素的时候,要更新下尾节点指针。

// 出队
int DeQueue(LinkQueue *queue, int *element) {
    if (queue->front == queue->rear) {
        return 0; // 队列为空,出队失败
    }
    QueuePtr temp = queue->front->next; // 暂存队首节点
    *element = temp->data;              // 获取要出队的元素值
    queue->front->next = temp->next;    // 更新队首指针
    if (queue->rear == temp) {
        queue->rear = queue->front;     // 如果出队后队列为空,更新队尾指针
    }
    free(temp);                         // 释放出队节点的内存
    return 1; // 出队成功
}

5.队列为空

        队首和队尾相同的时候,队列为空。

// 是否为空队列
int QueueEmpty(LinkQueue *queue) {
    return queue->front == queue->rear;
}

6.队列长度

        遍历队列中的数据元素。

// 队列长度
void QueueLength(LinkQueue *queue) {
    int length = 0;
    QueuePtr p = queue->front->next;
    while (p) {
        length++;
        p = p->next;
    }
    printf("队列长度:%d\n", length);
}

7.清空队列

        遍历队列中的数据元素,释放数据元素的存储空间。

// 清空队列
void clearQueue(LinkQueue *queue) {
    QueuePtr p = queue->front->next;
    while (p) {
        QueuePtr temp = p;
        p = p->next;
        free(temp);
    }
    queue->front->next = NULL;
    queue->rear = queue->front;
}

8.获取队首元素

// 获取队首元素
void getQueueHead(LinkQueue *queue) {
    if (QueueEmpty(queue)) {
        printf("队列为空,无法获取队首元素!\n");
    } else {
        printf("队首元素:%d\n", queue->front->next->data);
    }
}

9.完整代码

        

#include <stdlib.h>

// 节点类型定义
typedef struct QNode{
    int data;//元素
    struct QNode * next;//指向下一个节点的指针
}QNode,*QueuePtr;

typedef struct {
    QueuePtr front; // 队首指针
    QueuePtr rear;  // 队尾指针
}LinkQueue;
// 初始化队列
int initQueue(LinkQueue *queue) {
    queue->front = queue->rear = (QueuePtr)malloc(sizeof(QNode));
    if (!queue->front) {
        return 0;
    }
    queue->front->next = NULL;
    return 1;
}

// 入队
int EnQueue(LinkQueue *queue, int element) {
    QueuePtr newNode = (QueuePtr)malloc(sizeof(QNode)); // 新节点
    if (!newNode) { // 存储分配失败
        return 0;
    }
    newNode->data = element;
    newNode->next = NULL;
    queue->rear->next = newNode; // 新节点插入到队列尾部
    queue->rear = newNode;       // 更新队尾指针
    return 1;
}

// 出队
int DeQueue(LinkQueue *queue, int *element) {
    if (queue->front == queue->rear) {
        return 0; // 队列为空,出队失败
    }
    QueuePtr temp = queue->front->next; // 暂存队首节点
    *element = temp->data;              // 获取要出队的元素值
    queue->front->next = temp->next;    // 更新队首指针
    if (queue->rear == temp) {
        queue->rear = queue->front;     // 如果出队后队列为空,更新队尾指针
    }
    free(temp);                         // 释放出队节点的内存
    return 1; // 出队成功
}

// 打印队列中的数据元素
void printQueue(LinkQueue *queue) {
    if (queue->front == queue->rear) {
        printf("队列为空\n");
        return;
    }
    QueuePtr p = queue->front->next;
    printf("队列元素:");
    while (p) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

// 是否为空队列
int QueueEmpty(LinkQueue *queue) {
    return queue->front == queue->rear;
}

// 队列长度
void QueueLength(LinkQueue *queue) {
    int length = 0;
    QueuePtr p = queue->front->next;
    while (p) {
        length++;
        p = p->next;
    }
    printf("队列长度:%d\n", length);
}

// 清空队列
void clearQueue(LinkQueue *queue) {
    QueuePtr p = queue->front->next;
    while (p) {
        QueuePtr temp = p;
        p = p->next;
        free(temp);
    }
    queue->front->next = NULL;
    queue->rear = queue->front;
}


// 获取队首元素
void getQueueHead(LinkQueue *queue) {
    if (QueueEmpty(queue)) {
        printf("队列为空,无法获取队首元素!\n");
    } else {
        printf("队首元素:%d\n", queue->front->next->data);
    }
}


void test_queue(void) {
    LinkQueue queue;
    // 初始化队列
    printf("初始化队列...\n");
    if (initQueue(&queue)) {
        printf("队列初始化成功!\n");
    } else {
        printf("队列初始化失败!\n");
    }
    
    // 入队元素 10
    printf("入队元素 10...\n");
    if (EnQueue(&queue, 10)) {
        printf("入队成功!\n");
    } else {
        printf("入队失败!\n");
    }

    
    // 入队元素 20
    printf("入队元素 20...\n");
    if (EnQueue(&queue, 20)) {
        printf("入队成功!\n");
    } else {
        printf("入队失败!\n");
    }
    
    // 入队元素 30
    printf("入队元素 30...\n");
    if (EnQueue(&queue, 30)) {
        printf("入队成功!\n");
    } else {
        printf("入队失败!\n");
    }
    
    // 打印队列
    printf("当前队列:\n");
    printQueue(&queue);
    
    // 出队
    int element;
    printf("出队元素...\n");
    if (DeQueue(&queue, &element)) {
        printf("出队元素:%d\n", element);
    } else {
        printf("队列为空,出队失败!\n");
    }
    
    // 打印队列
    printf("当前队列:\n");
    printQueue(&queue);
    
    // 获取队首元素
    printf("获取队首元素...\n");
    getQueueHead(&queue);
    
    // 清空队列
    printf("清空队列...\n");
    clearQueue(&queue);
    
    // 打印队列
    printf("当前队列:\n");
    printQueue(&queue);
}

2.顺序队列

1.定义

        队列的顺序类型定义中,base表示队列的基地址,front表示队首指针,rear表示队尾指针。

#define MAXQSIZE 100 //最大队列长度
typedef struct{
    int * base;//队列基址
    int front; //队首指针,若队列不为空 指向队列头元素
    int rear;  //队尾指针 若队尾不为空 指向队尾指针元素的下一个位置
}SeqQueue;

2.初始化

        初始化队列的时候,首先分配存储空间,然后队首和队尾的数据元素都为0;

// 初始化队列
int initSeqQueue(SeqQueue *seqQueue){
    seqQueue->base = (int *)malloc(sizeof(int) * MAXQSIZE);
    if (!seqQueue->base) {
        return 0;
    }
    seqQueue->front = seqQueue->rear = 0;
    return 1;
}

3.入队

        判断是否对满,对满的时候无法入队,入队之后rear++。

// 入队
int EnSeqQueue(SeqQueue *queue,int element){
    if (queue->rear >= MAXQSIZE ) {
        return 0;
    }
    queue->base[queue->rear++] = element;
    return 1;
}

4.出队

        出队的时候判断队列是否为空,不为空的话,front++。

// 出队
int DeSeqQueue(SeqQueue *queue, int *element){
    if (queue->front == queue->rear) {
        return 0; // 队列为空,出队失败
    }
    *element = queue->base[queue->front]; // 获取队首元素
    queue->front++; // 更新队首指针
    return 1; // 出队成功
}

5.队列为空

        队首和队尾相同的时候,队列为空。

// 是否为空队列
int seqQeueEmpty(SeqQueue *seqQueue){
    return seqQueue->front == seqQueue->rear;
}

6.队列长度

        遍历队列中的数据元素。

// 队列长度
int seqQueueLength(SeqQueue * seqQueue){
    return seqQueue->rear - seqQueue->front;
}

7.清空队列

        遍历队列中的数据元素,释放数据元素的存储空间。

// 清空队列
void clearQueue(LinkQueue *queue) {
    QueuePtr p = queue->front->next;
    while (p) {
        QueuePtr temp = p;
        p = p->next;
        free(temp);
    }
    queue->front->next = NULL;
    queue->rear = queue->front;
}

8.获取队首元素

        首先判断队列是否为空,空队列无法获取队首元素。

// 队列首元素
int getSeqQueueHead(SeqQueue * seqQueue,int * element){
    if (!seqQeueEmpty(seqQueue)) {
        * element = seqQueue->base[seqQueue->front];
        return 1;
    }
    return 0;
}

9.完整代码

        

#include <stdlib.h>
#include <stdio.h>

#define MAXQSIZE 5 //最大队列长度
typedef struct{
    int * base;//队列基址
    int front; //队首指针,若队列不为空 指向队列头元素
    int rear;  //队尾指针 若队尾不为空 指向队尾指针元素的下一个位置
}SeqQueue;


// 打印队列中的数据元素
void printSeqQueue(SeqQueue *queue){
    for (int i = 0; i<queue->rear; i++) {
        printf("%d\t",queue->base[i]);
    }
    printf("\n");
}

// 初始化队列
int initSeqQueue(SeqQueue *seqQueue){
    seqQueue->base = (int *)malloc(sizeof(int) * MAXQSIZE);
    if (!seqQueue->base) {
        return 0;
    }
    seqQueue->front = seqQueue->rear = 0;
    return 1;
}
// 出队
int DeSeqQueue(SeqQueue *queue, int *element){
    if (queue->front == queue->rear) {
        return 0; // 队列为空,出队失败
    }
    *element = queue->base[queue->front]; // 获取队首元素
    queue->front++; // 更新队首指针
    return 1; // 出队成功
}
// 入队
int EnSeqQueue(SeqQueue *queue,int element){
    if (queue->rear >= MAXQSIZE ) {
        return 0;
    }
    queue->base[queue->rear++] = element;
    return 1;
}

// 是否为空队列
int seqQeueEmpty(SeqQueue *seqQueue){
    return seqQueue->front == seqQueue->rear;
}

// 队列长度
int seqQueueLength(SeqQueue * seqQueue){
    return seqQueue->rear - seqQueue->front;
}

// 清空队列
void clearSeqQueue(SeqQueue * seqQueue){
    seqQueue->front = seqQueue->rear = 0;
}
// 销毁队列
void destroySeqQueue(SeqQueue * seqQueue){
    if (seqQueue->base) {
        free(seqQueue->base);
        seqQueue->base = NULL;
    }
    seqQueue->front = seqQueue->rear = 0;
}
// 队列首元素
int getSeqQueueHead(SeqQueue * seqQueue,int * element){
    if (!seqQeueEmpty(seqQueue)) {
        * element = seqQueue->base[seqQueue->front];
        return 1;
    }
    return 0;
}
//创建测试队列
SeqQueue createTestSeqQueue(SeqQueue seqQueue){
    int success = 0;
    for (int i = 1; i<= 5; i++) {
        if (EnSeqQueue(&seqQueue, 10 * i)) {//入队成功
            success = 1;
        }else{
            break;
        }
    }
    return seqQueue;
}

void testSeqQueue(void){
    SeqQueue seqQueue;
    printf("队列初始化.......\n");
    if(initSeqQueue(&seqQueue)){
        printf("队列初始化成功\t✅\n");
    }else{
        printf("队列初始化失败\n");
    }
    //测试入队
    for (int i = 1; i<= 5; i++) {
        //入队
        if (EnSeqQueue(&seqQueue, 10 * i)) {
            printf("第%d次入队 数据入队数据元素:%d 成功! 入队之后front = %d\t rear=%d\t\t✅\n",i,10 * i,seqQueue.front,seqQueue.rear);
        }else{
            printf("入队失败!");
        }
    }
    printf("\n********************\t队列长度和队列是否为空测试\t********************\n");
    printf("\n********************\t队列中的数据元素\t********************\n");
    printSeqQueue(&seqQueue);
    if (!seqQeueEmpty(&seqQueue)) {
        printf("\n队列不为空\t队列长度为:%d\t✅\n",seqQueueLength(&seqQueue));
    }
    int queueHeadElement;
    if (getSeqQueueHead(&seqQueue, &queueHeadElement)) {
        printf("队列首元素:%d\n",queueHeadElement);
    }
    
    printf("\n********************\t队列清空测试\t********************\n");
    clearSeqQueue(&seqQueue);
    if (seqQeueEmpty(&seqQueue)) {
        printf("队列为空,清空测试通过\t✅\n");
    }
    
    printf("\n********************\t队列销毁测试\t********************\n");
    seqQueue = createTestSeqQueue(seqQueue);
    printf("销毁之前队列:\n");
    destroySeqQueue(&seqQueue);
    if (seqQueueLength(&seqQueue)==0) {
        printf("队列为空,队列销毁成功\t✅\n");
    }
    printSeqQueue(&seqQueue);
}

int main(int argc, const char *argv[]) {
    testSeqQueue();
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/586562.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PDF高效编辑器,支持修改PDF文档并转换格式从PDF文件转换成图片文件,轻松管理你的文档世界!

PDF文件已成为我们工作、学习和生活中不可或缺的一部分。然而&#xff0c;传统的PDF阅读器往往只能满足简单的查看需求&#xff0c;对于需要频繁编辑、修改或转换格式的用户来说&#xff0c;就显得力不从心。现在&#xff0c;我们为您带来一款全新的PDF高效编辑器&#xff0c;让…

对话访谈——五问RAG与搜索引擎:探索知识检索的未来

记一次关于RAG和搜索引擎在知识检索方面的对话访谈&#xff0c;针对 RAG 与传统搜索引擎的异同,以及它们在知识检索领域的优劣势进行了深入的探讨。 Q&#xff1a;传统搜索引擎吗&#xff0c;通过召回-排序的两阶段模式&#xff0c;实现搜索逻辑的实现&#xff0c;当前RAG技术也…

Spark Structured Streaming 分流或双写多表 / 多数据源(Multi Sinks / Writes)

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

使用 scikit-learn 进行机器学习的基本原理-2

介绍 scikit-learn 估计器对象 每个算法都通过“Estimator”对象在 scikit-learn 中公开。 例如&#xff0c;线性回归是&#xff1a;sklearn.linear_model.LinearRegression 估计器参数&#xff1a;估计器的所有参数都可以在实例化时设置&#xff1a; 拟合数据 让我们用 nump…

第7篇:创建Nios II工程之控制LED<二>

Q&#xff1a;上一期我们完成了Quartus硬件工程部分&#xff0c;本期我们创建Nios II软件工程这部分。 A&#xff1a;创建完BSP和Nios II Application之后&#xff0c;在source文件main.c中添加LED控制代码&#xff1a;system.h头文件包含了Platform Designer系统中IP的硬件信…

VUE3----Tabs swiper 滑动切换

Tabs swiper 滑动切换 <template><view class"cc-tab-container"><scroll-view class"tab-head" :class"tabClassName" scroll-x"true" scroll-with-animation :scroll-left"state.scrollLeft"><view…

变电站综合自动化系统:Modbus-PLC-645转IEC104网关方案

前言 电力行业作为关系国计民生的重要基础产业&#xff0c;是关系千家万户的公用事业。但是要做好电力行业安全保障工作的前提&#xff0c;是需要对应的技术人员详细了解电力工业使用的系统、设备以及各类协议的安全特性&#xff0c;本文将主要介绍IEC 104协议的定义和钡铼技术…

STL——stackqueue

stack stack即为栈&#xff0c;先进后出是其特点 栈只有栈顶元素能被外界使用&#xff0c;故不存在遍历行为 栈中常用接口 构造函数 stack<T> stk; //默认构造方式 stack(const stack &stk); //拷贝构造 赋值操作 stack& operator(const stack &stk); …

对汉诺塔递归算法的简单理解

一.历史背景:汉诺塔&#xff08;Tower of Hanoi&#xff09;&#xff0c;又称河内塔&#xff0c;是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子&#xff0c;在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始…

网络安全是智能汽车下一个要卷的方向?

2024年一季度&#xff0c;中国汽车市场延续了2023年的风格&#xff0c;核心就是「卷」。 2023年&#xff0c;我国汽车市场爆发「最强价格战」&#xff0c;燃油车的市场空间不断被挤压&#xff0c;如今只剩下最后一口气。近日乘联会发布4月1-14日最新数据&#xff0c;新能源&am…

基于昇腾AI | 英码科技EA500I使用AscendCL实现垃圾分类和视频物体分类应用

现如今&#xff0c;人工智能迅猛发展&#xff0c;AI赋能产业发展的速度正在加快&#xff0c;“AI”的需求蜂拥而来&#xff0c;但AI应用快速落地的过程中仍存在很大的挑战&#xff1a;向下需要适配的硬件&#xff0c;向上需要完善的技术支持&#xff0c;两者缺一不可。 基于此&…

如何利用仪表构造InfiniBand流量在数据中心测试中的应用

一、什么是Infiniband&#xff1f; 在当今数据爆炸的时代&#xff0c;数据中心作为信息处理的中心枢纽&#xff0c;面临着前所未有的挑战。传统的通信方式已经难以满足日益增长的数据传输需求&#xff0c;而InfiniBand技术的出现&#xff0c;为数据中心带来了全新的通信解决方…

使用xshell工具连接ubuntu的root账户被拒绝的解决方法

问题描述&#xff1a; 我在使用xshell工具远程连接Ubuntu虚拟机的过程中&#xff0c;如果连接的是的普通用户则xshell工具可以正常连接&#xff0c;但是当我向连接ubuntu系统的root用户&#xff0c;即便是密码输入正确但还是不能连接成功。不能连接成功的截图如下&#xff1a; …

requests库进行接口请求

请求的常规写法 requests.post() 、requests.get() 从中可以看出&#xff1a; 必填参数&#xff1a; url可缺省参数&#xff1a; data&#xff0c;json等、关键字参数 **kwargs 如下进行了一个post请求的登录&#xff0c;且请求体在body中 知识点1 当为post请求时&#xff1…

建堆时间复杂度

片头 嗨&#xff01;小伙伴们&#xff0c;大家好&#xff01; 在上一篇中&#xff0c;我们学习了什么是堆&#xff0c;以及如何实现堆。这一篇中&#xff0c;我将继续带领大家来深入学习堆&#xff0c;准备好了吗&#xff1f;我要开始咯&#xff01; 首先&#xff0c;大家还记…

opencv_17_翻转与旋转

一、图像翻转 1&#xff09;void flip_test(Mat& image); 2&#xff09;void ColorInvert::flip_test(Mat& image) { Mat dst; //flip(image, dst, 0); //上下翻转 flip(image, dst, 1); //左右翻转 // flip(image, dst, -1); //180度翻转 imsho…

VScode 无法连接云服务器

试了很多方法&#xff0c;比如更换VScode版本&#xff0c;卸载重装&#xff0c;删除配置文件 重启电脑&#xff0c;都无法成功。最后重置电脑后才连接上&#xff0c;但是重启服务器后又出现该问题。 方法一&#xff1a;修改环境 方法二&#xff1a;把vscode卸载干净重下

【快速入门】数据库的增删改查与结构讲解

文章的操作都是基于小皮php study的MySQL5.7.26进行演示 what 数据库是能长期存储在计算机内&#xff0c;有组织的&#xff0c;可共享的大量数据的集合。数据库中的数据按照一定的数据模型存储&#xff0c;具有较小的冗余性&#xff0c;较高的独立性和易扩展性&#xff0c;并为…

LabVIEW智能变电站监控系统设计与实现

LabVIEW智能变电站监控系统设计与实现 随着电力系统和智能化技术的快速发展&#xff0c;建立一个高效、可靠的变电站监控系统显得尤为重要。通过分析变电站监控系统的需求&#xff0c;设计了一个基于LabVIEW软件的监控平台。该平台利用虚拟仪器技术、传感器技术和无线传输技术…

数据结构中的栈(C语言版)

一.栈的概念 栈是一种常见的数据结构&#xff0c;它遵循后进先出的原则。栈可以看作是一种容器&#xff0c;其中的元素按照一种特定的顺序进行插入和删除操作。 压栈&#xff1a;栈的插入操作叫做进栈/压栈/入栈&#xff0c;入数据在栈顶。 出栈&#xff1a;栈的删除操作叫做…
最新文章