栈与队列的实现逻辑以及底层代码

1.前言

栈和队列不是一种语言独有的结构,而是一个由代码语言设计的一种数据结构。是由人设计出的一种具有特定意义的结构。

2.栈

什么是栈,栈以结构体为节点按要求链接的一种后进先出的一种数据结构(last in first out)简称LIFO结构。栈可以由数组实现也可以由链表实现。只不过数组实现出的栈效果更好,这里以数组为实现。

每一个进去栈的数据都包含三个数据,数组指针,空间大小以及栈顶元素的下标为了将三个封装在一起所以我们要用到结构体。分别是int* a(数组,通过下标来储存数据) int top (栈顶元素的下一个的下标(为什么是下一个元素的小标呢因为我们初始化时将top赋值0即 top=0,但是此时栈中是没有数据的,所以是下一个小标。不过也可以赋值为-1,那么此时就是栈顶元素的下标了)) 

栈的节点

typedef int DataType;typedef struct Stack
{DataType* a;//顺序表int top;栈顶元素的下一个下标int capacity;空间大小
}ST;

栈的底层代码函数有7个

​void STinit(ST* ps);//栈的初始化
void STDstory(ST* ps);//栈的销毁
void STpush(ST* ps,DataType x);//入栈操作
void STpop(ST* ps);//出栈操作
DataType STtop(ST* ps);//获得栈顶的元素
bool STEmpty(ST* ps);//判断栈是否为空
int STSize(ST* ps);//判断栈中的有效元素个数​

为什么要有这7个底层函数呢,目前而言这七个函数满足了栈的各种需求,如果你认为还有更好的函数来满足栈的需求也可以自己增加。不过这7个函数应该是已经足够了。

2.1下列分别介绍7个函数

