C++ 栈的应用

1、栈的应用1 解决迷宫问题

问题:一个n*n的0、1矩阵,0 表示可以走通,1表示不可以走 ,假定矩阵的下边是出口,给定矩阵的入口坐标,求出走出迷宫的路径

这里用 栈 主要是解决 如图所示 走不出去 会退时上一步(出栈) 位置的记录

以及 记录已经走过的路径(压栈)

扩展 :(1) 非递归法实现

(递归法 与 非递归 的 一点不同

递归法不会出现 尝试下一步失败后 退到上一步 再次尝试下一步时 不会出现 重复 尝试上一次走错的那个“下一步” 而 下面使用 栈的方式的 退栈时 下一步尝试还会判断 已走过不成功的情况【重复判断一次】)

(2) 多个出口 最短路问题    【在下面实现】

//-----------------Maze.h---------

#pragma once

#define N 10

#define MAZEPATH "MazeMap.txt"

#include<iostream>

using namespace std;

#include <assert.h>

#include <stack>

struct Pos

{

int _row;

int _col;

};

void GetMaze(int* a, int n);

void PrintMaze(int* a, int n);

bool MazePath(int* a, int n, const Pos entry, stack<Pos>& path);

//-----------------Maze.cpp-----------

#define _CRT_SECURE_NO_WARNINGS 1

// 栈应用:迷宫(n*n)问题

#include "Maze.h"

void GetMaze(int* a, int n)

{

FILE* f_out = fopen(MAZEPATH, "r");

assert(f_out != NULL);

for (int i = 0; i < n; i++)

{

for (int j = 0; j < n; )

{

char ch = fgetc(f_out);

if (ch == ‘0‘ || ch == ‘1‘) //通路为0 不通路2

{

a[i*n + j] = ch - ‘0‘;

++j;

}

else

{

continue;

}

}

}

fclose(f_out);

}

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(const int *a, int n, const 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;

}

}

// const Pos entry 入口  , stack<Pos>& path 用于压路径的 栈

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);

continue;

}

// 向右 探索

next = cur;

next._col++;

if (CheckIsAccess(a, n, next))

{

cur = next;

path.push(cur);

continue;

}

// 向下 探索

next = cur;

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;

}

// 走不通

a[cur._row * n + cur._col] = 5;// 标出错误路线

path.pop();

if (!path.empty())

{

cur = path.top();

}

}

return false;

}

//---------------------test.cpp----------------------

#define _CRT_SECURE_NO_WARNINGS 1

#include "Maze.h"

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);

}

int main()

{

TestMaze();

getchar();

return 0;

}

//--------------MazeMap.txt----------------

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

0 0 0 1 1 1 1 1 1 1

1 1 0 1 1 1 1 1 1 1

1 1 0 1 1 1 1 1 1 1

1 1 0 1 1 1 1 1 1 1

1 1 0 0 0 0 0 0 1 1

1 1 0 1 1 1 1 0 1 1

1 1 0 1 1 1 1 0 1 1

1 1 0 1 1 1 1 1 1 1

//////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////

2、栈的应用2 逆波兰式计算

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>

#include<assert.h>

#include<stack>

using namespace std;

// 栈的应用 2 算数表达式求解

enum Type

{

OP_NUM,

OP_SYMBOL

};

struct Cell

{

Type type;

int value;

};

enum SYMBOL

{

ADD,

SUB,

MUL,

DIV

};

int CountRNP(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();

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 TestRnp()

{

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 = CountRNP(a, sizeof(a)/sizeof(a[0]));

}

int main()

{

TestRnp();

return 0;

}

////////////////////////////////////////////////////

////////////////////////////////////////////////////

//----------------迷宫 递归法(不用栈)---------

// 递归法  不需要栈

bool MazePath(int* a, int n, Pos cur)

{

// 定义数组 最下边为 出口

if (cur._row == n - 1 && a[cur._row * n + cur._col] == 0) // 判断是否到出口

{

a[cur._row * n +cur._col] = 2; // 2 表示此路可走

return true;

}

if (CheckIsAccess(a, n, cur))

{

a[cur._row * n +cur._col] = 2; // 2 表示此【点】可走 下一步还不知道

Pos next_left = cur;

next_left._col--;

Pos next_right = cur;

next_right._col++;

Pos next_up = cur;

next_up._row--;

Pos next_down = cur;

next_down._row++;

bool next = (MazePath((int*)a, n, next_up)

|| MazePath((int*)a, n, next_right)

|| MazePath((int*)a, n, next_down)

|| MazePath((int*)a, n, next_left));

if (!next)

{

a[cur._row * n +cur._col] = 5; //5表示  下一步走不出去 把当前点从2变到五 表示这个点走不出去

return false;

}

else

{

return true;

}

}

else //cur 不能走

{

return false;

}

}

2 表示成功路线

5 表示 尝试失败的路线

/////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////

//--------------------迷宫 (最短路) ---------------

//-------------------Maze.h--------------------

#pragma once

#define N 10

#define DEBUGE 0 // 1 调试 0 不调试

#define MAZEPATH "MazeMap.txt"

#include<iostream>

using namespace std;

#include <assert.h>

#include <stack>

struct Pos

{

int _row;

int _col;

};

//stack<Pos> MinPath;

void GetMaze(int* a, int n);

void PrintMaze(int* a, int n);

bool MazePath(int* a, int n, const Pos entry, stack<Pos>& path);

bool FindMinPath(int* a, int n, const Pos entry ,stack<Pos>& MinPath);

int GetCount(stack<Pos> path);

//---------------------------Maze.cpp-----------------

#define _CRT_SECURE_NO_WARNINGS 1

// 栈应用2:迷宫(n*n)问题

#include "Maze.h"

void GetMaze(int* a, int n)

{

FILE* f_out = fopen(MAZEPATH, "r");

assert(f_out != NULL);

for (int i = 0; i < n; i++)

{

for (int j = 0; j < n; )

{

char ch = fgetc(f_out);

if (ch == ‘0‘ || ch == ‘1‘) //通路为0 不通路2

{

a[i*n + j] = ch - ‘0‘;

++j;

}

else

{

continue;

}

}

}

fclose(f_out);

}

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(const int *a, int n, const 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;

}

}

