栈的一些小小应用

昨天刚实现了栈的一些基本操作,今天就来实现一点栈的应用把!

首先,写一点比较简单的:

1.逆波兰表达式的计算。

在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示。逆波兰表达式也称为后缀表达式。比如:

  两种表达式如果在程序中运行时,后缀表达式不需要考虑符号优先级的问题。

现在通过一个程序去计算一个简单的后缀表达式:

#pragma once

#include <iostream>
#include <assert.h>
#include <stack>
using namespace std;

enum Type
{
	OP_NUM,//数字
	OP_SYMBOL,//运算符
};

enum SYMBOL
{
	ADD,
	SUB,
	MUL,
	DIV,
};

struct Cell
{
	Type _type;//类型(1.数字 2.运算符)
	int _value;
};

int CountSymbol(Cell a[], size_t size)
{
	assert(a);
	stack<int> s;

	for (size_t i = 0; i < size; i++)//依次读取每个数据
	{
		if (a[i]._type == OP_NUM)
		{
			s.push(a[i]._value);
		}
		else
		{
			//取出运算符前面的两个数字进行计算
			int right = s.top();
			s.pop();//栈的特性,只能pop一个后去下一个数
			int left = s.top();
			s.pop();

			switch (a[i]._value)
			{
				//把计算结果压入栈中
			case ADD:
				s.push(left + right);
				break;
			case SUB:
				s.push(left - right);
				break;
			case MUL:
				s.push(left * right);
				break;
			case DIV:
				s.push(left / right);
				break;
			}
		}
	}
	return s.top();
}

void TestSymbol()
{
	//12*(3+4)-6+8/2 = 82
	//12 3 4 + * 6 - 8 2 / +   逆波兰表达式
	Cell a[] =
	{
		{OP_NUM,12},
		{OP_NUM, 3},
		{OP_NUM,4},
		{OP_SYMBOL,ADD},
		{OP_SYMBOL,MUL},
		{OP_NUM,6},
		{OP_SYMBOL,SUB},
		{OP_NUM,8},
		{OP_NUM,2},
		{OP_SYMBOL,DIV},
		{OP_SYMBOL,ADD},
	};
	int ret = CountSymbol(a, sizeof(a) / sizeof(a[0]));
	cout << "ret=" << ret << endl;
}

在这个程序中可以看到应用了栈的一个重要特性,“后进先出”。

2.迷宫是一个很长久的话题,今天我就用代码来实现它。

迷宫问题有一个很重要的点,就是“回溯”,顾名思义,就是沿着走过的路依次往回走。

为了简单起见,直接写一个迷宫,定义为“Maze.txt”文件

(0表示通路,1表示墙)

首先,定义一个二维数组,把迷宫的信息存储在这个二维数组中,然后从起点起依次判断该点的“上下左右”是否可以通过,可以通过就走到下一个点上,并且把走过的点置为“2”,直到无路可走时,沿着走过的路回溯,如果回溯到起点了,就表示没有路可以从这个迷宫中走出去!

话不多说,下面给出代码:

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1

#define N 10

#include <iostream>
#include <stack>
#include <assert.h>

using namespace std;

struct Pos//记录坐标
{
	int _row;//行
	int _col;//列
};

void GetMaze(int * a,int n)//读取迷宫
{
	FILE * fout = fopen("Maze.txt", "r");
	assert(fout);

	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; )
		{
			char ch = fgetc(fout);
			if (ch == ‘0‘ || ch == ‘1‘)
			{
				a[i*n + j] = ch - ‘0‘;
				j++;//有数据时,才往二维数组中存,所以j++放在这里
			}
			else
			{
				continue;
			}
		}
	}
	fclose(fout);
}

void printMaze(int * a, int n)//输出迷宫
{
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cout << a[i*n + j] << " ";
		}
		cout << endl;
	}
}

