(详解)数据结构-----------栈与队列 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;
}

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


 

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

        

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM 判定对象是否死亡的两种方式

引用计数法&#xff1a;&#xff08;脑门刻字法&#xff09;和 可达性分析 引用计数算法 引用计数器的算法是这样的&#xff1a;在对象中添加一个引用计数器&#xff0c;每当有一个地方引用它时&#xff0c;计数器值就加一&#xff1b;当引用失效时&#xff0c;计数器值就减一…

python之socket编程

本章内容 1、socket 2、IO多路复用 3、socketserver Socket socket起源于Unix&#xff0c;而Unix/Linux基本哲学之一就是“一切皆文件”&#xff0c;对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现&#xff0c;socket即是一种特殊的文件&#xff0…

服务器数据恢复- RAID5出现故障后恢复数据和操作系统的案例

服务器数据恢复环境&#xff1a; 某品牌服务器中有4块SAS硬盘组建了一组RAID5阵列&#xff0c;另外1块磁盘作为热备盘使用。上层操作系统为redhat linux&#xff0c;部署了一个数据库是oracle的OA。 服务器故障&初检&#xff1a; RAID5中一块磁盘离线后热备盘未自动激活re…

1. 安装Zookeeper

​ 1.下载 点击下载Zookeeper 单机版安装 安装Zookeeper前需要先安装jdk上传安装包rz解压安装包:tar -zxvf apache-zookeeper-3.6.0-bin.tar.gz -C /opt/app/zookeeper zookeeper目录结构:a. bin: 放置运行脚本和工具脚本b. conf: zookeeper 默认读取配置的目录,里面会有…

CSS中你不得不知道的盒子模型

目录 1、CSS的盒子模型1.1 css盒子模型有哪些&#xff1a;1.2 css盒子模型的区别1.3 通过css如何转换css盒子模型 1、CSS的盒子模型 1.1 css盒子模型有哪些&#xff1a; 标准盒子模型、怪异盒子模型&#xff08;IE盒子模型&#xff09; 1.2 css盒子模型的区别 标准盒子模型&a…

【人工智能】—_神经网络、M-P_神经元模型、激活函数、神经网络结构、学习网络参数、代价定义、总代价

M-P_神经元模型、激活函数、神经网络结构、学习网络参数、代价定义 文章目录 M-P_神经元模型、激活函数、神经网络结构、学习网络参数、代价定义 M-P 神经元模型激活函数(Activation function)神经网络结构举例训练神经网络学习网络参数代价定义均方误差交叉熵&#xff08;Cros…

C++ deque底层原理

deque底层原理 一、目的二、底层实现三、原理图四、类结构五、push_back六、pop_back 一、目的 实现双端数组 二、底层实现 双向开口的连续线性空间 三、原理图 四、类结构 class deque : protected Deque base _Deque_base._Deque_impl M_map 指针数组 _M_map_size …

avalonia、WPF使用ScottPlot动态显示ECG心电图

文章目录 avalonia、WPF使用ScottPlot动态显示ECG心电图实现效果&#xff0c;动态效果懒得录视频了安装代码部分UpdateData方法就是用来更新心电图表的方法&#xff0c; 根据消息队列数据去更新是视图中的ScottPlot 图表 avalonia、WPF使用ScottPlot动态显示ECG心电图 avalonia…

共筑开源新长城 龙蜥社区走进开放原子校源行-清华大学站

6 月 28 日&#xff0c;以“聚缘于校&#xff0c;开源共行”为主题的 2023 年开放原子校源行活动在清华大学成功举行。本次活动由开放原子开源基金会和清华大学共同主办&#xff0c;来自各行业的 22 位大咖共聚校园共话开源。龙蜥社区技术专家边子政受邀进行技术分享&#xff0…

stable diffusion实践操作-SD原理

