数据结构 栈与队列详解!!

一.栈

 关于内存中的栈和数据结构中的栈是不同的,本章着重讲的是数据结构的栈。

 这是一张关于栈的表达图。从图中可以看出栈很像是一副卡牌,发牌时只能从上取出,即出栈。

而入栈则是像你出牌后,要把你出的牌压在上一张出的牌上面。这是入栈。

栈可以用链表或者顺序表实现,这里采用的是顺序表的结构。

1.栈的头文件 

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int StackDatatype;
typedef struct Stack
{StackDatatype* data;int capacity;int Top;
}ST;
void STPush(ST* pst, StackDatatype x);
void StackInit(ST* pst);
void StackDestroy(ST* pst);
void Push(ST* pst, StackDatatype x);
void Pop(ST* pst);
StackDatatype StackTop(ST* pst);
int StackSize(ST* pst);
bool StackEmpty(ST* pst);

 2.栈的初始化

void StackInit(ST* pst)
{assert(pst);pst->capacity = 0;pst->data = NULL;pst->Top = -1;
}

这里的pst->Top可以用-1,或者0.用-1的话后续你的pst->Top 所代表的下标就是栈顶元素。

如果用0 那pst-Top 之后的下标就是栈顶元素的下一个位置。这里可以自己考虑,代码的多样性。 (本章采用的是-1 的写法)

3.栈的插入

void Push(ST* pst, StackDatatype x)
{assert(pst);pst->Top++;JudgeCapacity(pst);pst->data[pst->Top] = x;
}

栈的插入就是入栈,top++ 是pst->top 指向当前即将插入元素的位置(栈顶的位置)。

后面在判断pst中的容量,不够需要扩容。把x 插入栈顶位置。 

4.栈的取出

void Pop(ST* pst)
{assert(pst);assert(pst->Top > -1);pst->Top--;
}

和顺序表一样只要 top--即可,不用删除,因为top -- 以后,你下次在使用该位置的时候,其实就是把原来这个位置的元素更改就可以了,不需要删除。

5.栈的栈顶元素

StackDatatype StackTop(ST* pst)
{assert(pst);return pst->data[pst->Top];
}

 这个函数的存在意义就是取当前的栈顶元素的值。

6.栈的元素个数

int StackSize(ST* pst)
{assert(pst);return pst->Top+1;
}

因为我们的Top 用的是-1开头,所以,当它指向第一个元素的时候,这时候Top == 0, 所以加一。

7.栈的判空

bool StackEmpty(ST* pst)
{assert(pst);return pst->Top == -1;
}

判断栈此时是否为空,用pst- top == -1 的判断表达式返回即可。 

8.栈的销毁

void StackDestroy(ST* pst)
{assert(pst);free(pst->data);pst->data = NULL;pst->capacity = 0;pst->Top = -1;
}

因为栈是创建出来的一个空间。所以最后要将这段空间free,并将所有数据都置空 

栈的容量判断

void JudgeCapacity(ST* pst)
{assert(pst);if (pst->capacity == pst->Top){int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;StackDatatype* tmp = (StackDatatype*)realloc(pst->data, sizeof(StackDatatype) * newcapacity);if (tmp == NULL){perror("malloc failed!");return;}pst->data = tmp;pst->capacity = newcapacity;}
}

 和顺序表的容量判断一样,有兴趣的可以直接去看我的顺序表详解,这里给大家简单的说一下,用三目表达式判断并赋值newcapacity,然后扩容pst->data这一段空间。

最后把扩容好的空间地址给到tmp,newcapacity给到原来的capacity。

二.队列

 上图是队列的表达图,队列如字意就像是排队一样,先进入的人,就先获得服务。

所以 队列和 栈的不同点就是出栈和出队,队列出的是头元素,而栈出的是尾元素(栈顶)

对比入队和 入栈两者相似都是尾插。

,还有队列用的是链表,栈用的是顺序表。

1.队列的头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int QeDataType;
typedef struct QueueNode
{struct QueueNode* next;QeDataType data;
}Qnode;
typedef struct Queue
{Qnode* head;Qnode* back;
}Qe;
void QueueInit(Qe* q);
void QueueDestroy(Qe* q);
void Queuepush(Qe* q, QeDataType x);
void QueuePop(Qe* q);
QeDataType QueueFront(Qe* q);
QeDataType QueueBack(Qe* q);
int QueueSize(Qe* q);
bool QueueEmpty(Qe* q);

 相比栈 队列多用了一个typedef 原因是,队列要记录头元素和尾元素。因为入队入的在尾部,出队出的是头部

2.队列的初始化

void QueueInit(Qe* q)
{assert(q);Qnode* newnode = CreateNode(-1);q->head = newnode;q->back = newnode;
}

 这里采用的是有头结点的队列,当然没有头结点(哨兵位)也是可以的,根据个人喜好选择。