bool CheckIsAccess(int * a, int n, Pos next)//检查是否通行
{
	assert(a);
	if (next._row >= 0 && next._row < n&&
		next._col >= 0 && next._col < n&&
		a[next._row*n + next._col] == 0)// 0 表示可以通行
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool MazePath(int *a, int n, const Pos & entry, stack<Pos>& path)
{
	Pos cur = entry;
	path.push(cur);

	while (!path.empty())//栈空的时候返回起点
	{
		a[cur._row*n + cur._col] = 2;//走过的路标记为2

		if (cur._row == n - 1)//判断是否到出口
		{
			return true;
		}
		//向上
		Pos next = cur;
		next._row--;
		if (CheckIsAccess(a, n, next))//判断
		{
			cur = next;
			path.push(cur);//走过的坐标push进栈
			continue;
		}
		//向下
		next = cur;//每次判断的时候重新赋值给next
		next._row++;
		if (CheckIsAccess(a, n, next))
		{
			cur = next;
			path.push(cur);
			continue;
		}
		//向左
		next = cur;
		next._col--;
		if (CheckIsAccess(a, n, next))
		{
			cur = next;
			path.push(cur);
			continue;
		}
		//向右
		next = cur;
		next._col++;
		if (CheckIsAccess(a, n, next))
		{
			cur = next;
			path.push(cur);
			continue;
		}
		//无路可走
		a[cur._row*n + cur._col] = 3;
		path.pop();
		if (!path.empty())
		{
			cur = path.top();
		}
	}

	return false;
}

void TestMaze()
{
	int a[N][N] = {};
	GetMaze((int *)a, N);
	printMaze((int *)a, N);

	stack<Pos> path;
	Pos entry = { 2,0 };

	MazePath((int *)a, N, entry, path);
	cout << "结果" << endl;
	printMaze((int *)a, N);

}

必须强调的是:这个问题充分的利用了栈的特点来进行“回溯”。

时间: 2024-10-12 03:15:14

栈的一些小小应用的相关文章

七方件业金离以提领前群约会ODjdidtlwfWv

为了从不同环节,尤其与广大使用人群直接关系的环节反映质量状况,对共享自行车投放点.运营仓库.生产企业等不同环节的产品抽查,覆盖了共享自行车从成品出厂到待投放的关键环节. 该负责人称,根据新车投放情况,结合共享自行车行业市场占有分布特点,本次重点抽查了摩拜.ofo.Hellobike三个品牌的产品,占本次抽查批次总数的83.3%.其中,在天津.无锡.武汉.广州.深圳.东莞6个城市抽查了9批次摩拜产品,占产品抽查批次总数的37.5%,抽查批次合格率88.9%,抽查不合格的1批次产品为待投放于广州市的

内存分配(堆、栈、BSS、代码段、数据段)

这两天看了马士兵老师的视频.视频中提到了一个万能钥匙.就是了解程序运行中对内存的操作.主要讲了堆.栈.Data.说真的有点晕.看了两遍.也就略懂一二.在这做个小小知道总结 简介 我们程序运行的时候都是放在内存里的.根据静态.成员函数.代码段.对象.等等.放在不同的内存分块里.大概分为5块 1  栈 2  堆 3 BSS段-全局区-(静态区) 4 代码段 5 数据段 栈 存放局部变量.临时变量.声明.返回值.指向堆对象的地址(指针).总之存放一些小的东西.当不需要时候.栈会自动清除.比如一个加法方

安卓利用栈和算术表达式优先级实现进阶版计算器

先po上具体的源代码 简单的xml文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="

Nodejs系列课程,从入门到进阶帮你打通全栈

本课程由社区博主:Scott 编写 本文通过提供给大家学习的方法,以及我个人录制的一系列视频,帮助你更快更好的学习 Nodejs,了解前后端的 HTTP 知识,以及配置和使用阿里云 ECS 来部署你的 Nodejs 项目,成为那个具有争议的全栈开发工程师. 要不要学习 Nodejs 如果你是前端开发工程师,你本地电脑上不可避免的要安装 Nodejs,作为工具也好,作为服务器也好,要帮助你做掉很多又脏又累的事情,比如 less/scss 的编译,ES6/7 到 ES5 的转换,Javascript

“全栈”工程师 请不要随意去做

今天我来给大家说说 "全栈工程师" 的事儿. 写这篇文的背景原因: 很简单就是最近越来越多的人想做[全栈工程师],他们的目标就是全栈,他们才入行短短1-2年,甚至刚从培训班出来:我的目标是做全栈,我啥都要学会,啥都会写,这样我就是大牛了,可以挣大钱,就算创业,我也不用招那么多人,一个人搞定一个产品,融资上市 ,CEO白富美,balabala... 我给他的回复是: 去你xx的,你连JS 数组和对象用法都搞不清,抄几个效果,看几个视频教程摸索摸索就要做万能人了? "全栈&quo

15.1-全栈Java笔记:Java事件模型是什么?事件控制的过程有哪几步??

应用前边两节上一章节的内容,大家可以完成一个简单的界面,但是没有任何的功能,界面完全是静态的,如果要实现具体功能的话,必须要学习事件模型. 事件模型简介及常见事件模型 对于采用了图形用户界面的程序来说,事件控制是非常重要的. 一个源(事件源)产生一个事件并把它(事件对象)送到一个或多个监听器那里,监听器只是简单地等待,直到它收到一个事件,一旦事件被接收,监听器将处理这些事件. 一个事件源必须注册监听器以便监听器可以接收关于一个特定事件的通知. 每种类型的事件都有其自己的注册方法,一般形式为: v

链栈的实现

链栈即链式栈,也就是说我们不用再考虑空间的大小,可随心所欲的进行数据的插入/删除了.和顺序栈一样,仍然要保持其stack的特性,只在一端进行插入和删除,后进先出. 示例代码: #ifndef _LINKSTACK_H #define _LINKSTACK_H typedef int ElemType; typedef int Status; typedef struct linkStack { ElemType data; struct linkStack * top; }linkStack;

95后实习生的远程办公体验(asp.net mvc\C#技术栈)

这个月我们做了一件别人看起来很疯狂的事情,就是让一批95后的实习生实行远程办公,效果还不错,于是写此文总结一下. 其实认真算算,我自己的远程工作经验有十年了吧,在北京工作的时候天气不好就申请在家办公,在硅谷的时候每周有三天在家办公,两天去办公室办公.所以我也算得上是远程办公的老司机了吧. 不过,我之前都是对有多年工作经验的老司机才实行远程办公,还从来没有对还未毕业的实习生实行过.老实说,不敢啊,也不放心,况且我在cnblogs博客园呆了十年,还真没见过对还未毕业的实习生实行过远程办公的. 那为什

全栈必备Linux 基础

Linux 几乎无处不在,不论是服务器构建,还是客户端开发,操作系统的基础技能对全栈来说都是必备的. 系统的选择 Linux发行版本可以大体分为两类,一类是商业公司维护的发行版本,一类是社区组织维护的发行版本,前者以著名的Redhat(RHEL)为代表,后者以Debian为代表. Redhat,应该称为Redhat系列,包括RHEL.Fedora.CentOS(RHEL的社区克隆版本,免费).Ubuntu严格来说不能算一个独立的发行版本,Ubuntu是基于Debian加强而来,一个拥有Debia