系列文章目录 本文专门开一节写SD原理相关的内容&#xff0c;在看之前&#xff0c;可以同步关注&#xff1a; stable diffusion实践操作 文章目录 系列文章目录前言一、原理说明1.1、出图原理1.1.1 AI画画不是和人一样&#xff0c;从0开始&#xff0c;而是一个去噪点的过程&am…

IP初学习

1.IP报文 首部长度指的是报头长度&#xff0c;用于分离报头和有效载荷 2.网段划分 IP地址 目标网络 目标主机 3.例子 4.特殊的IP地址 5.真正的网络环境 6.调制解调器 “猫”&#xff0c;学名叫宽带无线猫 7.NAT 源IP在内网环境不断被替换 8.私有IP不能出现在公网上 因…

【LeetCode75】第四十三题 钥匙和房间

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 给我们一个数组&#xff0c;表示对应的房间里拥有能开启的对应索引号的钥匙。 一开始我们只能进入0号房间&#xff0c;也就是数组里索引…

【计算机组成 课程笔记】3.2 算数运算和逻辑运算的硬件实现

课程链接&#xff1a; 计算机组成_北京大学_中国大学MOOC(慕课) 3 - 2 - 302-门电路的基本原理&#xff08;11-39--&#xff09;_哔哩哔哩_bilibili 现代计算机的CPU和其他很多功能部件都是基于晶体管的集成电路&#xff0c;想要了解计算机组成的基本原理&#xff0c;还是需要有…

系统架构技能之设计模式-工厂模式

一、开篇 本文主要是讲述设计模式中最经典的创建型模式-工厂模式&#xff0c;本文将会从以下几点对工厂模式进行阐述。 本文将会从上面的四个方面进行详细的讲解和说明&#xff0c;当然会的朋友可以之处我的不足之处&#xff0c;不会的朋友也请我们能够相互学习讨论。 二、摘…

SpringCloudAlibaba常用组件

SpringCloudAlibaba常用组件 微服务概念 1.1 单体、分布式、集群 单体 ⼀个系统业务量很⼩的时候所有的代码都放在⼀个项⽬中就好了&#xff0c;然后这个项⽬部署在⼀台服务器上就 好了。整个项⽬所有的服务都由这台服务器提供。这就是单机结构。 单体应⽤开发简单,部署测试…

el-date-picker自定义只能选中当前月份和半年内月份等

需求&#xff1a;el-date-picker只能选中当前月期和当前月期往前半年&#xff0c;其他时间就禁用了不让选择了&#xff0c;因为没数据哈哈。当然也可以选择往前一年等。 一、效果 二、写个日期选择器 :picker-options&#xff1a;日期选项 value-format&#xff1a;选择后的格…

运算放大器总结

早期的运算放大器目的是制造模拟计算机&#xff0c;用来计算各种数学公式。虽然现在已经被数字电路替代了&#xff0c;但是运算放大器在模拟电路设计中&#xff0c;仍然是最重要的知识。 1、运放是怎么工作的&#xff1f; 以电压反馈型运放&#xff08;VFA&#xff09;为例。由…

一套成熟在用的Spring Cloud工程项目数字化管理云平台源码

技术架构&#xff1a; 微服务JavaSpring Cloud VueUniApp MySql 开发语言&#xff1a;Java 开发工具&#xff1a;Idea 前端框架&#xff1a;Vue 后端框架&#xff1a;Spring Cloud 数 据 库&#xff1a;MySql 移 动 端&#xff1a;UniApp 系统端口&#xff1a;PC端&…

【2D/3D RRT* 算法】使用快速探索随机树进行最佳路径规划(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

渗透测试漏洞原理之---【失效的访问控制】

文章目录 1、失效的访问控制1.1、OWASP Top 101.1.1、A5:2017-Broken Access Control1.1.2、A01:2021 – Broken Access Control 1.2、失效的访问控制类别1.2.1、水平越权1.2.2、垂直越权 1.3、攻防案例1.3.1、Pikachu靶场 Over Permision1.3.2、DVWA越权利用失效的访问控制漏洞…