当前位置: 首页 > news >正文

(详解)数据结构-----------栈与队列 c语言实现

本章将会详细讲解以下知识点:

目录

一:栈

        1:栈的定义,栈的特点

        2:用什么结构来实现栈与原因的分析?

        3:  (超详解)栈的常用接口并且附上测试用例

二:队列

        1:队列的定义,队列的特点

        2:用什么结构来实现队列与原因的分析?

        3:(超详解)队列的接口并且附上测试用例


正文开始~:-^-

        1:栈的定义及其特点

        首先栈是一种特殊线性表,其只能在一端进行插入删除的操作,进行数据删除插入的一端我们称它为栈顶,另外一端为栈底。栈中的数据元素遵循后进先出的原则。

        下面是栈的操作的叫法:

                压栈:表示数据元素插入到栈中,又称为进栈/入栈。入数据在栈顶

                出栈:表示栈中数据元素的删除的操作。出数据在栈顶

                栈的特点只能在栈一端进行数据元素的插入与删除,数据元素遵循后进先出的原则。

        2:用什么结构来实现栈与原因?

        经过前面我们对比顺序表与链表的优缺点,在实现栈的时候我们首选使用顺序表来进行实现栈这种数据结构。当然也可以使用链表来实现。

        原因:我们根据栈具有先进后出的特点,它只能在栈顶进行数据元素的插入与删除。

        而我们的顺序表就非常适合它,顺序表的尾插与尾删的时间复杂度都是O(1),且顺序表的缓存利用率比链表快,所以顺序表的结构更加优于链表。

         3:(详解)栈的常用接口

        栈的常用操作有:栈的初始化,栈的销毁,栈的入栈,栈的出栈,获取栈顶元素的值

        栈是否为空的判读,栈的大小

        在讲解这些接口之前,我们先来讲解栈的定义

        包含三个成员变量,S是我们开辟空间的首地址,top是用来记录元素有多少个,同时是数组中元素最后一个元素的下一个位置,capacity是用来表示数组空间容量的大小。

        代码如下:

//动态的顺序栈
typedef int STDataType;typedef struct Stack
{STDataType* S;int top;//用来表示栈中最后一个元素的下一个元素的位置int capacity;
}ST;

        1:栈的初始化:将三个成员变量的值全部弄为空或者是0

        代码如下:

void InitStack(ST* ps)
{assert(ps);ps->capacity = 0;ps->top = 0;ps->S = NULL;
}

        2:栈的入栈操作:每次入栈之前我们先要判断空间是否足够,然后在直接使用顺序表随机访问的特点对栈进行尾插,每次入栈完成我们都需要将top++。

        在下面代码中有一个非常精髓的地方,由于我们初始化的时候并没有给数组开辟空间之类的,所以我们巧用了三目运算符来对我们新开辟的空间的大小进行分配,如果是第一次我们就将空间的大小搞成4,之后的过程就是一次扩2倍的空间。

         代码如下:

        

void PushStack(ST* ps, STDataType x)
{assert(ps);//先检查空间够不够if (ps->top == ps->capacity){int newcapcity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);STDataType* tmp = (STDataType*)realloc(ps->S, sizeof(STDataType) * newcapcity);if (tmp == NULL){perror("realloc fail");exit(-1);}ps->S = tmp;ps->capacity = newcapcity;}ps->S[ps->top] = x;++ps->top;
}

         3:栈的出栈操作:这里我们需要用暴力的解法先判断栈是否为空,如果为空就给我们报错,不为空才能进行出栈的操作,然后我们的就top--。

        代码如下:

