【数据结构】三、栈和队列:3.链栈(链栈栈的初始化,判空,进栈,出栈,读取栈顶,链栈实例)

news/2024/5/10 1:13:09

文章目录

    • 3.链栈
      • 3.1初始化
      • 3.2判空
      • 3.3获取栈长度
      • 3.4入栈
      • 3.5出栈
      • 3.6销毁链栈
      • 3.7读取栈顶
      • 3.8遍历输出
      • ❗3.9链栈c++实例

3.链栈

链栈是运算受限的单链表,只能在链表头部进行操作的单链表。

  1. 链表的头指针就是栈顶,链头为栈顶,链尾为栈底
  2. 栈的链式存储不需要附设头节点
  3. 基本不存在栈满的情况,不需要判断栈满,但要判空。
  4. 空栈相当于头指针指向空。
  5. 插入(入栈)和删除(出栈)仅在栈顶处执行
  6. 因为是动态分配空间,所以需要释放。
#define MaxSize 100     //链栈的最大长度
typedef int SElemType;  //链栈的数据元素类型假设为int整型//创建链栈结构
typedef struct StackNode 
{SElemType data;   				//结点数据域struct StackNode* next;			//结点指针域
}StackNode, *LinkStack;				//struct StackNode的结点形式、链栈形式别名LinkStack stack;   //创建栈顶指针指向链栈的头结点
  • *StackNode,LinkStack的区别:
LinkStack temp1 = new StackNode;

这里 LinkStack 是一个指针类型别名,实际上是 StackNode* 的别名。
所以 temp1 是一个指针变量,指向 StackNode 类型的结点。

StackNode* temp2 = new StackNode;

这里直接声明了一个 StackNode* 类型的指针变量 temp2,指向 StackNode 类型的结点。

这两种声明方式是等价的。两者都创建了一个动态分配的 StackNode 类型的结点,并将它的地址赋给相应的指针变量。两者都可以通过 temp1->data 或 temp2->data 来访问结点的数据成员,以及 temp1->next 或 temp2->next 来访问结点的下一个结点的指针成员。

因此,在功能上,temp1 和 temp2 没有区别。不同的只是它们的声明方式,temp1 是通过别名 LinkStack 来声明的指针变量,而 temp2 是直接以 StackNode* 类型来声明的指针变量。

3.1初始化

//链栈的初始化
bool InitStack(LinkStack& stack){//构造一个空栈、栈顶指针置为空stack = NULL;return true; 
}

3.2判空

//判断链栈是否为空
bool StackEmpty(LinkStack& stack){if (stack == NULL){return true;}return false;
}

3.3获取栈长度

/*** @brief 获取栈顶长度。* 因为链表的最后一个节点的next指针是nullptr(或者说是NULL),代表链表的终止,* 所以可以将链表的遍历条件设置为当前节点指针不等于nullptr,这样在遍历过程中,* 当指针指向最后一个节点时,其next指针就会指向nullptr,循环条件就不再成立,* 遍历结束,可以避免继续遍历下一个不合法的节点。* @param stack * @return int */
int StackLength(LinkStack& stack){int length = 0;StackNode* temp = stack;//创建临时指针temp与stack指向同一位置while (temp != nullptr){length++;  						//链栈长度即为栈中元素个数,循环一次,长度++temp = temp->next; 		//temp指针下移一位}return length; 					//返回链栈长度
}

3.4入栈

链栈的入栈相当于单链表的前插法。

//入栈(前插法)
bool PushStack(LinkStack& stack, SElemType value){   //不用判栈满StackNode* temp = new StackNode; 		//生成新结点temptemp->data = value; 		//将新节点数据域置为valuetemp->next = stack; 		//将新结点插入栈顶stack = temp; 					//更新栈顶指针return true;
}

3.5出栈

//出栈:首先判空
bool PopStack(LinkStack& stack, SElemType &value){if (StackEmpty(stack)){return false; }value = stack->data;  		//将栈顶数据域元素赋值给valueStackNode* temp = stack;	//创建一个temp指针,并将其指向 stack 指针所指向的内存地址,以便找到出栈位置并释放。stack = stack->next; 			//令栈顶指针指向下一位结点,即更新栈顶指针delete temp;   						//释放temp所指向的空间,即出栈元素所占的内存空间,temp本身会在函数结束后自动销毁。return true;
}

3.6销毁链栈

