[考研系列之数据结构]线性表之栈
2014-05-30 22:07
197 查看
基本概念
栈的定义 | 限定仅在表尾进行插入或删除的线性表 | |
组成 | 栈顶 | |
栈底 | ||
基本操作 | 入栈(PUSH) | 往栈中插入一个元素 |
弹栈(POP) | 从栈顶删除一个元素 | |
栈的表示 | 顺序栈 | |
链栈 |
base指向栈底
top指向栈顶
对于栈的一些基本情况:
栈不存在时候 | base=NULL |
栈为空时 | top=base |
栈的长度 | top-base |
栈的应用
1 数制转换
数制转换我们使用一种称之为“辗转相除法”的算法。此算法的基本原理基于:N=(N div d)*d + N mod d
应用辗转相除法,我们看看如何将十进制的1348转换成八进制:
在程序上,我们将N mod 8的结果入栈,在div结束之后弹栈得到答案就是2508了。
最后我们看一下程序的实现,很简单,程序分为两个流程:
入栈过程
弹栈过程
入栈过程也就是运算过程,使用Java风格伪代码:
Stack<int> stack=new Stack<int>;
while(N!=0)
{
stack.push(N%8);
N=N/8;
}
弹栈过程就是输出八进制数的时候了:
String result;
while(!stack.empty())
{
result+=stack.pop();
}
2 括号匹配检验
栈的另个用途就是检测括号的匹配,算法的思路是:1.构造一个空栈,栈的元素是单个字符 |
2.对于括号,我们分为"("、")"、"["、"]"、"{"、"}"这六种,其中两两配对,每对都有左右两种,我们遍历整个全是括号的字符串,针对3种左括号,我们遇到之后将它入栈 |
3.针对于遇到的右括号,我们弹出栈顶元素,看看弹出的左括号是不是能和遇到的右括号匹配,如果能继续往后遍历字符串,反之检验失败:括号不能匹配 |
4.当我们遍历整个字符串没有发现3中的检验失败,我们要做一个收尾工作:如果现在栈为空则检验括号是匹配的;反之表示多出了不能匹配的左括号,括号不能匹配 |
能匹配的情况:[([]())]
不能匹配的情况:[([]()})]
算法的伪代码:
boolean check(String str)
{
Stack<char> stack=new Stack<char>();
for(int i=0;i<str.length;++i)
{
if(str[i].equal("(")||str[i].equal("[")||str[i].equal("{")) //左括号
{
stack.push(str[i]);
}
else //右括号
{
if(str[i].equal(")"))
{
if(!"(".equal(stack.pop()))
return false;
}
else if(str[i].equal("]"))
{
if(!"[".equal(stack.pop()))
return false;
}
else if(str[i].equal("}"))
{
if(!"{".equal(stack.pop()))
return false;
}
}
}
if(stack.empty())
return true;
return false;
}
3 行编辑程序
见严书P49。4 迷宫求解
针对严书上的迷宫求解,我不甚明了,所谓迷宫求解也就是搜索算法,也可以认为是图论的一部分,而搜索算法分为广度优先搜索算法
深度优先搜索算法
针对深度优先搜索算法,由于需要回溯,所以经常使用栈去记录路径和状态,这个按下不表。
5 表达式求解
我们使用“算符优先法”去对表达式求值我们的表达式求值只包括加减乘除括号这几种操作,针对于两个算符a b,两者的关系只能是
a<b | a的算数优先级小于b的算数优先级 |
a>b | a的算数优先级大于b的算数优先级 |
a=b | a的算数优先级等于b的算数优先级 |
下面谈算法的实现
[1] 首先我们需要构造两个栈
OPTR | 存放操作符 |
OPND | 存放操作数和运算结果 |
1 初始情况 | OPND为空 | |
OPTR中栈底为# | ||
2 依次读入每个字符c | 如果c是操作数 | OPND.push(c) |
如果c是操作符,将OPTR栈顶操作符OPTR.top()和它比较 | c<OPTR.top() | operation=OPTR.pop(); |
a=OPND.pop(); | ||
b=OPND.pop(); | ||
Cal(a,opreation,b); | ||
c=OPTR.top() | OPTR.pop() | |
c>OPTR.top() | OPTR.push(c) | |
3 获取结果 | result=OPND.top() |
计算3*(7-2)
相应的栈的操作:
相关算法的实现以后会补齐。
6 栈和递归
递归是程序设计上一个非常重要的概念,关于递归最精炼的描述是一个冷笑话:”
要想知道什么是递归,那么你首先得知道什么是递归。
“
理解递归的人看到这个笑话一定会会心一笑。
关于递归的基础知识这里就不多说了。递归有很多应用,如求斐波那契数列、求阶乘....
下面问题是:如何将一个递归的算法改成非递归的实现?
这个问题是有非常广阔的前景的,学习数据结构后面的知识大家会知道树的深度优先搜索的递归和非递归形式。事实上,所以递归算法都会有其非递归的实现,因为递归的函数调用是和栈息息相关的,那么,如果我们自己构造一个栈去模拟递归就可以得到非递归的实现了。
汉诺塔问题[待完善]
相关文章推荐
- [考研系列之数据结构]线性表之链表
- [考研系列之数据结构]数据结构概述
- [考研系列之数据结构]线性表之队列
- [考研系列之数据结构]线性表之字符串
- [考研系列之数据结构]线性表概述
- 手工数据结构系列-C语言模拟栈 hdu1022
- 【数据结构&&算法系列】KMP算法介绍及实现(c++ && java)
- 09考研数据结构试题的一种解法(Java版)
- 数据结构系列之链表——双链表删除
- 数据结构考研
- 数据结构系列之快速排序详解
- Open vSwitch系列之数据结构解析深入分析Hmap
- 【数据结构系列】线段树(Segment Tree)
- 考研数据结构题目——树(持续更新)
- 重温数据结构系列随笔:单链表(c#模拟实现)
- 考研路上的那些一战二战三战成功与失败的故事系列之十五
- 数据结构系列——后缀树(附Java实现代码)
- 我思故我在系列—数据结构面试NO.24(题目搜集整理者JULY,非常感谢!!)
- 2019数据结构考研(二)-----线性表
- 数据结构系列笔记---系统导图