初始化创立一个头结点(哨兵位)后,头指针和尾指针都指向头结点(哨兵位)

3.队列的插入

void Queuepush(Qe* q, QeDataType x)
{assert(q);Qnode* newnode = CreateNode(x);q->back->next = newnode;q->back = newnode;
}

 关于队列的插入,就是链表的尾插,如果链表还没明白的朋友,可以去看我之前关于单链表的博客。

4.队列的取出

void QueuePop(Qe* q)
{assert(q);assert(q->head->next);Qnode* next = q->head->next;q->head->next = next->next;free(next);next = NULL;if (q->head->next == NULL){q->back = q->head;q->back->next = NULL;}
}

关于队列的取出,实质上就是链表的头删。 

5.队列的头元素

QeDataType QueueFront(Qe* q)
{assert(q);assert(q->head->next);return q->head->next->data;
}

 队列的头元素返回就是返回哨兵位后的第一个节点的数据。因为要返回数值,所以这个第一个节点不能为空,用assert断言。

6.队列的尾元素

QeDataType QueueBack(Qe* q)
{assert(q);assert(q->head->next);return q->back->data;
}

 既然要返回尾元素的数据,那就是用到尾指针,当然链表第一个节点不能为空。

7.队列的元素个数

int QueueSize(Qe* q)
{Qnode* size = q->head->next;int num = 0;while (size){size = size->next;num++;}return num;
}

队列的元素个数,就把链表遍历一遍,用num记录遍历次数,就是元素个数。 

8.队列的判空

bool QueueEmpty(Qe* q)
{return q->head->next == NULL;
}

 队列的判空就是判断第一个节点是否为空,return 一个 表达式即可,也可以用if else 语句。因人而异。

创造一个节点

Qnode* CreateNode(QeDataType x)
{Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));newnode->data = x;newnode->next = NULL;return newnode;
}

 创造一个节点在链表的初始化和插入都会用到,在之前链表的那篇博客有讲到,偏简单。

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

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

相关文章

【算法基础】筛质数

文章目录 问题描述解决方法朴素筛法线性筛法 问题描述 给定一个正整数 n n n&#xff0c;请你求出 1 ∼ n 1∼n 1∼n 中质数的个数。 输入格式 共一行&#xff0c;包含整数 n。 输出格式 共一行&#xff0c;包含一个整数&#xff0c;表示 1∼n 中质数的个数。 数据范围 …

完美解决k8s master节点无法ping node节点中的IP或Service NodePort的IP

1、问题一 使用搭建好了K8S集群&#xff0c;先是node节点加入k8s集群时&#xff0c;用的内网IP&#xff0c;导致master节点无法操作node节点中的pod&#xff08;这里的不能操作&#xff0c;指定是无法查看node节点中pod的日志、启动描述、无法进入pod内部&#xff0c;即 kubec…

【GCN】GCN学习笔记一

谱域图卷积 卷积 卷积定义离散空间的卷积 图卷积简介 卷积定理谱域图卷积实现思路如何定义图上的傅里叶变换拉普拉斯矩阵 &#xff08;Laplacian Matrix&#xff09;拉普拉斯矩阵的性质拉普拉斯矩阵的谱分解拉普拉斯矩阵与拉普拉斯算子 图傅里叶变换 图上的信号表示经典傅里叶变…

Python Web框架的三强之争:Flask、Django和FastAPI

JetBrains 公布 2022 Python 开发者调查结果。 完整报告地址&#xff1a;https://lp.jetbrains.com/zh-cn/python-developers-survey-2022/ 这是由 Python 软件基金会 (PSF) 和 JetBrains 共同开展的第六次官方年度 Python 开发者调查&#xff0c;回复于 2022 年 10 月至 12 …

2013年12月13日 Go生态洞察:Go在App Engine上的工具、测试和并发

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Java高级编程-----网络编程

网络通信协议 通过计算机网络可以实现多台计算机连接&#xff0c;但是不同计算机的操作系统和硬件体系结构不同&#xff0c;为了提供通信支持&#xff0c;位于同一个网络中的计算机在进行连接和通信时必须要遵守一定的规则&#xff0c;这就好比在道路中行驶的汽车一定要遵守交…

mricorn 手动勾画ROI并保存为模版的方法步骤

mricorn软件手动勾画ROI&#xff1a; 这里拿一个做了切除手术的癫痫病人举例子&#xff0c;我们需要把切除区域勾画出来并保存成切除的模版。 1、将图像导入到mricorn中 2、逐层勾画ROI并填充 比较方便的是从切除区域的起始层进行勾画&#xff0c;这里为了方便展示只勾画中间…

计算机网络的OSI七层模型

目录 1、OSI七层模型是什么 1.1 物理层&#xff08;Physical Layer&#xff09; 1.2 数据链路层&#xff08;Data Link Layer&#xff09; 1.3 网络层&#xff08;Network Layer&#xff09; 1.4 传输层&#xff08;Transport Layer&#xff09; 1.5 会话层&#xff08;S…