//销毁链栈,释放内存
void DestroyStack(LinkStack& stack){StackNode* temp = new StackNode;	//创建一个指针while (stack != nullptr){temp = stack;				//使该临时指针与stack指向同一位置stack = temp->next;	//更新栈顶指针delete temp;				//释放临时指针}stack = nullptr;
}

3.7读取栈顶

//读取栈顶:取栈顶元素
bool GetTop(LinkStack& stack, SElemType &value){if (!StackEmpty(stack)){  	//若栈不为空value = stack->data;  		//返回栈顶元素return true;}cout<<"栈为空"<<endl;return false; 
}

3.8遍历输出

//遍历输出栈元素
bool StackPrint(LinkStack& stack){if (stack != nullptr){StackNode* temp = stack;	//创建一个指针与stack指向同一位置cout<<"出栈顺序:";while (temp != nullptr){cout << temp->data <<" ";temp = temp->next;  		//temp向下移动一位}return true;}cout<<"栈为空!"<<endl;return false;
}

❗3.9链栈c++实例

#include<iostream>
using namespace std;#define MaxSize 100     //链栈的最大长度
typedef int SElemType;  //链栈的数据元素类型假设为int整型//创建链栈结构typedef struct StackNode 
{SElemType data;   				//结点数据域struct StackNode* next;			//结点指针域
}StackNode, *LinkStack;				//struct StackNode的结点形式、链栈形式别名bool InitStack(LinkStack& stack);						//初始化链栈
bool StackEmpty(LinkStack& stack);					//链栈判空
int StackLength(LinkStack& stack);					//计算链栈长度元素个数
bool PushStack(LinkStack& stack, SElemType value);	//入栈
bool PopStack(LinkStack& stack, SElemType& value);	//出栈
bool GetTop(LinkStack& stack, SElemType& value);		//获取栈顶元素
bool StackPrint(LinkStack& stack);					//遍历元素
void DestroyStack(LinkStack& stack);				//销毁链栈,释放内存int main()
{//创建链栈LinkStack stack;SElemType value=1;InitStack(stack);cout << "检查栈是否为空?" << (StackEmpty(stack) ? "\t是" : "\t否") << endl;int number = 0;	//插入元素个数cout << "请输入需要插入的元素个数:";cin >> number;while ((number--) > 0) {PushStack(stack, value);//插入所输入元素value++;}cout << "当前栈的元素个数:" << StackLength(stack) << endl;GetTop(stack, value);cout << "栈顶元素:" << value << endl;StackPrint(stack);//遍历打印栈顶元素cout << endl;PopStack(stack, value);cout << "出栈一次,栈顶元素为:" << value << endl;StackPrint(stack);DestroyStack(stack);cout << endl << "栈已被销毁释放" << endl;cout << "销毁栈后遍历栈结果:" << " ";StackPrint(stack);system("pause");return 0;
}//链栈的初始化
bool InitStack(LinkStack& stack){//构造一个空栈、栈顶指针置为空stack = NULL;return true; 
}//判断链栈是否为空
bool StackEmpty(LinkStack& stack){if (stack == NULL){return true;}return false;
}/*** @brief 获取栈顶长度。* 因为链表的最后一个节点的next指针是nullptr(或者说是NULL),代表链表的终止,* 所以可以将链表的遍历条件设置为当前节点指针不等于nullptr,这样在遍历过程中,* 当指针指向最后一个节点时,其next指针就会指向nullptr,循环条件就不再成立,* 遍历结束,可以避免继续遍历下一个不合法的节点。* @param stack * @return int */
int StackLength(LinkStack& stack){int length = 0;StackNode* temp = stack;//创建临时指针temp与stack指向同一位置while (temp != nullptr){length++;  						//链栈长度即为栈中元素个数,循环一次,长度++temp = temp->next; 		//temp指针下移一位}return length; 					//返回链栈长度
}//入栈(前插法)
bool PushStack(LinkStack& stack, SElemType value){   //不用判栈满StackNode* temp = new StackNode; 		//生成新结点temptemp->data = value; 		//将新节点数据域置为valuetemp->next = stack; 		//将新结点插入栈顶stack = temp; 					//更新栈顶指针return true;
}//出栈:首先判空
bool PopStack(LinkStack& stack, SElemType &value){if (StackEmpty(stack)){return false; }value = stack->data;  		//将栈顶数据域元素赋值给valueStackNode* temp = stack;	//创建一个temp指针,并将其指向 stack 指针所指向的内存地址,以便找到出栈位置并释放。stack = stack->next; 			//令栈顶指针指向下一位结点,即更新栈顶指针delete temp;   						//释放temp所指向的空间,即出栈元素所占的内存空间,temp本身会在函数结束后自动销毁。return true;
}//取栈顶元素
bool GetTop(LinkStack& stack, SElemType &value){if (!StackEmpty(stack)){  	//若栈不为空value = stack->data;  		//返回栈顶元素return true;}cout<<"栈为空"<<endl;return false; 
}//遍历输出栈元素
bool StackPrint(LinkStack& stack){if (stack != nullptr){StackNode* temp = stack;	//创建一个指针与stack指向同一位置cout<<"出栈顺序:";while (temp != nullptr){cout << temp->data <<" ";temp = temp->next;  		//temp向下移动一位}return true;}cout<<"栈为空!"<<endl;return false;
}//销毁链栈,释放内存
void DestroyStack(LinkStack& stack){StackNode* temp = new StackNode;	//创建一个指针while (stack != nullptr){temp = stack;				//使该临时指针与stack指向同一位置stack = temp->next;	//更新栈顶指针delete temp;				//释放临时指针}stack = nullptr;
}

检查栈是否为空? 是
请输入需要插入的元素个数:5
1
2
3
4
5
当前栈的元素个数:5
栈顶元素:5
出栈顺序:5 4 3 2 1
出栈一次,栈顶元素为:5
出栈顺序:4 3 2 1
栈已被销毁释放
销毁栈后打印输出结果: 栈为空!
销毁栈后遍历栈结果: 栈为空!
Press any key to continue . . .


http://www.mrgr.cn/p/56778840

相关文章

在控制台实现贪吃蛇

在控制台实现贪吃蛇 前备知识Win32APICOORD这个结构体的声明如下&#xff1a;GetStdHandle 函数GetConsoleCursorInfo 函数SetConsoleCursorInfo 函数 SetConsoleCursorPosition 函数getAsyncKeyState 函数 控制台窗口的大小以及字符打印介绍控制台中的坐标宽字符及本地化介绍s…

MySQL第一次作业

解压完安装包 以管理员进入命令行 初始化并记住初始随机密码 创建服务名称 启动mysql 使用随机密码登录 修改密码 退出并重登服务器 MySQL创建数据库和表 创建数据库 创建表 1.进入数据库 创建表 向表中插入数据

启动 UE4编辑器报 加载 Plugin 失败

启动 UE4编辑器报 加载 Plugin 失败&#xff0c;报如下错误&#xff1a; Plugin ‘SteamVR’ failer to load because module ‘SteamVR’ could not be found. Please ensure the plugin is properly installed, otherwise consider disabling the plugin for this project. …

[ARC176F] Colorful Star

数数My Blogs [ARC176F] Colorful Star 感觉很考验想象力和计数基本功 QWQ。 首先考虑给定了局面之后如何进行判定。考虑把覆盖的过程倒着做:如果 \(i\) 旁边有和它颜色相同的棋子,那它就可以变成任意的颜色,然后要求最终能不能 \(n\) 种颜色都只剩一种。 然后这个还是不太本…

LayuiMini使用时候初始化模板修改(下载源码)

忘记加了 下载 地址 &#xff1a; layui-mini: layuimini&#xff0c;后台admin前端模板&#xff0c;基于 layui 编写的最简洁、易用的后台框架模板。只需提供一个接口就直接初始化整个框架&#xff0c;无需复杂操作。 LayuiMini使用时候初始化模板官网给的是&#xff1a; layu…

IIS中搭建.Net Core项目,步骤详解

一、准备服务器 1&#xff09;安装IIS 这个比较简单&#xff0c;百度一下就行 2&#xff09;安装 .NET Core 运行时 下载地址&#xff1a;下载 .NET(Linux、macOS 和 Windows) 因为我是本地开发&#xff0c;所以我下载的是SDK 安装成功之后显示如下&#xff1a; 检查是否安装…

WPF Prism

WPF编程-Prism世有伯乐,然后有千里马。千里马常有,而伯乐不常有。一、背景 Winform和WPF1. WinForms和WPF技术架构:WinForms是基于传统的窗体和控件的技术,使用的是类似于VB6时代的设计理念。 WPF是基于XAML(可扩展应用程序标记语言)的技术,允许更灵活、高度可定制化的用…

NIO之ByteBuffer

NIO中的ByteBuffer是缓冲区&#xff0c;其中有几个比较重要的属性capacity&#xff0c;position和limit。 capacity&#xff1a; 其中&#xff0c;capacity是缓冲区的容量大小&#xff0c;在分配内存空间后不会改变。 limit&#xff1a; limit是限制位置&#xff0c;在读写模…

SpringBoot集成minio前后端联调

基本配置 初始化项目 新建一个 SpringBoot 项目,集成 lombok mybatis-plus minio hutool-core(可有可无)。 新建一个数据表 attachement,用于存储文件上传后在 minio 中的位置。 drop table if exists attachment; create table attachment (id int auto_inc…

JMeter配置元件(一)

一 前言 环境: window 10 JMeter 5.3 记录一些常用的配置元件的用法 二 Configuration elements 配置元件 Configuration elements(配置元件)的作用就是给其后面的sampler(同作用域)准备好需要的数据,需要注意的是,配置原件总是比同作用域的sampler先执行 这有点像是定时…

Springboot集成minio前后端联调(后端对接minio)

基本配置 初始化项目 新建一个 SpringBoot 项目,集成 lombok mybatis-plus minio hutool-core(可有可无)。 新建一个数据表 attachement,用于存储文件上传后在 minio 中的位置。 drop table if exists attachment; create table attachment (id int auto_inc…

从Kafka的可靠性设计体验软件设计之美

目录 1. Kafka可靠性概述 2. 副本剖析 2.1 什么是副本 2.2 副本失效场景 2.3 数据丢失场景 2.4 解决数据丢失方案 3. 日志同步机制 4. 可靠性分析 1. Kafka可靠性概述 Kafka 中采用了多副本的机制&#xff0c;这是大多数分布式系统中惯用的手法&#xff0c;以此来实现水平扩…

Quarto Dashboards 教程 2:Dashboard Layout

「写在前面」 学习一个软件最好的方法就是啃它的官方文档。本着自己学习、分享他人的态度&#xff0c;分享官方文档的中文教程。软件可能随时更新&#xff0c;建议配合官方文档一起阅读。推荐先按顺序阅读往期内容&#xff1a; 1.quarto 教程 1&#xff1a;Hello, Quarto 2.qu…

echarts 图表+表格实现上图下表

效果图:1、结构布局 <div id="graphQuantityStatistics"></div> 2、配置图表data () {return {option:{legend: [{left: 0,bottom: -5,width: 80,orient: "vertical",itemGap: 0,itemWidth:6,itemHeight:6,textStyle: {width: 80,height: 25,…

制作表格/表单并用CSS美化

制作表格用到background-img设置表头背景图片(导航栏也可以这么用) 用到设置单双行不同颜色的方法 用到合并列colspan=number,合并行用rowspan=number 用到设置表格范围宽度方法<html><head><!--Ctrl+S保存后就可以刷新浏览器预览--><meta http-equiv=&…

ansible-copy用法

目录 概述实践不带目录拷贝带目录拷贝 概述 ansible copy 常用用法举例 不带目录拷贝&#xff0c;拷贝的地址要写全 带目录拷贝&#xff0c;拷贝路径不要写在 dest 路径中 实践 不带目录拷贝 # with_fileglob 是 Ansible 中的一个循环关键字&#xff0c;用于处理文件通配符匹…

工业测径仪的应用场景和可靠性判断

关键字:线缆测径仪,圆棒测径仪,圆管测径仪,金属棒管测径仪,工业测径仪,智能测径仪 智能测径仪主要应用于以下领域&#xff1a; 金属加工&#xff1a;测量金属线材、棒材、管材等的直径。线缆制造&#xff1a;检测电线、电缆的直径。塑料管材生产&#xff1a;监控塑料管材的外…

【深度学习】YOLOv5,烟雾和火焰,目标检测,防火检测,森林火焰检测

文章目录 数据收集和数据标注查看标注好的数据的脚本下载yolov5创建 dataset.yaml训练参数开始训练yolov5n训练训练后的权重下载gradio部署 数据收集和数据标注 搜集数据集2w张。 pip install labelme labelme 然后标注矩形框和类别。 下载数据请看这里&#xff1a; https:…