void PopStack(ST* ps)
{assert(ps);//非空assert(ps->top > 0);ps->top--;}

        4:栈的获取栈顶元素的操作:首先还是得判断栈是否为空,为空就这个接口就会报错。

        在这个代码中我们要注意的是我们栈顶元素得下标并不是top而是top-1

        代码如下:

        

STDataType GetStack(ST*ps)
{assert(ps);//非空assert(ps->top > 0);return ps->S[ps->top-1];
}

        5:栈的大小:我们直接返回top就行。

        代码如下:

        

int SizeStack(ST* ps)
{assert(ps);return ps->top;
}

        6:判断栈是否为空:这里如果top为0,则说明栈中无元素返回true,如果有元素返回true,这里要注意c语言中并没有这两个关键字,我们需要引入头文件<stdbool.h>

        代码如下:

        

bool EmptyStack(ST* ps)
{assert(ps);//这里代码的意思是如果top为0,则返回真,不为0返回falsereturn ps->top == 0;}

        为了体现栈的特点所以我们在打印出栈中数据的时候,并不是直接遍历数组的

        我们使用的是--->

        

while (!EmptyStack(&st)){printf("%d ", GetStack(&st));PopStack(&st);}

        这里是每次取栈顶的元素,然后在删除栈顶的元素。这样才能体现出栈的特点。

        

        图解:

         

        栈的详解就到这里结束了。



    1:队列的定义与特点

        队列的定义:队列也是一种特殊的线性表,它只能在一端进行插入操作,在另外一端进行删除的操作,我们将插入一端称为队尾,将删除的一端我们称之为队头,这种结构在我们生活中非常常见,我们可以想象一下我们在食堂排队的情况,如果有人来了那么它就会往队尾进行插入,打完饭的人则会从队头出队。

        出队:将队头的元素进行删除的操作

        入队:在队尾插入数据的操作。

        队列特点:只能在队头进行删除的操作,在队尾进行插入的操作,遵循先进先出原则

        图:

        

         2:用啥结构来实现队列与原因?

        先公布答案:相对与顺序表来说我们一般使用链表来实现队列这一数据结构。

        原因:链表在进行头删的时候更加方便,在进行尾插的时候我们只需要定义一个尾指针就可以节省时间了。

        3:(详解)队列的常用接口

        队列的接口包括:初始化队列,销毁队列,入队操作,出队操作,判断队列是否为空

获取队头元素,获取队尾元素,判断队列的大小。 

       首先我们先来了解队列的结构代码分析:

typedef int QueueDataType;typedef struct QNode
{struct QNode* next;QueueDataType data;
}QNode;typedef struct Queue
{QNode* head;QNode* tail;int size;//用来记录有多少个结点,可以直接算大小
}Que;

     首先队列的每个元素都是一个链表的基本结构,我们只需要记录链表的头节点与尾结点我们就可以将队列给表示出来,而又因为我们一般传参的时候只传地址所以我们就将头指针与尾指针定义到一个结构体当中,并且增加一个成员变量size,用来记录队列元素的个数。

            将两个指针放到同一个结构体中,有一个好处就是我们只需要通过结构体指针就可以改变我们的指针的值,不然就需要使用二级指针来修改它们的值。

 

        1:队列的初始化:如果你和我的初始化不同那么可能会导致后面一些接口中步骤有些差异。初始化并不唯一

        代码如下:

            

void QueueInit(Que* pq)
{assert(pq);pq->head = pq->tail = 0;pq->size = 0;
}

        2:入队操作:这里需要分为两种情况,第一张是插入第一个元素的时候我们需要将两个指针的指向给改变,另外一种情况我们只需要在尾指针的后面插入一个新的结点即可,与此同时我们将尾指针指向新结点,插入之后我们的size++;

        代码如下:

        

void QueuePush(Que* pq, QueueDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail:");exit(-1);}//为第一个结点的时候if (pq->head == NULL){pq->head = pq->tail = newnode;}//不是第一个结点else{pq->tail->next = newnode;}pq->tail = newnode;newnode->data = x;newnode->next = NULL;pq->size++;
}

        3:出队操作:首先得判断队列中是否含有数据元素,且有两类,一类是队列中只有一个元素,那么我们需要将这个元素删除,并且将head与tail的值置为空,在size--;

        代码如下:

void QueuePop(Que* pq)
{assert(pq);assert(!QueueEmpty(pq));//只有一个结点的时候if (pq->head->next == NULL){free(pq->head);pq->head = pq->tail = NULL;}else{QNode* phead = pq->head->next;free(pq->head);pq->head = phead;}pq->size--;

       4:获取队头元素:这个非常简单,先判断队列是否为空,不为空我们只需要返回head->data,就行。

        代码如下:

QueueDataType QueueFront(Que* pq)
{assert(pq);//判断pq是否有意义assert(!QueueEmpty(pq));return pq->head->data;
}

        5:获取队尾元素:与上面的思路类似,只需要返回tail指针所指向的数据元素就行

        

QueueDataType QueueBack(Que* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->tail->data;
}

        6:判断队列是否为空:为空那么head指针就为空,head为NULL则返回true,否则返回false

        代码如下:

               

bool QueueEmpty(Que* pq)
{assert(pq);return pq->head==NULL;
}

        7:队列的元素个数判断:我们根据我们所定义的结构可在,我们只需要返回size即可。

        

int QueueSize(Que* pq)
{assert(pq);return pq->size;
}

        在某种情况下可以使用栈转化为队列,也可以使用队列转化为栈,让我们一起想一想它是如何转化的吧。


 

 !!!本章完,感谢大家的耐心观看!

        

相关文章:

(详解)数据结构-----------栈与队列 c语言实现

本章将会详细讲解以下知识点&#xff1a; 目录 一&#xff1a;栈 1&#xff1a;栈的定义&#xff0c;栈的特点 2&#xff1a;用什么结构来实现栈与原因的分析? 3: (超详解)栈的常用接口并且附上测试用例 二:队列 1:队列的定义&#xff0c;队列的特点 2&#xff1a;用什么结…...

前端文件、图片直传OOS、分片上传、el-upload上传(vue+elementUI)

前言&#xff1a;基于天翼云的面相对象存储(Object-Oriented Storage&#xff0c;OOS),实现小文件的直接上传&#xff0c;大文件的分片上传。 开发文档地址&#xff1a;网址 上传之前的相关操作&#xff1a;注册账户&#xff0c;创建 AccessKeyId 和 AccessSecretKey之后&…...

java自动登录 selenium 自动登录并获取cookie

选择操作网页 我用的edge&#xff0c;谷歌我的版本太高没有对应的驱动… 下载Edge的驱动程序&#xff0c;直接解压就好里面只有一个.exe文件 https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ 复制即用&#xff0c;看注释 import com.alibaba.fastjs…...

vue中 computed()方法详解

在Vue中&#xff0c;computed是一种计算属性&#xff0c;它用于定义一个属性&#xff0c;该属性的值是根据其他属性的值计算而来的。computed属性的值会被缓存&#xff0c;只有当依赖的属性发生变化时&#xff0c;才会重新计算。 computed属性可以在Vue实例的computed选项中定…...

在服务器上搭建Jenkins

目录 1.服务器要求 2.官方文档 3.在服务器上下载Jenkins 3.1 下载war包 3.2 将war包上传到服务器的一个目录下 3.3 启动jenkins 3.3.1 jdk版本升级 1&#xff09;下载jdk17 2&#xff09;解压到当前文件夹 3&#xff09;配置路径 4.jenkins配置 4.1 填写初始密码&a…...

全面解析MES系统中的报工操作

一、报工操作的定义&#xff1a; 报工操作是指在生产过程中&#xff0c;操作员通过MES系统记录和提交生产工序的相关信息&#xff0c;如工时、产量、质量等。报工操作将生产过程中的实际情况反馈给MES系统&#xff0c;实现生产数据的实时采集和记录。 二、报工操作的流程&…...

Harbor 私有仓库迁移

文章目录 一.私有仓库迁移的介绍1.为何要对Harbor 私有仓库的迁移2.Harbor 私有仓库的迁移特点3. Harbor 私有仓库的迁移注意要点 二.私有仓库迁移配置1.源Harbor配置&#xff08;192.168.198.11&#xff09;&#xff08;1&#xff09;接着以下操作查看容器状况及是否可以登录 …...

制造业物联网革命:智慧工厂数据采集与远程监控管理

智慧工厂是指运用现代信息技术和物联网技术&#xff0c;实现制造业生产过程的智能数字化。智慧工厂的工业设备不仅能够自动化运行&#xff0c;还可以通过网络技术帮助企业实现数据采集、远程监控与管理。4G工业网关便成为了智慧工厂通讯的重要组成部分&#xff0c;起到了连接工…...

软考A计划-网络工程师-复习背熟-网络管理和计算机基础知识

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…...

springBoot打印精美logo

文章目录 &#x1f412;个人主页&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;文本logo &#x1f412;个人主页 &#x1f3c5;JavaEE系列专栏 &#x1f4d6;前言&#xff1a; 本篇博客主要以提供springBoot打印精美logo &#x1f380;文本logo ??…...

kali开启SSH服务(简单无比)

我会一直陪着你 1.切换到管理员用户&#xff1a;2.启动SSH服务3.要在Kali Linux上启用SSH服务并修改配置文件&#xff0c;你可以按照以下步骤进行操作&#xff1a;4.查看SSH服务状态是否正常运行&#xff0c;命令为&#xff1a;注意&#xff1a;配置文件有些地方不同&#xff0…...

Ubuntu20.04如何更换国内源-阿里云源

1.备份源文件 cp /etc/apt/sources.list /etc/apt/sources.list.bak 2.打开源文件&#xff0c;注释默认的源 vim /etc/apt/sources.list ## 注释原本内容 # deb http://mirrors.ivolces.com/ubuntu/ focal main restricted universe multiverse # deb-src http://mirrors.ivolc…...

goland设置

1、go file设置 file->setting->Editor->File and Code Templates->Go File package ${GO_PACKAGE_NAME} /** * description: * author:${USER} * date:${YEAR}/${MONTH}/${DAY} ${HOUR}:${MINUTE} * Versio…...

2023年Java核心技术第十篇(篇篇万字精讲)

目录 十九 . 一个线程两次调用start&#xff08;&#xff09;方法会出现什么情况&#xff1f;线程的生命周期和状态转移。 19.1 典型回答 19.1.1 线程生命周期&#xff1a; 19.1.2 计时等待详细解释&#xff1a; 19.2 深入扩展考察 19.2.1 线程是什么&#xff1f; 19.2.2 Green…...

分享一篇关于如何使用BootstrapVue的入门指南

你想轻松地创建令人惊叹且响应式的在线应用程序吗&#xff1f;使用BootstrapVue&#xff0c;您可以快速创建美观且用户友好的界面。这个开源工具包是基于Vue.js和Bootstrap构建的&#xff0c;非常适合开发现代Web应用程序。本文将介绍其基础知识&#xff0c;让您可以开始使用这…...

【1day】复现Cellular Router命令执行漏洞

目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现 一、漏洞描述 移动路由器(Cellular Router)是一种利用移动网络提供无线互联网连接的设备。它们类似于传统路由器,但不同于使用有线连接(如以太网或DSL)...

【Torch API】pytorch 中repeat_interleave函数详解

torch.repeat_interleave(input, repeats, dimNone) → Tensor Repeat elements of a tensor. Parameters input (Tensor) – the input tensor. repeats (Tensor or int) – The number of repetitions for each element. repeats is broadcasted to fit the shape of the …...

TDesign表单rules通过函数 实现复杂逻辑验证输入内容

Element ui 中 我们可以通过validator 绑定函数来验证一些不在表单model中的值 又或者处理一下比较复杂的判断逻辑 TDesign也有validator 但比较直观的说 没有Element那么好用 这里 我们给validator绑定了我们自己的checkAge函数 这个函数中 只有一个参数 value 而且 如果你的…...

springgateway网关修改响应后,部分中文乱码问题

原因 是因为响应体过大&#xff0c;开启了压缩&#xff0c;数据分段进行响应得&#xff0c;导致处理返回体得时候乱码 解决方式 Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request exchange.getR…...

微信开发之一键发布群公告的技术实现

简要描述&#xff1a; 设置群公告 请求URL&#xff1a; http://域名地址/setChatRoomAnnouncement 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必…...

R语言和Python用泊松过程扩展:霍克斯过程Hawkes Processes分析比特币交易数据订单到达自激过程时间序列...

全文下载链接&#xff1a;http://tecdat.cn/?p25880 本文描述了一个模型&#xff0c;该模型解释了交易的聚集到达&#xff0c;并展示了如何将其应用于比特币交易数据。这是很有趣的&#xff0c;原因很多。例如&#xff0c;对于交易来说&#xff0c;能够预测在短期内是否有更多…...

自动化运维:Ansible脚本之playbook剧本

目录 一、理论 1.playbooks 2.YAML 3.使用ansible批量安装apache服务 4.定义、引用变量 5.指定远程主机sudo切换用户 6.when条件判断 7.迭代 8.Templates 模块 9.tags 模块 10.Roles 模块 二、实验 1.使用ansible批量安装apache服务 2.定义、引用变量…...

基于角色访问控制-RBAC(Role-Based Access Control)

1.RBAC简介 RBAC&#xff08;Role-Based Access Control&#xff09;是一种基于角色的访问控制模型&#xff0c;它是一种安全策略&#xff0c;用于限制系统中用户对资源的访问权限。RBAC模型的核心概念是用户角色和资源访问权限。 在角色访问控制中&#xff0c;首先需要定义系…...

springboot项目实现断点续传

java代码 package com.ruoyi.web.upload.controller; import com.ruoyi.web.upload.dto.FileChunkDTO; import com.ruoyi.web.upload.dto.FileChunkResultDTO; import com.ruoyi.web.upload.result.Result; import com.ruoyi.web.upload.service.IUploadService; import org.s…...

解析经典面试题:for 循环中的 let var

更多文章可以看看我的博客&#xff1a;https://icheng.github.io/ 题目 for循环中&#xff0c;使用 var 或 let 声明 i 变量&#xff0c;会得到不同的结果 var arr []; for (var i 0; i < 2; i) {arr[i] function () {console.log(i);} } arr[0](); arr[1]();输出&…...

CSS按钮-跑马灯边框

思路很简单&#xff0c;实现方法有很多很多。但是大体思路与实现方法都类似&#xff1a;渐变色 动画&#xff0c;主要区别在动画的具体实现 0、HTML 结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><titl…...

【PCIE系统学习】Gen1/2Gen3/4 symobl与OrderSet概念对比

这个专栏要干的事:学习PCIE理论知识,学会PCIE IP/VIP的使用。可以达到上手做项目,而不是空有理论 适合谁看:正在学习PCIE 设计验证,但学的过于零散。想有对比的系统的学习。 低价收费的目的:抵制胡乱传播转载现象。 版本控制:便于增加内容以及勘误 版本说明v20230829 …...

C++ Qt 中QMimeDatabase类详细介绍以及应用场景

C Qt 中QMimeDatabase类详细介绍以及应用场景 文章目录 C Qt 中QMimeDatabase类详细介绍以及应用场景一、QMimeDatabase类是什么&#xff1f;二、QMimeDatabase类中的关键功能和特点三、QMimeDatabase的用法四、QMimeDatabase的应用场景 一、QMimeDatabase类是什么&#xff1f;…...

深度学习7:生成对抗网络 – Generative Adversarial Networks | GAN

生成对抗网络 – GAN 是最近2年很热门的一种无监督算法&#xff0c;他能生成出非常逼真的照片&#xff0c;图像甚至视频。我们手机里的照片处理软件中就会使用到它。 目录 生成对抗网络 GAN 的基本原理 大白话版本 非大白话版本 第一阶段&#xff1a;固定「判别器D」&#x…...

R语言空气污染数据的地理空间可视化和分析:颗粒物2.5(PM2.5)和空气质量指数(AQI)...

原文链接&#xff1a;http://tecdat.cn/?p23800 由于空气污染对公众健康的不利影响&#xff0c;人们一直非常关注。世界各国的环境部门都通过各种方法&#xff08;例如地面观测网络&#xff09;来监测和评估空气污染问题&#xff08;点击文末“阅读原文”获取完整代码数据&…...