5款免费BI数据可视化工具,2023年最新精选推荐!

BI可视化工具顾名思义是进行数据分析和可视化的软件&#xff0c;旨在将数据以表格、图表、仪表盘等形式展示出来&#xff0c;让用户能够更加直观了解其业务状况、发现问题&#xff0c;并在必要时进行决策。   市面上BI数据可视化工具很多&#xff0c;目前比较火的像国外的Tabl…

CTF/AWD竞赛标准参考书+实战指南

随着网络安全问题日益凸显&#xff0c;国家对网络安全人才的需求持续增长&#xff0c;其中&#xff0c;网络安全竞赛在国家以及企业的人才培养和选拔中扮演着至关重要的角色。 在数字化时代&#xff0c;企业为了应对日益增长的攻击威胁&#xff0c;一般都在大量部署安全产品、…

uview-plus u-picker的defaultIndexs修改后无效的问题

uniapp项目中使用了uview-plus组件库&#xff0c;在使用u-picker组件时&#xff0c;发现其默认的选中属性 defaultIndex是一次性的&#xff0c;修改后无法响应&#xff0c;解决办法就是在u-picker源码中修改这个属性的watch,源码位置在uni_modules/uview-plus/components/u-pi…

Hive 定义变量 变量赋值 引用变量

Hive 定义变量 变量赋值 引用变量 变量 hive 中变量和属性命名空间 命名空间权限描述hivevar读写用户自定义变量hiveconf读写hive相关配置属性system读写java定义额配置属性env只读shell环境定义的环境变量 语法 Java对这个除env命名空间内容具有可读可写权利&#xff1b; …

SQL零基础入门教程,贼拉详细!贼拉简单! 速通数据库期末考!(十一)

COUNT() 计数函数 COUNT() 函数返回匹配指定条件的行数。 语法&#xff1a; 1.返回指定列的字段值条数 SELECT COUNT(column_name) FROM table_name;2.返回整表数据行条数 SELECT COUNT(*) FROM table_name;3.返回指定列去重后的字段值条数 SELECT COUNT(DISTINCT column_…

Leetcode 第 372 场周赛题解

Leetcode 第 372 场周赛题解 Leetcode 第 372 场周赛题解题目1&#xff1a;2937. 使三个字符串相等思路代码复杂度分析 题目2&#xff1a;2938. 区分黑球与白球思路代码复杂度分析 题目3&#xff1a;2939. 最大异或乘积思路代码复杂度分析 题目4&#xff1a;2940. 找到 Alice 和…

vatee万腾的科技奇点:Vatee创新力引领数字未来

在数字时代的涌动潮流中&#xff0c;Vatee万腾显露出一颗科技的奇点之心&#xff0c;其创新力正引领着数字未来的前沿。随着科技不断演进&#xff0c;Vatee万腾敏锐地捕捉到了科技的契机&#xff0c;展现出独特的创新视野&#xff0c;为数字化未来勾勒出了一幅令人瞩目的画卷。…

使用frp搭建内网穿透服务

使用frp搭建内网穿透服务 frp 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、HTTPS 等多种协议&#xff0c;且支持 P2P 通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。 1.下载frp 下载地址 2.服务端安装 …

[Linux] shell脚本相关知识

一、shell脚本基础 1.1 shell脚本的作用 shell将人类使用的高级语言翻译成二进制&#xff0c;再将二进制翻译成高级语言。换句话就是人类写了一个命令集合&#xff0c;然后用bash去翻译给硬件执行。 linux中常见的shell&#xff1a; bash:基于gun的框架下发展的shell csh:类…

同为科技(TOWE)智能机柜PDU助力上海华为数据中心完善机房末端配电

智能时代加速而来&#xff0c;最大的需求是算力&#xff0c;最关键的基础设施是数据中心。作为一家在信息通信领域拥有多年经验和技术积累的公司&#xff0c;华为在全国多个地区都设有数据中心&#xff0c;如知名的贵州贵安华为云全球总部、内蒙古乌兰察布华为数据中心等&#…

pnpm 管理依赖包是如何节省磁盘空间的?

npm 存在的问题 我们经常使用 npm 来管理 node 项目中的包&#xff0c;从 package.json 中读取配置将依赖下载到本地&#xff0c;以保障项目的正常运行。 当项目数量多时&#xff0c;这样的包管理方式会非常的占用电脑内存。由于每个项目都有属于自己的依赖&#xff0c;每个项…

什么是多域名证书?

多域名证书是指同一个证书中包含多个域名&#xff0c;能够在多个站点之间共享一份证书&#xff0c;实现一个站点对应多个域名的情况。多域名证书非常适合需要跨多个站点部署的应用&#xff0c;例如企业的子站点、博客等。 特点 多域名证书的优点包括以下几个方面&#xff1a;…