栈和深度优先搜索
栈¶
-
一种数据结构
-
特性:后进先出(如同子弹弹匣上子弹一样,先放进去的子弹是在最下层的,最后才会被打出来;而最后放进去的子弹是最上层的,会最先打出来)
栈的相关概念:¶
- 栈顶与栈底:允许元素插入与删除的一端称为栈顶,另一端称为栈底。
- 压栈:栈的插入操作,叫做进栈,也称压栈、入栈。
- 弹栈:栈的删除操作,也叫做出栈。
例如我们有一个存储整型元素的栈,我们依次压栈:{1,2,3}
在压栈的过程中,栈顶的位置一直在“向上”移动,而栈底是固定不变的。
如果我们要把栈中的元素弹出来:
STL就有栈,不需要大家重新手写一个栈。头文件:
1 |
|
1 2 |
|
一些常用的关于栈的函数:
- top() 返回栈顶部的元素
- push(x)插入元素x到顶部
- pop()弹出顶部元素
- size()返回栈中元素个数
- empty() bool类型,如果栈为空返回true,否则返回false
调用只需要把定义出来的栈对象如s,使用s.top()
,s.push(1)
,while(!s.empty())
……即可
栈的应用¶
1.括号匹配¶
通过使用栈可以很简单的去判断一个括号表达式是否合法
() , (()) , )()
具体步骤:
1). 首先新建一个空栈,遍历整个表达式
2). 遇到左括号时,将对应下标入栈
3). 遇到右括号时,检查栈是否为空,如果不为空那么弹出栈顶,否则表达式不合法
2.后缀表达式¶
我们日常见到的数学表达式如 a + b , a * (b + c) 等都是中缀表达式
而 a b + , a b c + *是对应的后缀表达式
通过栈 可以将中缀表达式转化为后缀表达式,很方便的得到表达式的计算结果,通过这个原理可以实现一个简易的计算器
具体实现算法:
1). 初始化两个空栈:运算数栈A,运算符栈B,遍历整个中缀表达式
2). 遇到运算数 a 直接入运算数栈A (a -> A)
3). 遇到运算符号 $ 判断 当前运算符的优先级 > 栈顶的运算符的优先级,
如果满足条件就入栈,否则将B栈顶符号出栈,并取运算数栈A的栈顶元素a和次栈顶元素b(也就是前两个元素),进行相应的运算a$b,并将运算结果入栈A
4). 如果遍历完表达式了,而运算符栈B不为空,那么将B栈顶符号出栈,并取运算数栈A的栈顶元素a和次栈顶元素b(也就是前两个元素),进行相应的运算a$b,并将运算结果入栈A
最终表达式的运算结果就是栈A的栈顶元素
注意:
如果是左括号那么不用判断优先级直接入栈,是右括号那么一直弹出栈顶直到遇到左括号,将左括号也弹出,结束。
如果遇到运算符而栈顶是括号,那么直接不用判断优先级直接入栈。
3.中断,子程序调用等等方面应用广泛¶
深度优先搜索 DFS¶
深度优先搜索算法(英语:Depth-First-Search,简称DFS)
定义:是ACM中一种十分常见和常用的搜索算法
方式:一般通过递归函数的方式,来搜索每一个需要的状态,去得到有用的信息,进而更新答案。
一般的搜索函数包括:
1.边界条件(搜索终止的条件,一定要注意设置好边界条件不然容易死递归)
2.递归主体
3.递归分支
1 2 3 4 5 6 |
|
DFS搜索的过程其实是一种树型结构,一般称为DFS树。
DFS举例¶
1. DFS枚举子集¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
--
2.DFS枚举全排列¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
3.八皇后问题¶
八皇后问题(英文:Eight queens),是回溯算法的典型案例。
问题表述为:在8×8格的国际象棋上摆放8个皇后棋子,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
4. 连通问题¶
二维地图DFS,假设给你一片二维平面上的草地,其中'#'表示草,'.'表示荒地,请你去求所有连通的草地数目,上下左右在一起的草地算连通。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
拓展知识: