假设以S和X分别表示入栈和出栈的操作,则初态和终态均为栈空的入栈和出栈操作序列可以表示为仅由S和X组成的序列。称可以操作的序列为合法序列(例如,SXSX为合法序列,SXXS为非法序列)。试给出区分给定序列为合法序列或非法序列的一般准则,并证明,两个不同的合法(栈操作)序列(对同一输入序列)不可能得到相同的输出元素(注意:在此指的是元素实体,而不是值)序列
答:
区分给定序列为合法序列或非法序列的一般准则为:1.序列中S的个数等于X的个数。2.序列中前i个字符中‘S’的数目大于等于‘X’的数目。
证明:假设两个不同的合法序列中前n个入栈和出栈的操作相同,此时两个栈的状态是相同的,设此时的栈顶元素的都是是t。从第n+1个操作时开始不同,这样必然存在一个入栈和一个出栈的操作,设入栈的元素是s。则对于进行入栈操作的之后得到的序列应该是...st...而对于出栈得到的序列为...ts....。显然二者是不同。因此可以证明不可能得到相同的输出元素。
二、试证明:若借助栈由输入序列12...n得到的输出序列为p1,p2,...pn(它是输入序列的一个排列),则在输出序列中不可能出现这样的情形:存在着i<j<k使pj<pk<pi。
答:
利用反证法。
假设存在着i<j<k使pj<pk<pi。当i<j且pj<pi说明pi在pj前入栈,说明pj出栈后pi才能出栈。当j<k且pj<pk说明pj在pk入栈前就出栈。i<k且pk<pi说明pi在pk前入栈,说明pk出栈后pi才能出栈。由于输入序列是单调的。i<k所以入栈的pk>pi。与条件产生矛盾。所以不存在这样的情形。
三、试写一个算法,识别一次读入的一个以@为结束符的字符序列是否为形如‘序列1&序列2’模式的字符序列。其中序列1和序列2中都不含字符‘&’,且序列2是序列1的逆序列。例如,‘a+b&b+a’是属于该模式的字符序列,而‘1+3&3-1’则不是。
答:
本算法可以用栈进行实现。在遇到&之前将元素压入栈中,遇到&之后每次将得到的元素与栈顶元素进行比较如果相等将栈顶元素弹出,继续进行。如果出现不同直接返回不能。循环结束的条件为栈为空时。如果循环顺利进行完。则返回能。
该算法实现的伪代码如下:
/* 函数名称:判断是否属于该模式的字符序列 函数传入参数:需要判断的字符串 返回值:返回true代表是 返回false代表不是 */ bool isThisString(char a[]) { stack<char> s; //声明一个栈 int i = 0; for(i = 0; a[i] != '&'; ++i) { push(s, a[i]) //将a[i]元素压入栈 } i++; while(stackEmpty(s)) { GetTop(s, &e); //获得栈顶元素 if(a[i++] == e) { pop(s, &e); //删除栈顶元素 } else { return false; //如果出现不同直接判断不是 } } return true; //循环执行完毕说明匹配完毕该字符串符合要求返回是 }
算法分析:本算法的时间复杂度为O(n)。通过一次遍历进行求解。空间占用为一个栈的空间。
四、假设一个算术表达式中可以包含三种括号:圆括号“(”和“)”、方括号“[”和“]”和花括号“{”和“}”,且这三种括号可以按任意的次序嵌套使用(如:...[...{...}...[...]......(...)...)。编写判别给的那个表达式中所含括号是否正确配对出现的算法(已知表达式已存入数据元素为字符的顺序表中)
答:
本实现的判断可以通过一个栈进行实现。
当遇到左括号我们把它压入栈中。当遇到右括号时,我们先于栈顶元素进行判断看是否匹配。如果匹配则弹出栈顶元素。
如果不匹配则返回不能。循环在遍历完成时结束。如果能顺利结束循环则说明表达式中所含括号是正确配对的。
同时我们需要一个变量i来进行对传入的字符数组的遍历。
本算法实现的伪代码如下:
/* 函数名称:判断所含括号是否正确配对 函数传入参数:需要判断的字符串 返回值:返回true代表是 返回false代表不是 */ bool isThisString(char a[]) { stack<char> s; //声明一个栈 int i = 0; for(i = 0; i < a.size(); ++i) { if(a[i] == '(' || a[i] == '[' || a[i] == '{') push(s, a[i]) //将a[i]元素压入栈 else if(a[i] == ')') { if(!StackEmpty(s)) { //如果是空栈直接返回不能 return false; } GetTop(s, &e) //获得栈顶元素 if(e == '('){ pop(s, &e); //删除栈顶元素 } else { return false; } } else if(a[i] == ']') { if(!StackEmpty(s)) { //如果是空栈直接返回不能 return false; } GetTop(s, &e) //获得栈顶元素 if(e == '['){ pop(s, &e); //删除栈顶元素 } else { return false; } } else if(a[i] == '}') { if(!StackEmpty(s)) { //如果是空栈直接返回不能 return false; } GetTop(s, &e) //获得栈顶元素 if(e == '{'){ pop(s, &e); //删除栈顶元素 } else { return false; } } } return true }
算法分析:本算法的时间复杂度为O(n)。空间占用一个栈的空间。利用栈的思想顺利解决了此类问题