一、栈的基本操作
stack<typename>myStack//定义
.size()//大小
.push()//加入元素到栈中 压栈
.top()//得到栈顶元素
.pop()//弹栈
.empty()//判断栈是否为空
题目
1、零复杂度转换
描述:你被给了一系列整型数,把这个序列反转一下
输入:首先输入一个n,这个n表示这个数组的长度;第二行包含n个元素
整数的数据类型
- int 4bytes
- unsigned int 4bytes
- long long 8bytes
- unsigned long long 8bytes
代码
#include<stack>
#include<cstdio>
using namespace std;
int main() {
stack<long long>myStack;
int n;
long long num;
scanf_s("%d", &n);
for (int i = 0; i < n; i++) {
scanf_s("%lld", &num);//%lld读取long long类型的十进制数
myStack.push(num);
}
while (!myStack.empty()) {
printf("%lld ", myStack.top());
myStack.pop();
}
}
2.括号匹配问题
描述:
再某个字符串(长度不超过100)中有左括号,右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与它右边且距离最近的右括号匹配,再写一个程序,找到无法匹配的左括号和右括号,输出原来的字符串,并在下一行标出不能匹配的括号,不能匹配的左括号用“$"
标注,不能匹配的右括号用“?”标注
输入:
输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母;字符串长度不超过100
**输出:**对每组输出数据,输出两行,每一行包含原始输入字符,第二行由 '$' '?'
表示与之对于的左括号和右括号不能匹配
样例
输入:
)(rttyy())sss)(
输出:
? ?$
解题思路
采用一个栈,栈中还要记录左括号的位置信息,左括号压栈,右括号弹栈
- 不匹配的左括号:假定非法,当对应的右括号找不到时就非法
- 不匹配的右括号:栈空试图弹栈
读取字符串的操作
读取单词 char buf[100];scanf(“%s”,buf);
读取一行 char buf[1000](比题目大一些)fgets(buf,1000,stdin)【额外读一个换行】——>解决方法:string str=buf;str.pop_back();
代码
#include<cstdio>
#include<stack>
#include<string>
using namespace std;
int main() {
char buf[200];
while (fgets(buf, 200, stdin) != NULL) {
//fgets配合while实现不确定数量的多行读取
string str = buf;
str.pop_back();//str去掉额外的换行
stack<unsigned>indexStack;//存储了左圆括号的下标
string res;//保存输出的结果
for (unsigned i = 0; i < str.size(); ++i) {
if (str[i] == '(') {
indexStack.push(i);//把下标压栈
//暂且认为这个左圆括号是非法的
res.push_back('$');
}
else if (str[i] == ')') {
if (indexStack.empty()) {
res.push_back('?');
}
else {
res.push_back(' ');
res[indexStack.top()] = ' ';
indexStack.pop();
}
}
else {
res.push_back(' ');
}
}
printf("%s\n%s\n", str.c_str(), res.c_str());
}
}
3、表达式解析的问题
-
从左往右遍历表达式遇到3类运算符:
*/
±
$(虚拟的终止符号) -
后一个运算符的优先级比前面的低/相等,前面的运算符可以运算了
-
数据结构设计
stack oper 操作数
stack num 中间数据 -
从左往右遍历表达式
数字 num压栈
运算符 a高 oper压栈;b先oper弹出一个再num弹出2个,运算
代码
#include<cstdio>
#include<stack>
#include<string>
#include<map>
using namespace std;
int main() {
char buf[300];
map<char, int>priority = {
{'$',0},
{'+',1},{'-',1},
{'*',2},{'/',2}
};
while (fgets(buf, 300, stdin) != NULL) {
string expr = buf;
expr.pop_back();
if (expr == "0") {
break;
}
expr.push_back('$');
string num;//收集单独的0-9以组成一个数字 1 2 3 4-->1234
stack<double>numstack;
stack<char>operstack;
for (unsigned i = 0; i < expr.size(); ++i) {
if (expr[i] >= '0' && expr[i] <= '9') {
num.push_back(expr[i]);
}
else if (expr[i] == ' ') {
if (num!="") {
numstack.push(stod(num));//string to double
num = "";
}
}
else {
// + - * / $
if (expr[i] == '$') {
if (num != "") {
numstack.push(stod(num));
}
}
while (!operstack.empty() && priority[operstack.top()] >= priority[expr[i]]) {
//后来的运算符的优先级不高于栈顶的优先级
char oper = operstack.top();
operstack.pop();
double rhs = numstack.top();
numstack.pop();
double lhs = numstack.top();
numstack.pop();
switch (oper) {
case '+':
numstack.push(lhs + rhs);
break;
case '-':
numstack.push(lhs - rhs);
break;
case '*':
numstack.push(lhs * rhs);
break;
case '/':
numstack.push(lhs / rhs);
break;
}
}
operstack.push(expr[i]);
}
}
printf("%.2lf\n", numstack.top());
}
}