数据结构 堆栈
Posted 上山打老虎D
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构 堆栈相关的知识,希望对你有一定的参考价值。
链表
1. DS堆栈–逆序输出(STL栈使用)
题目描述
C++中已经自带堆栈对象stack,无需编写堆栈操作的具体实现代码。
本题目主要帮助大家熟悉stack对象的使用,然后实现字符串的逆序输出
输入一个字符串,按字符按输入顺序压入堆栈,然后根据堆栈后进先出的特点,做逆序输出
stack类使用的参考代码
n包含头文件:#include
n创建一个堆栈对象s(注意stack是模板类):stack s;//堆栈的数据类型是字符型
n把一个字符ct压入堆栈:s.push(ct);
n把栈顶元素弹出:s.pop();
n获取栈顶元素,放入变量c2:c2 =s.top();
n判断堆栈是否空:s.empty(),如果为空则函数返回true,如果不空则返回false
输入
第一行输入t,表示有t个测试实例
第二起,每一行输入一个字符串,注意字符串不要包含空格
字符串的输入可以考虑一下代码:
#include
int main()
{ string str;
Int len;
cin>>str; //把输入的字符串保存在变量str中
len = str.length() //获取输入字符串的长度
}
输出
每行逆序输出每一个字符串
输入样例
2
abcdef
aabbcc
输出样例
fedcba
ccbbaa
参考代码
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
string str;
int len;
cin>>str;
len = str.size();
stack<char> s;
for(int i=0;i<len;i++)
{
char ct=str[i];
s.push(ct);
}
for(int i=0;i<len;i++)
{
str[i]=s.top();
s.pop();
}
cout<<str<<endl;
}
}
2. DS堆栈–行编辑
题目描述
使用C++的STL堆栈对象,编写程序实现行编辑功能。行编辑功能是:当输入#字符,则执行退格操作;如果无字符可退就不操作,不会报错
本程序默认不会显示#字符,所以连续输入多个#表示连续执行多次退格操作
每输入一行字符打回车则表示字符串结束
注意:必须使用堆栈实现,而且结果必须是正序输出
输入
第一行输入一个整数t,表示有t行字符串要输入
第二行起输入一行字符串,共输入t行
输出
每行输出最终处理后的结果,如果一行输入的字符串经过处理后没有字符输出,则直接输出NULL
输入样例
4
chinaa#
sb#zb#u
##shen###zhen###
chi##a#####
输出样例
china
szu
sz
NULL
参考代码
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
string str;
int len;
cin>>str;
len = str.size();
stack<char> s;
for(int i = 0;i<len;i++)
{
if(str[i] == '#')
{
if(!s.empty())
s.pop();
}
else
{
s.push(str[i]);
//cout<<str[i];
}
}
if(s.empty())
{
cout<<"NULL"<<endl;
continue;
}
str.clear();
len=0;
while(!s.empty())
{
str+=s.top();
len++;
s.pop();
}
//cout<<len<<endl;
for(int i=0;i<len;i++)
{
char ct=str[i];
s.push(ct);
}
for(int i=0;i<len;i++)
{
str[i]=s.top();
s.pop();
}
cout<<str<<endl;
}
}
3. DS堆栈–括号匹配
题目描述
处理表达式过程中需要对括号匹配进行检验,括号匹配包括三种:“(”和“)”,“[”和“]”,“{”和“}”。例如表达式中包含括号如下:
( | ) | [ | ( | ) | ( | [ | ] | ) | ] | { | } |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
从上例可以看出第1和第2个括号匹配,第3和第10个括号匹配,4和5匹配,6和9匹配,7和8匹配,11和12匹配。从中可以看到括号嵌套的的情况是比较复杂的,使用堆栈可以很方便的处理这种括号匹配检验,可以遵循以下规则:
1、 当接收第1个左括号,表示新的一组匹配检查开始;随后如果连续接收到左括号,则不断进堆栈。
2、 当接受第1个右括号,则和最新进栈的左括号进行匹配,表示嵌套中1组括号已经匹配消除
3、 若到最后,括号不能完全匹配,则说明输入的表达式有错
建议使用C++自带的stack对象来实现
stack类使用的参考代码
n包含头文件:#include
n创建一个堆栈对象s(注意stack是模板类):stack s;//堆栈的数据类型是字符型
n把一个字符ct压入堆栈:s.push(ct);
n把栈顶元素弹出:s.pop();
n获取栈顶元素,放入变量c2:c2 =s.top();
n判断堆栈是否空:s.empty(),如果为空则函数返回true,如果不空则返回false
输入
第一行输入一个t,表示下面将有t组测试数据。接下来的t行的每行输入一个表达式,表达式只考虑英文半角状态输入,无需考虑中文全角输入
输出
对于每一行的表达式,检查括号是否匹配,匹配则输入ok,不匹配则输出error
输入样例
2
(a+b)[45+(-6)]
[58]/{(a+b)-6
输出样例
ok
error
参考代码
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
stack<char> s;
string str;
cin>>str;
for(int i=0;i<str.size();i++)
{
if(str[i]=='('||str[i]=='{'||str[i]=='[')
s.push(str[i]);
else
{
if(str[i]==')')
{
if(s.top()=='(')
s.pop();
}
else if(str[i]=='}')
{
if(s.top()=='{')
s.pop();
}
else if(str[i]==']')
{
if(s.top()=='[')
s.pop();
}
}
}
if(s.empty())
cout<<"ok"<<endl;
else
cout<<"error"<<endl;
}
}
4. DS堆栈–迷宫求解
题目描述
给出一个N*N的迷宫矩阵示意图,从起点[0,0]出发,寻找路径到达终点[N-1, N-1]
要求使用堆栈对象来实现,具体算法参考课本3.2.4节51页
输入
第一行输入t,表示有t个迷宫
第二行输入n,表示第一个迷宫有n行n列
第三行起,输入迷宫每一行的每个方格的状态,0表示可通过,1表示不可通过
输入n行
以此类推输入下一个迷宫
输出
逐个输出迷宫的路径
如果迷宫不存在路径,则输出no path并回车
如果迷宫存在路径,将路径中每个方格的x和y坐标输出,从起点到终点,每输出四个方格就换行,最终以单词END结尾,具体格式参考示范数据
输出的代码参考如下:
//path是保存路径的堆栈,堆栈中每个元素都包含x坐标和y坐标,用属性xp和yp表示
//path1是一个临时堆栈,把path的数据倒序输出到path1,使得路径按正序输出
if (!path.empty())//找到路径
{//…若干代码,实现path的数据导入path1
i=0; //以下是输出路径的代码
while (!path1.empty())
{cpos = path1.top();
if ( (++i)%4 == 0 )
cout<<’[’<<cpos.xp<<’,’<<cpos.yp<<’]’<<"–"<<endl;
else
cout<<’[’<<cpos.xp<<’,’<<cpos.yp<<’]’<<"–";
path1.pop();
}
cout<<“END”<<endl;
}
else
cout<<“no path”<<endl; //找不到路径输出no path
输入样例
2
8
0 0 0 1 1 1 1 1
1 0 0 0 1 0 0 1
1 0 0 0 1 0 0 0
1 1 0 0 0 0 0 1
0 0 1 1 0 1 1 0
0 0 0 0 0 0 1 1
1 1 1 1 1 0 0 1
0 0 0 0 1 0 0 0
7
0 0 0 1 1 1 1
1 0 0 1 0 0 1
1 0 0 1 0 0 0
1 1 0 0 0 0 1
0 0 1 1 0 1 0
1 0 0 0 0 1 0
0 0 0 0 1 1 0
输出样例
[0,0]–[0,1]–[0,2]–[1,2]–
[1,3]–[2,3]–[3,3]–[3,4]–
[4,4]–[5,4]–[5,5]–[6,5]–
[6,6]–[7,6]–[7,7]–END
no path
参考代码
#include<iostream>
#include<stack>
#include<string>
using namespace std;
class pos
{
public:
int xp,yp;
int p;
int dir;
void set(int a,int b,int c)
{
xp=a,yp=b,p=c;
}
};
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
stack<pos> s;
pos a[n+2][n+2];
pos b,temp;
for(int i=0;i<n+2;i++)
for(int j=0;j<n+2;j++)
a[i][j].set(i,j,1);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int k;
cin>>k;
a[i][j].set(i,j,k);
}
s.push(a[1][1]);
int x=1,y=1;
while(!s.empty())
{
b=s.top();
s.pop();
if(s.empty())
temp=b;
else
temp=s.top();
s.push(b);
if(x==n&&y==n)
{
break;
}
if(a[x+1][y].p==0&&x+1!=temp.xp)
{
x++;
a[x][y].p=1;
s.push(a[x][y]);
}
else if(a[x][y+1].p==0&&y+1!=temp.yp)
{
y++;
a[x][y].p=1;
s.push(a[x][y]);
}
else if(a[x-1][y].p==0&&x-1!=temp.xp)
{
x--;
a[x][y].p=1;
s.push(a[x][y]);
}
else if(a[x][y-1].p==0&&y-1!=temp.yp)
{
y--;
a[x][y].p=1;
s.push(a[x][y]);
}
else
{
a[x][y].p=1;
s.pop();
}
}
if(!s.empty())
{
stack<pos> ans;
while(!s.empty())
{
ans.push(s.top());
s.pop();
}
int ii=0;
while(!ans.empty())
{
temp=ans.top();
cout<<'['<<temp.xp-1<<','<<temp.yp-1<<']'<<"--";
if((++ii)%4==0)
cout<<endl;
ans.pop();
}
cout<<"END"<<endl;
}
else
{
cout<<"no path"<<endl;
}
}
}
5. DS堆栈–表达式计算
题目描述
计算一个表达式的运算结果
使用C++自带stack堆栈对象来实现
参考课本的算法伪代码P53-54
例如
-
Push (OPTR, ‘#’);表示把字符#压入堆栈OPTR中,转换成c++代码就是OPTR.push(’#’);
-
Pop(OPND, a); 表示弹出栈OPND的栈顶元素,并把栈顶元素放入变量a中。因此改成c++代码是两个操作:
a = OPND.top();
OPND.pop(); -
a = GetTop(OPND)表示获取栈OPND的栈顶元素,转成c++代码就是: a = OPND.top();
输入
第一个输入t,表示有t个实例
第二行起,每行输入一个表达式,每个表达式末尾带#表示结束
输入t行
输出
每行输出一个表达式的计算结果,计算结果用浮点数(含4位小数)的格式表示
用cout控制浮点数输出的小数位数,需要增加一个库文件,并使用fixed和setprecision函数,代码如下:
#include
#include
using namespace std;
int main()
{ double temp = 12.34
cout<<fixed<<setprecision(4)<<temp<<endl;
}
输出结果为12.3400
输入样例
2
1+2*3-4/5#
(66+(((11+22)*2-33)/3+6)*2)-45.6789#
输出样例
6.2000
54.3211
参考代码
#include <iostream>
#include <stack>
#include <string>
#include <cstdlib>
#include <iomanip>
#include <cstring>
using namespace std;
#define ok 0
#define error -1
#define overflow -1
#define opsetsize 7
typedef int Status;
char Prior[7][7] = {
'>',
'>',
'<',
'<',
'<',
'>',
'>',
'>',
'>',
'<',
'<',
'<',
'>',
'>',
'>',
'>',
'>',
'>',
'<',
'>',
'>',
'>',
'>',
'>',
'>',
'<',
'>',
'>',
'<',
'<',
'<',
'<',
'<',
'=',
' ',
'>',
'>',
'>',
'>',
' ',
'>',
'>',
'<',
'<',
'<',
'<',
'<',
' ',
'=',
};
float Operate(float a, unsigned char theta, float b)
{
if (theta == '+')
return a + b;
else if (theta == '-')
return a - b;
else if (theta == '*')
return a * b;
else if (theta == '/')
return a / b;
}
char OPSET[opsetsize] = {'+', '-', '*', '/', '(', ')', '#'};
Status In(char Test, char *TestOp)
{
for (int i = 0; i < opsetsize在后台堆栈中多次防止相同的片段