问题 A: 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 <string>
int main()
{
string str;
int len;
cin >> str; //把输入的字符串保存在变量str中
len = str.length() //获取输入字符串的长度
}
输出
每行逆序输出每一个字符串
样例输入
2
abcdef
aabbcc
样例输出
fedcba
ccbbaa
AC代码
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
while (n--)
{
string s;
cin >> s;
stack<char>st;
for (auto it = s.begin(); it != s.end(); it++)
st.push(*it);
while (!st.empty())
{
cout << st.top();
st.pop();
}
cout << endl;
}
return 0;
}
问题 B: DS堆栈–行编辑
题目描述
使用C++的STL堆栈对象,编写程序实现行编辑功能。行编辑功能是:当输入#字符,则执行退格操作;如果无字符可退就不操作,不会报错
本程序默认不会显示#字符,所以连续输入多个#表示连续执行多次退格操作
每输入一行字符打回车则表示字符串结束
注意:必须使用堆栈实现,而且结果必须是正序输出
输入
第一行输入一个整数t,表示有t行字符串要输入
第二行起输入一行字符串,共输入t行
输出
每行输出最终处理后的结果,如果一行输入的字符串经过处理后没有字符输出,则直接输出NULL
样例输入
4
chinaa#
sb#zb#u
##shen###zhen###
chi##a#####
样例输出
china
szu
sz
NULL
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
while (n--)
{
string s;
cin >> s;
stack<char>st;
for (auto it = s.begin(); it != s.end(); it++)
if (*it != '#')
st.push(*it);
else if (!st.empty())
st.pop();
if (st.empty())
cout << "NULL" << endl;
else {
s = "";
while (!st.empty()) {
s += st.top();
st.pop();
}
reverse(s.begin(), s.end());
cout << s << endl;
}
}
return 0;
}
问题 C: 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
提示
算法流程
1、初始化,i=0,建立堆栈,栈为空
2、输入表达式,建立指针指向表达式的头部
3、读入表达式的第i个字符
4、如果第i个字符是左括号,入栈
5、如果第i个字符是右括号,检查栈顶元素是否匹配
A.如果匹配,弹出栈顶元素
B.如果不匹配,报错退出
6、i++,指向下一个字符,是否已经表达式末尾
A. 未到末尾,重复步骤3
B. 已到达末尾
a. 堆栈为空,输出ok
b. 堆栈不为空,输出error
AC代码
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
while (n--)
{
string s;
cin >> s;
stack<char>st;
for (auto it = s.begin(); it != s.end(); it++)
{
if (*it != '(' && *it != ')' && *it != '[' && *it != ']' && *it != '{' && *it != '}')
continue;
if (st.empty())
{
st.push(*it);
continue;
}
if (*it == ')' && st.top() == '(')
{
st.pop();
continue;
}
if (*it == ']' && st.top() == '[')
{
st.pop();
continue;
}
if (*it == '}' && st.top() == '{')
{
st.pop();
continue;
}
st.push(*it);
//if (*it == ')' && st.top() != '(')
//{
// st.push(*it);
// break;
//}
//if (*it == ']' && st.top() != '[')
// st.push(*it);
//if (*it == '}' && st.top() != '{')
// st.push(*it);
}
if (st.empty())
puts("ok");
else
puts("error");
}
return 0;
}
问题 D: DS栈–Web导航
题目描述
标准Web浏览器包含在最近访问过的页面之间前后移动的功能。 实现这些功能的一种方法是使用两个堆栈来跟踪可以通过前后移动到达的页面。 在此问题中,系统会要求您实现此功能。
需要支持以下命令:
BACK:将当前页面推到前向堆栈的顶部。 从后向堆栈的顶部弹出页面,使其成为新的当前页面。 如果后向堆栈为空,则忽略该命令。
FORWARD:将当前页面推到后向堆栈的顶部。 从前向堆栈的顶部弹出页面,使其成为新的当前页面。 如果前向堆栈为空,则忽略该命令。
访问:将当前页面推送到后向堆栈的顶部,并将URL指定为新的当前页面。 清空前向堆栈。
退出:退出浏览器。
假设浏览器最初在URL http://www.acm.org/上加载网页
输入
测试数据只有一组
输入是一系列命令。 命令关键字BACK,FORWARD,VISIT和QUIT都是大写的。 URL没有空格,最多包含70个字符。 任何时候堆栈都不会超过100个元素。 输入结束由QUIT命令指示。
输出
对于除QUIT之外的每个命令,如果不忽略该命令,则在执行命令后输出当前页面的URL。否则,打印“Ignored”。 每个命令的输出应该在对应行上输出。 QUIT命令无输出。
样例输入
VISIT http://acm.ashland.edu/
VISIT http://acm.baylor.edu/acmicpc/
BACK
BACK
BACK
FORWARD
VISIT http://www.ibm.com/
BACK
BACK
FORWARD
FORWARD
FORWARD
QUIT
样例输出
http://acm.ashland.edu/
http://acm.baylor.edu/acmicpc/
http://acm.ashland.edu/
http://www.acm.org/
Ignored
http://acm.ashland.edu/
http://www.ibm.com/
http://acm.ashland.edu/
http://www.acm.org/
http://acm.ashland.edu/
http://www.ibm.com/
Ignored
AC代码
#include<bits/stdc++.h>
using namespace std;
class VisitWed {
stack<string>back_URL;
stack<string>forward_URL;
string current_URL;
public:
VisitWed() { current_URL = "http://www.acm.org/"; }
void back(){
if (back_URL.empty())
{
puts("Ignored");
return;
}
forward_URL.push(current_URL);
current_URL = back_URL.top();
back_URL.pop();
cout << current_URL << endl;
}
void forward(){
if (forward_URL.empty())
{
puts("Ignored");
return;
}
back_URL.push(current_URL);
current_URL = forward_URL.top();
forward_URL.pop();
cout << current_URL << endl;
}
void visit() {
back_URL.push(current_URL);
cin >> current_URL;
cout << current_URL << endl;
while (!forward_URL.empty())
forward_URL.pop();
}
};
int main() {
VisitWed t;
while (true)
{
string s;
cin >> s;
if (s == "VISIT")
t.visit();
else if (s == "BACK")
t.back();
else if (s == "FORWARD")
t.forward();
else if ("QUIT" == s)
break;
}
return 0;
}
问题 E: DS堆栈–表达式计算
题目描述
计算一个表达式的运算结果
使用C++自带stack堆栈对象来实现
参考课本的伪代码,把伪代码改造成可运行的代码
课本即严蔚敏老师编著的《数据结构》,理解本题需要理解一些编译原理的知识——曹无悔注。
例如
-
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 <iostream>
#include<iomanip>
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
AC代码
#include<bits/stdc++.h>
using namespace std;
class Expression {
string formula;
const char prior[7][7] =
{
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=',' '},
{'>','>','>','>',' ','>','>'},
{'<','<','<','<','<',' ','='},
};
const char OPERATOR[7] = { '+','-','*','/','(',')','#' };
public:
Expression() { cin >> formula; }
double getValue(double left, double right, char oper)
{
switch (oper)
{
case '+':return left + right;
case '-':return left - right;
case '*':return left * right;
case '/':return left / right;
}
return 0;
}
double getValue() {
string s = "#" + formula;
stack<double>_number;
stack<char>_operator;
while (!s.empty())
{
if (isalnum(s[0])||s[0]=='.') {
string temp_num;
while (isalnum(s[0]) || s[0] == '.')
{
temp_num += s[0];
s.erase(0, 1);
}
_number.push(atof(temp_num.c_str()));
}
else if (_operator.empty()) {
_operator.push(s[0]);
s.erase(0, 1);
}
else {
char theta1, theta2;
for (int i = 0; i < 7; i++)
if (OPERATOR[i] == _operator.top())
{
theta1 = i;
break;
}
for (int i = 0; i < 7; i++)
if (OPERATOR[i] == s[0])
{
theta2 = i;
break;
}
if (prior[theta1][theta2] == '<')
{
_operator.push(s[0]);
s.erase(0, 1);
}
else if (prior[theta1][theta2] == '>')
{
double right = _number.top();
_number.pop();
double left = _number.top();
_number.pop();
_number.push(getValue(left, right, _operator.top()));
_operator.pop();
}
else {
s.erase(0, 1);
_operator.pop();
}
}
}
return _number.top();
}
};
int main() {
int n;
cin >> n;
while (n--)
{
Expression e;
cout << fixed << setprecision(4) << e.getValue() << endl;
}
return 0;
}
问题 F: 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
AC代码
#include<bits/stdc++.h>
using namespace std;
struct Point {
bool flag;
int x, y;
void set(int i, int j, bool s = 1) { x = i; y = j; flag = s; }
};
class Maze {
Point** maze;
int length;
public:
Maze() {
cin >> length;
length += 2;
maze = new Point * [length];
for (int i = 0; i < length; i++)
maze[i] = new Point[length];
for (int i = 0; i < length; i++)
for (int j = 0; j < length; j++)
{
if (i == 0 || j == 0 || i == length - 1 || j == length - 1)
{
maze[i][j].set(i, j, 1);
}
else
{
maze[i][j].set(i, j);
cin >> maze[i][j].flag;
}
}
}
void go_maze() {
bool flag = 0;
int current_x = 1, current_y = 1;
stack<Point>path;
path.push(maze[current_x][current_y]);
while (!path.empty())
{
maze[current_x][current_y].flag = 1;
if (maze[current_x][current_y + 1].flag == 0) {
current_y += 1;
path.push(maze[current_x][current_y]);
}
else if (maze[current_x + 1][current_y].flag == 0) {
current_x += 1;
path.push(maze[current_x][current_y]);
}
else if (maze[current_x][current_y - 1].flag == 0) {
current_y -= 1;
path.push(maze[current_x][current_y]);
}
else if (maze[current_x - 1][current_y].flag == 0) {
current_x -= 1;
path.push(maze[current_x][current_y]);
}
else {
path.pop();
if (!path.empty())
{
Point temp = path.top();
current_x = temp.x;
current_y = temp.y;
}
}
if (current_x == length - 2 && current_y == length - 2) {
flag = 1;
break;
}
}
if (flag) {
int cnt = 0;
stack<Point>path1;
while (!path.empty())
{
path1.push(path.top());
path.pop();
}
while (!path1.empty())
{
Point current_point = path1.top();
path1.pop();
printf("[%d,%d]--", current_point.x - 1, current_point.y - 1);
cnt += 1;
if (cnt == 4)
{
cnt %= 4;
putchar('\n');
}
}
puts("END");
}
else puts("no path");
}
~Maze()
{
for (int i = 0; i < length; i++)
delete[]maze[i];
delete[]maze;
}
};
int main() {
int n;
cin >> n;
while (n--)
{
Maze test;
test.go_maze();
}
return 0;
}