出栈顺序
之前参加过华北计算机研究所和优酷土豆的笔试,都考到出栈顺序,之前数据结构学的不到位,遇到这类题时,还着实把我愣了一会,现在总结下,省得以后再遇到这类问题,也希望能给遇到同样问题的兄弟们一个参考。
废话不多说,直接上个例题。
一个栈的入栈序列是a,b,c,d,e则栈的不可能的输出序列是:()
A edcbd B decba C dceab D abcde
栈之根本——后进先出(Last In First Out , LIFO)初次接触到这个问题的人,或许会认为入栈abcde,所以出栈只能是edcba所以BCD都不对。
其实是这个问题描述有歧义,应该是分段入栈的顺序,也就是说,可能先入栈a,取出a,入栈b,取出b……,所以D也是可能的。
知道这个意思了以后,就要明确这个问题的矛盾根本所在:第一次出栈d,说明什么?说明a,b,c一定早已入栈(入栈顺序决定的)。那么在出栈d以后,a,b,c的出栈顺序一定是c,b,a,而不用理会中间穿插着出栈了d后面的字符(因为可以再入栈,再出栈嘛)。所以立即选中C,不用犹豫,理由简单:d出栈了,abc一定已经入栈,那么abc只能以cba的顺序出栈,C不符合,OK!
举一个更加直观的例子:
如栈顺序是:1 2 3 4 ,如何正确理解出栈?
(1)入栈顺序是1 2 3 4,就是指这四个数依次入栈: 数据4入栈之前,1 2 3肯定已经入栈了; 数据3入栈之前,1 2肯定已经入栈了,而4还没入栈; 数据2入栈之前,1肯定已经入栈了,而2 3 4还没入栈; 数据1最先入栈,2 3 4还没入栈。 (2)既然入栈顺序是1 2 3 4,3 4入栈的时候,1 2 肯定已经入栈了,怎么会在后面再入栈。 (3)先拿4 3 1 2这个出栈序列来说,4最先出来,说明此时1 2 3(底到顶顺序)还都在栈中;接下来只有3能出栈,3出来后,栈中为1 2(底到顶顺序);再接下来只有2能出栈,所以如果出栈序列前两个是4 3的话,后两个只能是2 1。 再看个正确的出栈序列:2 4 3 1;2最先出来,说明它出来时,3 4还没入栈,而1已入栈且还在栈中;接着是4出来,说明此时3也在栈中(3要比4先入栈),此时栈中有1 3(底到顶顺序);然后只能3出栈,最后是1出栈。
总之,挨个看出栈序列的数据,根据入栈顺序,分析它出来时,栈中应该还有谁,而有谁还没入栈,然后分析此时可不可能是它出栈。
下面针对具体问题,编程来进行分析。
输入一个压栈序列,判断第二个序列是否为其出栈序列。
例如:入栈序列:1 2 3 4 5 6,出栈序列,4,3,5,2,6,1
算法思想,1:根据出栈序列,入栈,直到其栈顶等于出栈元素,栈s:4,3,2,1
2:栈顶与出栈序列相同出栈,否则break
根据入栈序列入栈:(左为栈顶)
栈:1 2 3 4 1 2 3 1 2 5 1 2 1 6 1 |空
出栈元素: 4 3 5 2 6 1 , 4 3 5 2 6 1 ,4 35 2 6 1,4 3 5 2 6 1 ,4 3 5 26 1 ,4 3 5 2 61 ,完
#include <iostream>
#include <stack>
using namespace std;
bool IsStackPopOrder(int *pushorder,int *poporder,int len)
{
bool isorder = false;
if(pushorder!=NULL && poporder != NULL && len > 0)
{
stack<int> s;
int *pnextpush = pushorder;
int *pnextpop = poporder;
while((pnextpop - poporder) < len)
{
while(s.empty()||s.top()!=*pnextpop)
{
if((pnextpush - pushorder)==len)
break;
s.push(*pnextpush);
pnextpush++;
}
if (s.top() == *pnextpop)
{
s.pop();
pnextpop++;
}
else
break;
}
if ((pnextpop - poporder)==len && s.empty())
isorder = true;
}
return isorder;
}
void main()
{
int array1[7] = {1,2,3,4,5,6,7};
int array2[7] = {4,3,5,6,7,1,2};
if(IsStackPopOrder(array1,array2,7))
cout<<"是"<<endl;
else
cout<<"否"<<endl;
system("pause");
}
- 【机器学习】实例详解机器学习如何解决问题
- 企业网站架构之Nginx+tomcat+memcached集群
- 企业级Docker Registry开源工具Harbor的介绍以及使用指南
- HLS Lesson8-基本操作
- Windows渗透测试工具:RedSnarf
- HLS Lesson7-复合数据类型
- matlab GUI基础3
- 【Python环境】《Python数据科学入门》试译 第一章 简介
- HLS Lesson20-实例分析
- WannaCry勒索病毒详细解读
- matlab GUI基础3
- 不使用反射的实体类方案
- matlab GUI基础1
- Why to do,What to do,Where to do 与 Lambda表达式!
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 5个好用的 CSS 函数
- java1.8中Object类源码分析
- 多线程基础(六):Object的wait方法以及notify与notifyAll的区别
- Day15:反转链表
- Day16:合并两个排序的链表
- 大厂面试爱问的「调度算法」,20 张图一举拿下
- Day17:树的子结构
- 多线程基础(七):关于HotSpot中notify方法不具备随机性的证明
- Day18:二叉树的镜像
- ksubdomain 无状态域名爆破工具
- Day19:顺时针打印矩阵
- 疑似 KimsukyAPT 组织最新攻击活动样本分析
- 查找被删除但仍然占据磁盘的文件
- WPF 获取本机所有字体拿到每个字符的宽度和高度
- WPF 自己封装 Skia 差量绘制控件