C++数据结构-栈

目录

    • 顺序栈
    • 链栈

栈是允许在表的一端进行插入和删除的线性表。表中允许插入删除的一端是栈顶,栈顶的当前位置是动态变化的;不允许插入和删除的一端是栈底,栈底的位置是不变的。当表中没有元素时称为空栈,插入数据的运算称为进栈、压栈、入栈,删除数据的运算称为出栈或退栈。

进/出栈示意图:
在这里插入图片描述进栈的顺序是e1、e2、e3,出栈的顺序为e3、e2、e1,所以栈又称为后进先出线性表(Last In First Out),简称LIFO表,或称先进后出线性表。其特点是先进后出或者后进先出。

顺序栈

栈的存储与一般的线性表的存储类似,主要有两种存储方式:顺序存储和链式存储。

利用顺序存储方式实现的栈称为顺序栈。类似于顺序表的定义,要分配一块连续的存储空间存放栈中的元素,栈底位置可以固定地设置在数组的任何一端(一般在下标为0的一端),而栈顶是随着插入和删除而变化的,再用一个变量指明当前栈顶的位置(实际上是栈顶元素的下一个位置)。

在这里插入图片描述顺序栈的类描述如下:

// 学生表
struct Student
{
	int					id_;		// 学生id
	std::string			name_;		// 学生姓名
	int					score_;		// 学生成绩

	Student(int _id, std::string _name, int _score)
		: id_(_id), score_(_score), name_(_name)
	{}

	Student()
		: id_(0), score_(0)
	{}
};

class Stack
{
public:

	Stack(int _stackSize = 100);

	~Stack();

	bool IsEmptyStack();	// 判断栈是否为空

	bool PushStack(Student &_stu);		// 入栈

	bool PopStack(Student &_stu);		// 出栈

	bool GetTop(Student& _stu);			// 取栈顶元素

private:

	Student* base_;	// 栈底指针
	Student* top_;	// 栈顶指针

	int size_;		// 栈的大小
};

(1)判断栈是否为空

算法思想:判断top_是否小于等于base_,如果小于等于说明是空栈,返回true,否则返回false。

bool Stack::IsEmptyStack()
{
	if (top_ <= base_)
		return true;

	return false;
}

(2)入栈操作

算法描述:入栈操作是在栈的顶部进行插入操作,相当于在顺序表的表尾进行插入,因而无须移动元素。

算法思想:首先判断栈是否已满,若满则失败,返回0;否则,由于栈的top 指向栈顶元素的后一个位置,将入栈元素赋到top的位置,再将top+1指向新的位置,成功返回1。

bool Stack::PushStack(Student& _stu)
{
	if (top_ - base_ < size_)
	{
		*top_ = _stu;
		top_++;

		return true;
	}

	return false;
}

(3)出栈操作

算法描述:出栈操作是在栈的顶部进行,相当于是删除顺序表的最后一个元素,所以也不需要移动元素。

算法思想:首先判断栈是否为空,若空则失败,返回false;否则,由于栈的top 指向栈顶元素的后一位置,要先修改top为top-1,再将其所指向的元素以引用参数_stu返回,成功返回true。

bool Stack::PopStack(Student& _stu)
{
	if (top_ > base_)
	{
		top_--;
		_stu = *top_;

		return true;
	}

	return false;
}

(4)取栈顶元素

算法描述:取栈顶元素是获取出栈顶元素的值,而不改变栈。

算法思想:首先判断栈是否为空,若空则失败,返回0;否则,由于栈的top 指向栈顶元素的后一位置,返回top-1所指单元的值,栈不发生变化。

bool Stack::GetTop(Student& _stu)
{
	if (top_ <= base_)
		return false;

	_stu = *(top_ - 1);

	return true;
}

链栈

栈也可以用链式存储方式实现。一般链栈用单链表表示,其结点结构与单链表的结构相同,即结点为:

// 学生表
struct Student
{
	int					id_;		// 学生id
	std::string			name_;		// 学生姓名
	int					score_;		// 学生成绩

	Student(int _id, std::string _name, int _score)
		: id_(_id), score_(_score), name_(_name)
	{}

	Student()
		: id_(0), score_(0)
	{}
};

//定义链栈的结点
class StackNode                        
{
public:

	Student data;

	StackNode* next;
	StackNode()
	{
		next = NULL;
	};
};

因为栈中的主要运算是在栈顶进行插入和删除操作,显然在单链表的表头插入和删除都比较方便,因此以其作为栈顶,而且没有必要像单链表那样为了运算方便而附加一个头结点,存储结构如图:

