一、实验作业相关要求
实验四 栈和队列
1、实验目的与要求
1)熟悉栈、队列的类型定义和基本操作;
2)灵活应用栈、队列解决具体应用问题。
2、实验内容
1.判断回文数,回文是指正读反读均相同的字符序列,如“1221”和“12321”均是回文,但“1234”不是回文。
请写一个算法判定给定的字符向量是否为回文。
(提示:将一半字符入栈)。
2.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。
假设压入栈的所有数字均不相等。
例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
示例 1:
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
示例 2:
输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。
提示:
0 <= pushed.length == popped.length <= 1000
0 <= pushed[i], popped[i] < 1000
pushed 是 popped 的排列
3、实验结果
1)请将调试通过的主要源代码、输出结果粘贴在下面
2)简述算法步骤,格式如下:
S1:
S2:
S3:
3)请分析算法的时间复杂度。
二、源代码
将其写在同一项目
主函数源代码(submit.cpp)如下:
#include <iostream>
#include<string>
#include<vector>
#include "SeqStack.h"
#include "Solution.h"
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
string inp;
cout<<"请输入字符串判断是否回文:\n";
cin>>inp;
cout<<"此字符串"<<(Solution().judgePalindrome(inp)==1?"是":"不是")<<"回文字符串!\n"<<endl;
cout<<"请输入整数序列的长度:\n";
int length;
cin>>length;
vector<int> pushed(length);
vector<int> popped(length);
cout<<"请输入入栈序列:\n";
for(int i=0;i<length;i++){
cin>>pushed[i];
}
cout<<"请输入可能的出栈序列:\n";
for(int i=0;i<length;i++){
cin>>popped[i];
}
cout<<"第二个序列"<<(Solution().judgePoppedByPushed(pushed,popped)==1?"是":"不是")<<"该栈的弹出顺序!\n"<<endl;
return 0;
}
定义栈的头文件(SeqStack.h)如下:
#include<iostream>
using namespace std;
template<class T>
class Stack{
public:
Stack(){};
virtual void Push(T x) = 0;
virtual bool Pop() = 0;
virtual T Top() const = 0;
virtual bool Empty() const = 0;
virtual bool Full() const = 0;
virtual int Size() const = 0;
};
template<class T>
class SeqStack: public Stack<T>{
public:
SeqStack(int size = 50);
~SeqStack() {delete []elems;};
void Push(T x);
bool Pop();
T Top()const;
bool Empty()const {return top == -1;};
bool Full()const {return top == maxsize-1;};
int Size()const {return top+1;};
void makeEmpty() {top = -1;}
private:
T* elems;
int top;
int maxsize;
void overflow()const;
};
template<class T>
SeqStack<T>::SeqStack(int size){
if(size <= 0){
this->overflow();
}
elems = new T[size];
if(!elems){
this->overflow();
}
maxsize = size;
top = -1;
}
template<class T>
void SeqStack<T>::Push(T x){
if(this->Full()){
this->overflow();
}
elems[++top] = x;
}
template<class T>
bool SeqStack<T>::Pop(){
if(this->Empty()){
return false;
}
top--;
return true;
}
template<class T>
T SeqStack<T>::Top()const{
if(this->Empty()){
this->overflow();
}
return elems[top];
}
template<class T>
void SeqStack<T>::overflow()const{
cerr<<"overflow!!!"<<endl;
exit(-1);
}
方法类的头文件(Solution.h)如下:
#include<iostream>
//#include "SeqStack.h"
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
class Solution{
public:
bool judgePalindrome(string inp);
bool judgePoppedByPushed(vector<int>& pushed,vector<int>& popped);
};
bool Solution::judgePalindrome(string inp){
if(inp.size()<=1){
return true;
}
Stack<char>* store=new SeqStack<char>(inp.size()/2);
for(int i=0;i<=inp.size()-1;i++){
if(inp.size()%2==0){
if(i<=inp.size()/2-1){
store->Push(inp[i]);
}else{
if(store->Top()!=inp[i]){
return false;
}else{
store->Pop();
}
}
}else{
if(i<inp.size()/2){
store->Push(inp[i]);
}else if(i==inp.size()/2){
continue;
}else{
if(store->Top()!=inp[i]){
return false;
}else{
store->Pop();
}
}
}
}
delete store;
return true;
}
bool Solution::judgePoppedByPushed(vector<int>& pushed,vector<int>& popped){
if(pushed.size()<=1){
return true;
}
Stack<int>* store=new SeqStack<int>(pushed.size());
store->Push(pushed[0]);
int i=1,j=0;
while(true){
if(!store->Empty()&&j<popped.size()&&store->Top()==popped[j]){
store->Pop();
j++;
}else if(i<pushed.size()){
store->Push(pushed[i]);
i++;
}else{
if(!store->Empty()){
return false;
}else{
break;
}
}
}
delete store;
return true;
}
执行效果:
三、作业提交的文档内容
1)请将调试通过的主要源代码粘贴在下面
如上
2)简述算法步骤:
第一题
S1:判断字符串是奇数长度还是偶数长度,确认前一半的长度
S2:遍历字符串,前一半字符逐个入栈,后一半字符与逐个出栈的元素进行比对,若字符串回文,将是一一相等的
S3:比对过程中一旦碰到不相等的情况,中止返回flase;而若正常结束循环,返回true
第二题
S1:我们先假设弹出序列可以得到,模拟一遍入栈、弹出的过程,定义两个指针 i 与 j ,分别指向两序列,定义一个栈来存储。
S2:在一层循环中,每次进行一系列判断,若栈中存在元素且 j 指向的元素正好等于栈顶元素,便弹出栈顶,指针 j 向后移动一次;若栈为空或栈顶元素不等于 j 所指向元素,便将 i 指向的元素入栈,指针 i 向后移动;而若入栈序列已然遍历完且无法继续按照出栈序列弹出栈顶,循环结束。
S3:此时判断栈是否为空,若栈非空,则表明栈无法按照出栈序列弹出所有元素,返回false;若栈空,则表明栈按照出栈序列弹出所有元素,返回true。
3)请分析算法的时间复杂度。
第一题
只需循环一遍,入栈前一半,出栈后一半,所以时间复杂度为O(n)
第二题
一层循环的最坏情况下,入栈n次,出栈n次,总共遍历2n次,此时正是能按弹出序列弹出的情况;而其余的情况下,未能出栈n次,遍历次数小于2n次。
综上,时间复杂度为O(n)