数据结构---栈和队列详解(上)

一、栈的定义

1、栈是限定仅在表尾进行插入删除操作的线性操作。

(栈类似于子弹弹夹中的子弹一样,先进去的后出来,后进去的要先出来。)

在我们软件应用中,栈这种后进先出的数据结构是非常普。比如你用浏览器上网时,不管用什么浏览器,都有一个"后退键",你单击后可以按访问顺序的逆序加载浏览过的网页。再一个撤销操作也是用栈这样的方式实现的。

2、我们把允许插入和删除的一端称之为栈顶(top),另一端称作栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出(Last in First Out)的线性表,简称:LIFO结构。

3、栈是一个线性表,也就是说,栈元素具有线性关系 ,即前驱后继关系。只不过它是一种特殊的线性表而已。定义中说是在线性表尾进行插入和删除操作,这里表尾是指栈顶,而不是栈底。

它的特殊之处就在于限制了这个线性表的的插入和删除位置,它始终只在栈顶进行,这也就使得:栈底是固定的,最先进栈的只能在栈底。

4、栈的插入操作,叫做进栈,也称为压栈,入栈;栈的删除操作,叫做出栈,也有的叫弹栈。

二、栈的实现

(这里我们用数组来实现,链表空间开销更大)

1、栈的初始化:

先定义栈的结构:

cpp 复制代码
//定义栈的结构
typedef int STDatatype;
typedef struct Stack
{
	STDatatype* arr;
	int top;
	int capacity;

}ST;
cpp 复制代码
//初始化
void StackInit(ST* ps)
{
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}

这里top用来标记栈顶元素在数组中的位置。

2、入栈

cpp 复制代码
void StackPush(ST* ps, STDatatype x)
{
	assert(ps);
	if (ps->top == ps->capacity) {
		//增容
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDatatype* tmp = (STDatatype*)realloc(ps->arr, newCapacity * sizeof(STDatatype));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	ps->arr[ps->top++] = x;
}

3、销毁栈

cpp 复制代码
//销毁
void StackDestroy(ST* ps)
{
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}

4、判断栈是否为空

cpp 复制代码
//判断栈是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

5、出栈

cpp 复制代码
//出栈
void StackPop(ST* ps)
{
	assert(!StackEmpty(ps));
	--ps->top;
}

6、取栈顶元素

cpp 复制代码
//取栈顶元素
STDatatype StackTop(ST* ps)
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}

7、取栈顶有效元素

cpp 复制代码
//获取栈中的有效元素
int StackSize(ST* ps)
{
	return ps->top;
}

三、栈的作用

栈的引入简化了程序设计的问题,划分了不同关注层次,使得思考范围缩小,更加聚焦于我们要解决的问题核心。

四、栈的应用

后缀(逆波兰)表示法的定义:

逆波兰表示法,也称为后缀表示法,是一种数学表达式的表示方法。在这种表示法中,运算符位于其操作数之后,与我们常见的中缀表示法(如 a + b )不同,它的结构更利于计算机进行表达式求值(无需处理括号和运算符优先级)。

核心特点

  • 无括号:通过运算符的位置天然体现运算顺序,无需括号来指定优先级。
  • 运算顺序明确:从左到右扫描表达式,遇到运算符时,对其前面最近的若干个操作数执行运算。

示例

  • 中缀表达式 3 + 4 ,对应的逆波兰表示为 3 4 + 。

  • 中缀表达式 (3 + 4) * 5 ,对应的逆波兰表示为 3 4 + 5 * 。

  • 中缀表达式 3 + 4 * 5 ,对应的逆波兰表示为 3 4 5 * + (因为乘法优先级高于加法,先算 4*5 )。

求值逻辑(以栈实现)

  1. 初始化一个空栈。

  2. 从左到右扫描逆波兰表达式的每个元素:

  • 若为操作数,将其压入栈中。

  • 若为运算符,从栈中弹出两个操作数(先弹出的是右操作数,后弹出的是左操作数),执行该运算符的运算,再将结果压入栈中。

  1. 扫描结束后,栈中仅剩的元素即为表达式的结果。

例如,对 3 4 5 * + 求值:

  • 压入 3 →压入 4 →压入 5 ;

  • 遇到 * ,弹出 5 和 4 ,计算 4*5=20 ,压入 20 ;

  • 遇到 + ,弹出 20 和 3 ,计算 3+20=23 ,最终结果为 23 。

相关推荐
前端世界5 分钟前
用Python手写一个能识花的感知器模型——Iris分类实战详解
开发语言·python·分类
心.c20 分钟前
深拷贝浅拷贝
开发语言·前端·javascript·ecmascript
岑梓铭22 分钟前
《考研408数据结构》第六章(5.1+5.2+5.3树、二叉树、线索二叉树)复习笔记
数据结构·笔记·考研·408·1024程序员节
曦樂~22 分钟前
【Qt】启动新窗口--C/S传输信息
开发语言·qt
源代码•宸22 分钟前
Qt6 学习——一个Qt桌面应用程序
开发语言·c++·经验分享·qt·学习·软件构建·windeployqt
寻找华年的锦瑟24 分钟前
Qt-UDP
开发语言·qt·udp
橘颂TA26 分钟前
【QSS】软件界面的美工操作——Qt 界面优化
开发语言·qt·c/c++·界面设计
苏纪云35 分钟前
数据结构<C++>——数组
java·数据结构·c++·数组·动态数组
Evand J1 小时前
【MATLAB例程】二维环境定位,GDOP和CRLB的计算,锚点数=4的情况(附代码下载链接)
开发语言·matlab·定位·toa·crlb·gdop
郝学胜-神的一滴1 小时前
使用现代C++构建高效日志系统的分步指南
服务器·开发语言·c++·程序人生·个人开发