在这里插入图片描述思考:为什么不用单链表的表尾作为栈顶?

因为用表尾作为栈顶,那么每次进行入栈、出栈、取栈顶元素的操作都需要遍历一遍单链表找到表尾,或者声明尾指针指向表尾,但是这样做太复杂,没有必要。

// 链栈
class LinkStack
{
public:

	LinkStack();

	~LinkStack();

	bool Empty_Stack();							//判断栈是否为空
	bool Push_Stack(Student e);					//将元素e插入栈顶
	bool Pop_Stack(Student& e);					//从栈顶删除一个元素到e中返回
	bool GetTop_Stack(Student& e);				//从栈顶取出一个元素到e中返回

private:
	StackNode* top_;

};            

(1)判断链栈是否为空

bool LinkStack::Empty_Stack()
{
	return (top_ == nullptr);
}

(2)入栈操作

入栈操作相当于是在表头插入一个元素

bool LinkStack::Push_Stack(Student e)
{
	StackNode* p = new StackNode;
	p->data = e;
	p->next = top_;

	top_ = p;

	return true;
}

(3)出栈操作

出栈操作相当于删除表头

bool LinkStack::Pop_Stack(Student& e)
{
	if (top_)
	{
		StackNode* p = top_;

		e = p->data;

		top_ = p->next;

		delete p;
		p = nullptr;

		return true;
	}

	return false;
}

(4)取栈顶元素