// const Pos entry 入口  , stack<Pos>& path 用于压路径的 栈

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);

continue;

}

// 向右 探索

next = cur;

next._col++;

if (CheckIsAccess(a, n, next))

{

cur = next;

path.push(cur);

continue;

}

// 向下 探索

next = cur;

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;

}

// 走不通

a[cur._row * n + cur._col] = 5;// 标出错误路线

path.pop();

if (!path.empty())

{

cur = path.top();

}

}

return false;

}

int GetCount(stack<Pos> path)

{

int count = 0;

while(!path.empty())

{

count += 1;

path.pop();

}

return count;

}

void huanyuan(int* a,int n, stack<Pos> Path) // Path不用引用

{

while(!Path.empty())

{

a[Path.top()._row * n + Path.top()._col] = 0;

Path.pop();

}

}

bool FindMinPath(int* a, int n, const Pos entry,stack<Pos>& MinPath)

{

bool next = false;

bool ret = false;

do

{

stack<Pos> path;

next = MazePath(a, n, entry, path);

//----------------debuge----------

#if DEBUGE

cout<<"-----------------------------"<<endl;

PrintMaze(a,n);

#endif

if (next)

{

if (MinPath.empty())

{

MinPath = path;  

}

else

{

if (GetCount(MinPath) > GetCount(path))

{

MinPath = path; // 更新MinPath

}

}

huanyuan((int*)a, n, path);// 将已经走过的路 2 标记为 0

a[path.top()._row * n + path.top()._col] = 9; // 此出口已经堵住

//--------------debuge---------

#if DEBUGE

cout<<"-------------huanyuan----------------"<<endl;

PrintMaze(a,n);

#endif

ret = true;

}

}while(next);

if (ret)

{

huanyuan(a, n, MinPath);

//a[MinPath.top()._row * n + MinPath.top()._col] = 2; //打开这个最短路出口

}

return ret;

}

//--------------------------------test.cpp-----------------

#define _CRT_SECURE_NO_WARNINGS 1

#include "Maze.h"

void TestMaze()

{

int a[N][N] = {};

GetMaze((int*)a, N);

PrintMaze((int*)a, N);

stack<Pos> path;

stack<Pos> MinPath;

Pos entry = {2, 0};

FindMinPath((int*)a, N, entry ,MinPath);

cout<<"------------------------------"<<endl;

PrintMaze((int*)a, N);

}

int main()

{

TestMaze();

getchar();

return 0;

}

//----------------------------MazeMap.txt---------------------

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

0 0 0 1 1 1 1 1 1 1

1 1 0 1 1 1 1 1 1 1

1 1 0 1 1 1 1 1 1 1

1 1 0 1 1 1 1 1 1 1

1 1 0 0 0 0 0 0 1 1

1 1 0 1 1 1 1 0 1 1

1 1 0 1 1 1 1 0 1 1

1 1 0 1 1 1 1 0 1 1

运行图:

时间: 2024-10-28 18:57:09

C++ 栈的应用的相关文章

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

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

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

今天我来给大家说说 "全栈工程师" 的事儿. 写这篇文的背景原因: 很简单就是最近越来越多的人想做[全栈工程师],他们的目标就是全栈,他们才入行短短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

JavaScript栈和堆内存,作用域

1.栈 stack"和"堆 heap": 简单的来讲,stack上分配的内存系统自动释放,heap上分配的内存,系统不释放,哪怕程序退出,那一块内存还是在那里.stack一般是静态分配内存,heap上一般是动态分配内存. 2.基本类型和引用类型: 基本类型:存放在栈内存中的简单数据段.数据大小确定,内存空间大小可以分配. 引用类型:存放在堆内存中的对象,变量中实际保存的是一个指针,这个指针指向另一个位置.每个空间大小不一样,要根据情况开进行特定的分配. 详见<Javas

AC日记——双栈排序 洛谷 P1155

双栈排序 思路: 二分图染+模拟: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1005 #define maxm 2000005 int n,head[maxn],E[maxm],V[maxm],cnt,col[maxn]; int minn[maxn],ai[maxn],sta1[maxn],sta2[maxn],top1,top2; bool if_[maxn][maxn]; inline void in(

leetcode栈--5、valid-parentheses(有效括号)

题目描述 Given a string containing just the characters'(',')','{','}','['and']', determine if the input string is valid. The brackets must close in the correct order,"()"and"()[]{}"are all valid but"(]"and"([)]"are not.

栈的数据结构

package com.wwj.cn; public class SqStack { private final int MAXSIZE = 10; int[] data = new int[MAXSIZE]; int top;// 栈顶指针 }