2.1.1 栈的初始化(void STinit(ST* ps)

第一个函数很简单将结构体中的数据全部初始化为“0”就行了

void STinit(ST* ps)//栈的初始化
{ps->a=NULL;ps->top=ps->capacity=0;
}

2.1.2 栈的销毁 (void STDstory(ST* ps)

栈的销毁也比较简单,我们类比顺序表的销毁

void STDestory(ST* ps)//栈的销毁
{free(ps->a);ps->a=NULL;ps->top=ps->capacity=0;
}

2.1.3 入栈操作(void STpush(ST*ps,DataType x)

     将数据压入栈中类比与顺序表,先判断结构体是否为空,防止出现空指针访问,接着考虑空间是否充足,要不要扩容,最后再进行压栈操作。

void STpush(ST*ps,DataType x)
{assert(ps);if(ps->capacity==ps->top)//说明空间已经到达极限了,需要扩容操作{ps->capacity==0?2:(2*(pa->capacity));DataType* newa=(DataType*)relloc(ps->a,(ps->capacity)*sizeof(DataType))if(newa==NULL){perror("relloc fail!");return -1;}}ps->a[ps->top]=x;ps->top--;
}

2.1.4 出栈操作(STpop(ST* ps)) 

这实现的是,出的操作,将栈顶的元素pop出。

void STpop(ST* ps)
{assert(ps);//断言防止出现空指针的访问操作ps->a[top--]=0;
}

2.1.5 获取栈顶的元素(DataType STtop(ST* ps)

获得栈顶元素

​
DataType STtop(ST* ps)
{return ps->a[--(ps->top)];
}​

2.1.6 判断栈是否为空(bool STEmpty(ST* ps)

bool STEmpty(ST* ps)
{return (--ps->top)==0;
}

2.1.7 判断栈中的有效元素个数(int STSize(ST* ps))           

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

3.队列

队列+是以链表为基础的数据结构实现的是先进先出。但这里需要带头节点和尾结点,为什么呢?假如我们不带尾节点在我们进行入栈操作时需要遍历一遍链表到达尾节点时间复杂度是O(N),而用带尾结点我们就可以直接进行尾删操作了这样一来时间复杂度可以做到O(1)了。但是我们传参的时候传两个有点不太方便,所以我们就想到了用结构体将他们封装起来。

所以队列有两个结构体,一个表示一个节点包括的内容包括了,DataType val ,struct QueueNode* next。另一个则是包括首尾指针的结构体

代码如下

​
typedef int DataType;
typedef struct QueueNode//队列的每一个结构体节点
{int val;struct QueueNode* next;
}QNode;typedef struct Queue//头尾指针
{QNode* tail;QNode* head;int size;//队列大小
}Queue;​

队列的底层代码有8个如下

//入队列队尾
void Queuepush(Queue* pq, QDataType x);//链表可能为空
//出队列队头
void Queuepop(Queue* pq);//队列的初始化
void QueueInit(Queue* pq,QNode* ps);//队列的销毁
void QueueDestory(Queue* pq);//返回队头的数据
QDataType QueueFront(Queue* pq);//返回队尾的数据
QDataType QueueBack(Queue* pq);//判断队列是否为空
bool QueueEmpty(Queue* pq);//返回队列中的有效元素个数
int QueueSize(Queue* pq);

3.1.1 入队列(void Queuepush(Queue*pq,QDataType x)

这里我们入队列用尾插,出队列我们用头插。

void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->val = x;newnode->next = NULL;if (pq->ptail){pq->ptail->next = newnode;pq->ptail = newnode;}else{pq->phead = pq->ptail = newnode;}pq->size++;
}

3.1.2 出队列(void QueuePop(Queue* pq)

void QueuePop(Queue* pq)
{assert(pq);// 0个节点// 温柔检查//if (pq->phead == NULL)//	return;// 暴力检查 assert(pq->phead != NULL);// 一个节点// 多个节点if (pq->phead->next == NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}

3.1.3 队列的初始化(void QueueInit(Queue* pq)

void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}

3.1.4 队列的销毁(void QueueDestroy(Queue* pq)

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->size = 0;
}

3.1.5 返回对头数据(QDataType QueueFront(Queue* pq)

QDataType QueueFront(Queue* pq)
{assert(pq);// 暴力检查 assert(pq->phead != NULL);return pq->phead->val;
}

3.1.6 返回队尾数据(QDataType QueueBack(Queue* pq)

QDataType QueueBack(Queue* pq)
{assert(pq);// 暴力检查 assert(pq->ptail != NULL);return pq->ptail->val;
}

3.1.7 判断队列是否为空(bool QueueEmpty(Queue* pq)

bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}

3.1.8 返回队列中有效元素个数(int QueueSize(Queue* pq)

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

希望这篇博客对你有帮助

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

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

相关文章

Docker部署一个SpringBoot项目(超级详细)

注意:下面的教程主要是针对 Centos7 的,如果使用的其他发行版会有细微的差别,请查看官方文档。 Docker部署一个SpringBoot项目(超级详细) 一、安装Docker1.卸载旧版2.配置Docker的yum库3.安装Docker4.设置开机自启动5.…

通过一篇文章让你了解如何学习C++

如何学习C 前言一、如何学习C二、别人是怎么学C的21天学会C编程能力与编程年龄 三、自己怎么学总结 前言 学习C需要掌握其基础语法、指针和内存管理、STL库使用、面向对象编程等核心概念。可通过阅读权威书籍、在线教程和参考官方文档来系统学习。实践是关键,通过…

网络编程基本概念(一篇文章掌握基本内容的详细概念,IP,端口号,协议,协议分层,封装和分用,客户端和服务端,请求和回应,两台主机的通信)

IP地址 概念 IP地址主要⽤于标识⽹络主机、其他⽹络设备(如路由器)的⽹络地址。简单说,IP地址⽤于定位主机的⽹络地址。 就像我们发送快递⼀样,需要知道对⽅的收货地址,快递员才能将包裹送到⽬的地。 IP的格式 IP地址…

自动化面试常见算法题!

1、实现一个数字的反转,比如输入12345,输出54321 num 12345 num_str str(num) reversed_num_str num_str[::-1] reversed_num int(reversed_num_str) print(reversed_num) # 输出 54321代码解析:首先将输入的数字转换为字符串&#xff…

HarmonyOS SDK 闭源开放能力 —Scan Kit

1.问题描述 Scan Kit扫描专用底层码流接口需要鉴权,鉴权失败后功能还能用吗? 解决方案 如果已经申请过白名单,因为异常导致的鉴权失败会优先放通,保障业务成功。 2.问题描述 调用Scan Kit扫描专用底层码流接口会不会将二维码…

systemd-journal(三)之systemd.journal-fields

文章目录 写在前面概述用户日志字段(User Journal Fields)MESSAGEMESSAGE_IDPRIORITYCODE_FILE, CODE_LINE, CODE_FUNCERRNOINVOCATION_ID, USER_INVOCATION_IDSYSLOG_FACILITY, SYSLOG_IDENTIFIER, SYSLOG_PID, SYSLOG_TIMESTAMPDOCUMENTATIONTIDUNIT, …

C++11新特性之并发

std::thread c11引入了std::thread来创建线程&#xff0c;支持对线程join或者detach。直接看代码&#xff1a; #include <iostream> #include <thread>void threadFunction() {std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "I…

渗透测试——分享几个我常用渗透网站

前言 经常有小伙伴问我常用的渗透网站有哪些&#xff0c;花点时间整理出来&#xff0c;废话不多说&#xff0c;直接上网站。 一、雨苁 雨苁 这个网站从我接触网络安全一直在用&#xff0c;里面有几个很有用的工具如&#xff1a;在线地图情报搜集&#xff0c;开源情报信息收集…

【2G 50元/年 4G 618/3年!】支持比价必赔 送抽奖机会 京东云服务器推荐 附阿里云 腾讯云价格对比表

《最新对比表》已更新在文章头部—腾讯云文档&#xff0c;文章具有时效性&#xff0c;请以腾讯文档为准&#xff01; 【腾讯文档实时更新】云服务器1分钟教会你如何选择教程 https://docs.qq.com/document/DV0RCS0lGeHdMTFFV?tab000003 ​ 当前活动&#xff1a;采购季&#…

浮点数 向偶数舍入

二进制中间值是2/21 10.1110101011011保留四位偶数舍入 10.1110 101011011 保留部分 舍弃部分 舍弃部分101011011>中间值1 所以要保留部分进位 最终结果为 10.1111 10.1110 1 保留部分 舍弃部分 舍弃部分1中间值1 此时看保留部分最后一位,如果是奇数就保留…

供应链数字化转型:电子元器件商城的策略与实践

电子元器件商城通过供应链数字化转型&#xff0c;可以提高运营效率、降低成本、加速交付&#xff0c;并增强竞争力。以下是一些策略和实践建议&#xff1a; 数字化采购管理&#xff1a; 利用供应链管理软件或平台&#xff0c;实现采购过程的数字化管理。这包括供应商信息管理、…

软考 - 软件系统架构设计师 - 统一过程 RUP

概念 统一过程&#xff08;Rational Unified Process&#xff0c;简称RUP&#xff09;是一个面向对象且基于网络的程序开发方法&#xff0c;它是由IBM Rational软件公司&#xff08;原Rational Software Corporation&#xff09;发明并倡导的一种软件过程框架&#xff0c;属于迭…

揭秘抖音百科词条创建全攻略!

在当今社交媒体的盛行时代&#xff0c;抖音作为一款备受青睐的短视频平台&#xff0c;一直以来都备受人们的喜爱和追捧。而在抖音上的各种短视频内容之中&#xff0c;往往会涉及各种明星名人、品牌产品以及各种时事热点。为了更好地让用户获取相关信息&#xff0c;抖音百科词条…

闲鱼教程大全(价值2000)

实战干货视频教程 免费发送内容: "闲鱼", 获取提取码

有道翻译接口逆向

前言 本文主要介绍了有道翻译的接口调用情况&#xff0c;对两个接口进行了初步的接口逆向&#xff0c;只供学习交流使用。 找到翻译接口 webtranslate 网页地址&#xff1a;https://fanyi.youdao.com/index.html#/ 首先找到翻译接口 可以看出&#xff0c;翻译接口是 webt…

【数据结构】归并排序(不用递归)

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解归并排序&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 归并排序&#xff08;用递归&#xff09; 之前我们写了一篇博客来介绍如何用递归实现归并排序…

工业无线网关在汽车制造企业的应用效果和价值-天拓四方

随着智能制造的快速发展&#xff0c;工业无线网关作为关键通信设备&#xff0c;在提升生产效率、优化生产流程、实现设备间的互联互通等方面发挥着越来越重要的作用。以下是一个关于工业无线网关在智能制造行业应用的具体案例&#xff0c;展示了其在实际生产中的应用效果和价值…

某易盾解析滑块 【2024/03/27】

文章目录 文章目录 文章目录前言网址请求图片 actoken获取图片 cb轨迹验证gdxidpyhxde 也就是fp前言 可以关注我哟,一起学习,主页有更多练习例子 如果哪个练习我没有写清楚,可以留言我会补充 如果有加密的网站可以留言发给我,一起学习共享学习路程 如侵权,联系我删除 此文…

fastadmin学习01-windows下安装部署

下载源代码 官网 安装 解压&#xff0c;然后使用phpstorm打开 修改配置文件 创建数据库 -- drop database fastadmin01; create database fastadmin01;这样fastadmin就部署好了 访问主页也能看到前台页面

进行接口测试时,连接数据库,对数据源进行备份、还原、验证操作

进行接口测试时&#xff0c;我们需要连接到数据库中&#xff0c;对数据源进行备份、还原、验证等操作。 一、Python连接数据库常见模块 MysqlDBpython2时代最火的驱动库。基于C开发&#xff0c;对windows平台不友好。现在已经进入python3时代&#xff0c;基本不再使用MysqlCl…