bool LinkStack::GetTop_Stack(Student& e)
{
	if (top_)
	{
		e = top_->data;

		return true;
	}

	return false;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从 MySQL 的事务 到 锁机制 再到 MVCC

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、事务 1.1 含义 1.2 ACID 二、锁机制 2.1 锁分类 2.2 隔离级别 三、MVCC 3.1 介绍 3.2 隔离级别 3.3 原理 四、总结 前…

python使用动态规划解决不同路径问题

针对二维动态规划&#xff0c;还有一个问题就是关于求不同路径的实例&#xff0c;主要是说明在实际应用的场景中&#xff0c;要理解透彻实际问题的真正目的&#xff0c;就可以灵活实现代码编写。 对于求不同路径问题描述&#xff0c;对于一个机器人&#xff0c;处在一个mxn的网…

【Unity美术】Unity工程师对3D模型需要达到的了解【二】

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

基于JavaWeb实验室预约管理系统(源码+数据库+文档)

一、项目简介 本项目是一套基于JavaWeb实验室预约管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;e…

【MATLAB】鲸鱼算法优化混合核极限学习机(WOA-HKELM)时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 鲸鱼算法优化混合核极限学习机&#xff08;WOA-HKELM&#xff09;是一种时序预测算法&#xff0c;它结合了鲸鱼算法和混合核极限学习机&#xff08;HKELM&#xff09;的优点。以下是该算法…

Ts自封装WebSocket心跳重连

WebSocket是一种在单个TCP连接上进行全双工通信的协议&#xff0c;允许客户端和服务器之间进行双向实时通信。 所谓心跳机制&#xff0c;就是在长时间不使用WebSocket连接的情况下&#xff0c;通过服务器与客户端之间按照一定时间间隔进行少量数据的通信来达到确认连接稳定的手…

大模型微调LoRA训练与原理

1.什么是LoRA&#xff1f; LoRA的全称是LOW-RANK-ADAPTATION。是一种实现迁移学习的技术手段。 2. 矩阵的秩&#xff1f; 秩是一个向量空间的基向量的个数。例如&#xff1a;二维平面坐标系存在两个基向量&#xff0c;平面上任意的一个向量都可以使用这两个基向量进行线性表示…

PS制作淘宝主图

PS制作淘宝主图 1.制作主图主页1.1新建800x800画板1.2填充前景色&#xff1a;altdel1.3选择圆角矩形&#xff0c;半径501.4按住ALT&#xff0c;往下投复制 2.调色 1.制作主图主页 1.1新建800x800画板 1.2填充前景色&#xff1a;altdel 1.3选择圆角矩形&#xff0c;半径50 居中对…

矿用以太网通讯的电缆传输可行性分析

概述 井下通讯系统是煤矿安全及生产调度必不可少的设施&#xff0c;近年泄露技术、小灵通技术、无线对讲技术及WIFI技术相继应用于煤矿井下。WIFI技术在地面的短距离无线通讯中已有多年的应用&#xff0c;相对于其他的无线宽带技术来说比较成熟可靠。 “泄露”技术及低频穿透技…

VC2019更改文件名称代码

VC2019更改文件名称代码 效果代码 效果 华为手机拍摄的视频默认名称是“VID_20231213_111723”,图片名称是“IMG_20231213_111723”&#xff0c;需要批量将“VID”改为“IMG” 代码 代码&#xff08;C#&#xff09;&#xff1a; csharpStringBuilder sbnew StringBuilder()…

ROS TF坐标变换 - 静态坐标变换

目录 一、静态坐标变换&#xff08;C实现&#xff09;二、静态坐标变换&#xff08;Python实现&#xff09; 如前文所属&#xff0c;ROS通过广播的形式告知各模块的位姿关系&#xff0c;接下来详述这一机制的代码实现。 模块间的位置关系有两种类型&#xff0c;一种是相对固定…

使用spring boot实现异常的统一返回

在这个前后端分离的时代&#xff0c;一个 统一的数据格式非常重要。本次我们实现用spring boot实现一下返回给前端数据的统一格式&#xff0c;不再出现服务器500的错误。 新建一个spring boot项目&#xff0c;并导入knife4j的依赖。 写一个controller控制器&#xff0c;用来是…

Vue中全局事件总线的配置和原理

实现任意组件之间的通信 任意组件通信的原理&#xff1a; 1、实现任意组件之间的通信,需要一个傀儡。这个傀儡既能被vm访问到,也能被VueComponent访问。 2、VueComponent.prototype.proto Vue.prototype为图上1.0黄色的线路。是Vue让组件实例对象VueComponent可以访问到Vue原…

将学习自动化测试时的医药管理信息系统项目用idea运行

将学习自动化测试时的医药管理信息系统项目用idea运行 背景 学习自动化测试的时候老师的运行方式是把医药管理信息系统项目打包成war包后再放到tomcat的webapp中去运行&#xff0c;于是我想着用idea运行会方便点&#xff0c;现在记录下步骤方便以后查找最开始没有查阅资料&am…

【栈】根据模式串构造最小数字

import java.util.ArrayDeque; import java.util.Deque;/*** 思路&#xff1a;如果是字符‘I’直接对应的数字加入结果res中&#xff0c;如果是‘D’将对应的数字加入栈中。* 再次遇到‘I’先将对应的数字加入结果res中&#xff0c;然后再将栈中的元素从栈顶取出存放在* …

simulink代码生成(五)——ePWM模块初级应用

前面分别讲到了SCI及ADC的配置及使用&#xff0c;现在梳理一下ePWM的配置和使用&#xff1b; 先打一些基础的DSP28335的基础知识&#xff1b; F28335 关于ePWM中断与SOC采样信号的一些思考_socasel-CSDN博客 F28335 ePWM模块简介——TMS320F28335学习笔记&#xff08;四&…

受“博比特虫”启发可实现多模态传感抓取动作的软执行器来了

软执行器可以实现对易碎和不规则形状物体的精细自适应抓取&#xff0c;这在生物和工程系统中至关重要。然而&#xff0c;目前软机器人在抓取的时候往往受制于抓取能力不足和功能限制。 博比特虫捕获猎物 最近研究人员提出了一种受博比特虫启发的多模态传感自适应软抓取器&…

simulink代码生成(六)——多级中断的配置

假如系统中存在多个中断&#xff0c;需要合理的配置中断的优先级与中断向量表&#xff1b;在代码生成中&#xff0c;要与中断向量表对应&#xff1b;中断相关的知识参照博客&#xff1a; DSP28335学习——中断向量表的初始化_中断向量表什么时候初始化-CSDN博客 F28335中断系…

sscanf的简介

sscanf 函数的原型&#xff1a; 第一个函数参数 const char * 表示字符串 &#xff08;类似于scanf&#xff09;第二个函数参数表示 格式 ​​​​​​​ ​​​​​​​ 第三个函数参数 首先sscanf函数可以用于以下几种情况&#xff1a; 分离数字&#xff1a; #i…

Java开发过程中的幂等性问题

幂等性问题&#xff1a; 1. 有时我们在填写某些 form表单 时&#xff0c;保存按钮不小心快速点了两次&#xff0c;表中竟然产生了两条重复的数据&#xff0c;只是id不一样。 2. 我们在项目中为了解决 接口超时 问题&#xff0c;通常会引入了 重试机制 。第一次请求接口超时了…