判断一个序列是否为栈的有效输出序列
栈的实际应用—判断一个序列是否为栈的有效输出序列
对于数据结构学科的初学者,栈的构建是很重要的知识,判断一个栈是否为有效输出序列是其中重要的题目。笔者整理了三种C++代码,其核心编程思想大致相同,希望能对初学者有一定帮助。
**【问题描述】**给出一个堆栈的输入序列,试判断一个序列是否能够由这个堆栈输出。如果能,则为有效输出,返回总的出栈次数,如果不能,则为无效输出,返回0。序列的输入及输出都是从左往右。
1、输入输出序列皆为正整数,可能有重复的数字
2、如果一个数字在输入序列中没有出现,但在输出序列中出现,则为无效输出。
3、如果一个数字在输入序列中出现,但在输出序列中没有出现,只要输出可以通过对输入数字进行出栈操作获取,仍然为有效输出。
**【输入形式】**第一行包含两个数字:输入序列的长度与输出序列的长度;第二行为输入序列的数字;第三行为输出序列的数字。输入数据以空格隔开。
**【输出形式】**如果是一个有效的出栈序列,则返回总的出栈次数, 否则返回0
【样例输入1】
5 5
1 2 3 4 5
4 5 3 2 1
【样例输出】5
【样例说明】可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4, push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
通过5次pop操作可以得到输出序列,因此返回5
【样例输入2】
5 5
1 2 3 4 5
4 3 5 1 2
【样例输出】0
【样例说明】1不能在2之前输出,因此返回0
**算法思想:**这个题目中涉及出栈、入栈等操作,很自然想到需要申请一个空间作为栈,进行相应的模拟操作。对于我们所要输出的序列,可以从头至尾一个个来操作,拿到最开始要输出的数字时,可以与输入序列相比较,如果恰好正确则直接输出,如果不相等则入栈,继续从前往后扫描输入序列。
举例来讲,如上述样例输入1,第一个要输出的数字是4,那么将这个数字依次与输入序列相比较,其中1、2、3与4并不相等,依次进栈,这时遇到了输入序列的4,这个4就可以输出了。下一个要输出的是5,先比较栈顶的数字3,与5并不相等,继续扫描输入序列找到5.依次类推,直到完成所有数据的输出。
算法1
这个算法利用了一个数组stack作为栈,也是笔者在拿到这个题目时做出的算法。其中代码行数比较少,思路也相对比较容易。
#include <iostream>using namespace std;bool pop(int sta[],int in[],int &curin,int &cur,int out);int main()
{int numin,numout,current=1,total=0,currentin=0; //需要设出两个表示下标的变量,分别代表栈的下标和输入序列读取到的下标cin>>numin>>numout;int *p,*q,*stack;p=new int[numin];q=new int[numout];stack=new int[numin];for(int i=0;i<numin;++i) cin>>p[i]; //读入输入序列for(int i=0;i<numout;++i) cin>>q[i]; //读入输出序列stack[0]=p[0]; //输入序列第一个数入栈for(int i=0;i<numout;++i) //从第一个输出序列的数字依次开始寻找if(pop(stack,p,currentin,current,q[i])==false) //如果没有寻找到某一个输出数字,直接输出结果0{total=0;break;}else {total+=1;currentin-=1;} //找到输出数字,那么出栈后栈的下标数字减1cout<<total;return 0;
}bool pop(int sta[],int in[],int &curin,int &cur,int out) //判断并出栈的函数
{for(;in[cur-1]!='\0';++cur) { //依次遍历栈顶和输入序列剩余的数字if(sta[curin]==out) {sta[curin]=in[cur];return true;} //找到则更替栈顶数字,返回trueelse{curin+=1;sta[curin]=in[cur];}}return false; //没找到,返回false
}
具体的思路和代码如上。
算法2
编写一个类来代替传统的STL。代码来自笔者室友。
#include<iostream>
#include<cstdio>
using namespace std;template<class elemType>
class ownstack
{private:elemType *elem;int top_p;int max_size;void doublespace();public:ownstack(int initSize=100); //栈的构造~ownstack(); //析构bool empty(); //判断栈空elemType top(); //取栈顶元素elemType pop(); //出栈void push(const elemType &x); //进栈
};template<class elemType>
ownstack<elemType>::ownstack(int initSize)
{elem=new elemType[initSize];max_size=initSize;top_p=-1;
};template<class elemType>
bool ownstack<elemType>::empty()
{return top_p==-1;
}template<class elemType>
ownstack<elemType>::~ownstack()
{delete []elem;
}template<class elemType>
elemType ownstack<elemType>::top()
{return elem[top_p];
}template<class elemType>
void ownstack<elemType>::push(const elemType &x)
{if(top_p==max_size-1) doublespace();elem[++top_p]=x;
}template<class elemType>
elemType ownstack<elemType>::pop()
{return elem[top_p--];
}template<class elemType>
void ownstack<elemType>::doublespace()
{elemType *tmp=elem;elem=new elemType[2*max_size];for(int i=0;i<max_size;++i)elem[i]=tmp[i];max_size*=2;delete []tmp;
}int judge(const int*pPush,const int *pPop,int length,int len)
{ //依次为输入、输出序列、输入序列剩余长度、输出序列剩余长度bool flag=false;if(pPush&&pPop&&length>0){const int *pNextPush=pPush;const int *pNextPop=pPop;ownstack<int>data;while(pNextPop-pPop<len) //当pop中还有数字{//当data为空,或者栈顶元素不是pop序列当前的值//则向data中pushwhile(data.empty()||data.top()!=*pNextPop){//如果push序列为空,则跳出!if(!pNextPush){break;}data.push(*pNextPush);if(pNextPush-pPush<length-1) pNextPush++; //如果输入序列还有数字,可以继续入栈else break; //pNextPush==NULL}if(data.top()!=*pNextPop) break;data.pop();pNextPop++;}if(pNextPop-pPop==len) flag=true;} //进栈数字的数目等于要输出数列的数字个数,则判断为正确if(flag) return len; //判断正确,返回输出数列的长度else return 0; //其余情况判断为错误,输出为0
}int main()
{int m=0,n=0,i;scanf("%d%d",&m,&n); //这里使用了scanf函数,效率高。cin.get();int push[m];int pop[n];for(i=0;i<m;i++)scanf("%d",&push[i]);cin.get();for(i=0;i<n;i++)scanf("%d",&pop[i]);cout<<judge(push,pop,m,n);return 0;
}
算法3
这种算法利用了STL。在进行栈的构建时,STL可以说是现成的工具。看到在本网站已经有了很好的STL构建,将相应的博主echo_xiao9的原文链接列出,希望读者也能关注一下这种较为方便实用的算法。
算法链接
总结来说,这道题目的大致思路是一样的,具体的算法实现和代码书写,笔者罗列了三种形式(其三为转载链接)。希望能对C++语言以及数据结构的初学者有所帮助。
判断一个序列是否为栈的有效输出序列相关推荐
- 《剑指offer》:[22]如何判断一个序列是否为栈的弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序. 假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压栈序列,序列4,5,3,2,1是该压栈序列 ...
- 判断一个数列是不是搜索二叉树后续遍历输出的结果
剑平面阿里被问到这个,刚开始画了下看有什么性质,乱蒙了几个都被推翻了,初始感觉就是要O(n)的,因为印象中BST的构树都可以O(nlogn)搞定.然后剑平说最后一个数肯定是根节点,一下反应过来了,就是 ...
- 判断一个序列是否是栈的输出序列(原理和源码(C语言))
[问题描述] 给出一个堆栈的输入序列,试判断一个序列是否能够由这个堆栈输出.如果能,返回总的出栈次数,如果不能,返回0.序列的输入及输出都是从左往右.(输入输出序列皆为整数且没有重复的数字,如果一个数 ...
- 栈的压入序列和弹出序列是否匹配
给两个数组pushed和poped,其中pushed为栈的压入序列,popped为栈的弹出序列,判断第一个序列是否是第一个序列的弹出序列.假设压入栈的所有数字均不相等. 分析:辅助栈判断. class ...
- 给定入栈序列,判断一个串是否为出栈序列
剑指offer22:给定入栈序列,判断一个串是否为出栈序列 public static boolean isOutStackSequence(int[] Spush, int[] Spop) {if ...
- 判断一个序列是否可由给定序列通过栈操作获得
Java代码: public class LegalSequence {public static void main(String[] args) {// System.out.println(le ...
- Java判断一个序列是否可由给定序列通过栈操作获得(ABCDEF)
Java栈操作中的代码题目你是否已经掌握了呢?接下来上题目叭~~~ 判断一个序列是否可由给定序列通过栈操作获得(ABCDEF) 这是基础题噢 学不会就打你pp呜呜呜~ 还是那句话,原创禁止转载侵权必究 ...
- 栈的push、pop序列-判断序列是否是栈的pop顺序
程序员面试题精选100题(24)-栈的push.pop序列[数据结构] 题目:输入两个整数序列.其中一个序列表示栈的 push 顺序,判断另一个序列有没有可能是对应的 pop 顺序.为了简单起见,我们 ...
- 回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。编写一个程序,使用栈判定给定的字符序列是否为回文。
内容: 回文是指正读反读均相同的字符序列,如"abba"和"abdba"均是回文,但"good"不是回文.编写一个程序,使用栈判定给定的字符 ...
最新文章
- 视频播放器——开源免费三大代表
- linux 命令终端显示-bash-4.2#解决方法
- 【转】前端进阶之路:如何高质量完成产品需求开发
- 【写作技巧】中文摘要及关键词的撰写
- PHP开发入门 | 简单的PHP新闻管理系统案例
- eclipse下载哪个版本开发java_官网上有很多版本的eclipse,下载哪个版本比较合适?...
- 苹果手机以旧换新价格表_苹果支持安卓手机以旧换新;索尼公司将更名;百度网盘推出“防误删”文件恢复服务...
- 【GEE笔记】最大类间方差法(otsu、大津法)算法实现——计算阈值、图像二值化分割
- C#程序设计--控制台程序输出上下三角形和菱形
- 一文说清:可逆与不可逆加密算法,对称与非对称加密算法-据说BCrypt比MD5要好?
- Xilinx FPGA MIPI 接口简单说明
- Spring bean解析 - refresh
- 电气工程类期刊最新数据+2019年电气工程领域的中文期刊(EI期刊+中文核期刊)
- 2018个人面试记录
- php 8bit 10bit 解码,求助:我想把10bit的MKV压制成8bitMP4
- 未来人工智能发展面临的问题
- oppo java模拟器_java动物声音模拟器
- iOS 解决scoryboard上tableview、collection view顶部有空白问题
- SpringBoot 优雅的读取yml(yml规范篇)
- 整站优化提升排名工具_百度快速排名教程【常见问题】