"Algorithm Note" learning diary-6.7 stack common usage details

6.7 Detailed explanation of common usage of stack

Codeup Contest ID:100000602

Question A: Simple calculator

Topic description
Read a non-negative integer calculation expression containing only +,-, *, /, and calculate the value of the expression.
Input The
test input contains several test cases, each test case occupies one line, each line does not exceed 200 characters, and a space is used to separate integers and operators. There are no illegal expressions. The input ends when there is only 0 in a line, and the corresponding result is not output.
Output
1 line for each test case, that is, the value of the expression, accurate to 2 decimal places.
Sample input

30 / 90 - 26 + 97 - 5 - 6 - 13 / 88 * 6 + 51 / 29 + 79 * 87 + 57 * 92
0

Sample output

12178.21

Idea
This question has already been implemented when writing a Python calculator with Tkinter, but Python uses a list, and here we use the STL stack container.

But no matter what language is used, the idea is definitely the same. Open up two stacks, one to store numbers and one to store operators, and specify the priority between operators. Here I use STL map (because I think of it When Python is implemented, a dictionary is used, and the dictionary is also corresponding to key and value, which is exactly the same as map).

Therefore, every time a number is read, it is pushed into the number stack. When an operator is encountered, it is first determined whether the operator stack is empty. If it is empty, it is directly pushed into the stack. If it is not empty, it is necessary to determine whether it is empty The priority of the operator is higher than the top of the stack. If it is larger, it is also put on the stack. If it is smaller, the operation is performed (Note that the number of operations performed here may be more than one, as long as the priority of the operator read is less than or equal to the priority of the top operator on the stack, it must be calculated all the time, otherwise an error will occur)。

The specific step of the operation is to pop two elements from the number stack pop () as a and b (a is the top number of the stack and b is the second top number), and then pop an element from the operator stack pop () as the operator, two The operator performs an operation and pushes the result of the operation back onto the digital stack. It should be noted here that for subtraction and division, it must be the second top number minus the top number (or the second top number divided by the top number), that is: b-a or b / a, otherwise it will be wrong.

In general, the code for this question may be relatively long, but the idea is still simple. If the program does not output (the card is stuck for a period of time, and then it is unexpectedly interrupted), most of the pop () operation is performed in the empty stack, so you must pay attention to writing The code must not execute pop () when the stack is not empty.
Code

#include<cstdio>
#include<string.h>
#include<algorithm>
#include<stack>
#include<map>
#include<string>
#include<iomanip>
#include<iostream>
using namespace std;
stack<double> num;//数字栈 
stack<char> op;//操作符栈
map<char, int> m;//规定优先级
int main(){
	m['+'] = 0;
	m['-'] = 0;
	m['*'] = 1;
	m['/'] = 1;
	string tmp;
	while(getline(cin, tmp)){
		if(tmp=="0") break;
		string number;
		for(int i=0;i<tmp.length();i++){
			if(tmp[i]==' '){
				if(number.length()!=0){//如果number字符串非空,说明空格之前是数字 
					double temp = stod(number);//用stod()函数把string型转成double型
					num.push(temp);//把之前的数字入栈
					number.clear();//清空字符串,准备接收下一个字符	
				}
				continue;//继续下一轮循环 
			}
			if(tmp[i]=='+'||tmp[i]=='-'||tmp[i]=='*'||tmp[i]=='/'){
				if(op.empty()==true||m[tmp[i]]>m[op.top()]){
					op.push(tmp[i]);//如果是空栈或者即将压入的操作符优先级大于栈顶操作符,则把当前的操作符入栈 
				}
				else{
					while(m[tmp[i]]<=m[op.top()]){//如果即将压入的操作符的优先级小于等于栈顶操作符的优先级
						//则进行运算,并入栈 
						double a = num.top();//数字栈顶元素 
						num.pop();
						double b = num.top();//数字栈次顶元素 
						num.pop();
						char c = op.top();
						op.pop();
						if(c=='+'){
							double temp = a+b;
							num.push(temp);//记得把算好的结果入栈 
						} 
						else if(c=='-'){
							double temp = b-a;
							num.push(temp);
						}
						else if(c=='*'){
							double temp = a*b;
							num.push(temp);
						}
						else{
							double temp = b/a;
							num.push(temp);
						}
						if(op.empty()==true) break;//如果操作符栈为空,则break,否则判断会出错 
					}
					op.push(tmp[i]);//运算完了之后压栈 
				}
				continue;
			}
			if(i==tmp.length()-1){//如果读到了字符串的尾部,就进行所有运算,直到操作符栈清空 
				number += tmp[i];//把最后一个数字字符串上 
				double temp = stod(number);//用stod()函数把string型转成double型
				num.push(temp);//把最后的数字入栈
				number.clear();//清空字符串
				while(!op.empty()){//只要操作符非空,就一直运算 
					double a = num.top();//数字栈顶元素 
					num.pop();
					double b = num.top();//数字栈次顶元素 
					num.pop();
					char c = op.top();
					op.pop();
					if(c=='+'){
						double temp = a+b;
						num.push(temp);//记得把算好的结果入栈 
					} 
					else if(c=='-'){
						double temp = b-a;
						num.push(temp);
					}
					else if(c=='*'){
						double temp = a*b;
						num.push(temp);
					}
					else{
						double temp = b/a;
						num.push(temp);
					}
				}
				break;
			}
			number += tmp[i];
		}
		double sum = num.top();
		num.pop();
		cout<<fixed<<setprecision(2)<<sum<<endl;
	}
	return 0;
}

Problem B: Problem E

For the title description
, please write a program to determine whether the brackets in the given expression match. The legal brackets in the expression are "(", ")", "[", "]", "{", ""} ", which The three brackets can be nested in any order.
Input
a plurality of expressions, the first line of input data is the number of expressions, each expression per line.
Output
For each expression, if the brackets in the expression match, "yes" is output, otherwise "no" is output.
Sample input

4
[(d+f)*{}]
[(2+3))
()}
[4(6]7)9

Sample output

yes
no
no
no

Ideas
, then this title compared to the previous question, it's much simpler, as long as the idea is to hit a left parenthesis on the stack, if you encounter a right parenthesis, then it points: ① Where at this time if the stack is empty, then the milli Directly on the stack without any doubt; ② If it does not match the left parenthesis on the top of the stack, then it is also pushed on the stack; ③ If it matches, then directly pop () off the left parenthesis on the top of the stack.
Therefore, if the stack is empty after the operation of a string, it means that the brackets match, if the stack is not empty, it means that there is no match.
Code

#include<cstdio>
#include<string.h>
#include<algorithm>
#include<string>
#include<stack>
#include<iostream>
using namespace std;
int main(){
	int n;
	while(cin>>n){
		for(int i=0;i<n;i++){
			stack<char> kuohao;//存放括号 
			string tmp;
			cin>>tmp;
			for(int j=0;j<tmp.length();j++){
				if(tmp[j]=='['||tmp[j]=='('||tmp[j]=='{'){//如果是左括号,入栈
					kuohao.push(tmp[j]); 
				}
				if(tmp[j]==']'||tmp[j]==')'||tmp[j]=='}'){//如果是右括号,处理括号匹配问题
					if(kuohao.empty()==true) kuohao.push(tmp[j]);//如果是空栈,直接入栈 
					else if(kuohao.top()=='['&&tmp[j]==']') kuohao.pop();//如果匹配,则直接出栈左括号 
					else if(kuohao.top()=='('&&tmp[j]==')') kuohao.pop();
					else if(kuohao.top()=='{'&&tmp[j]=='}') kuohao.pop();
					else kuohao.push(tmp[j]);//如果不匹配,入栈 
				}
			}
			if(kuohao.empty()==true) cout<<"yes"<<endl;//如果处理完字符串之后,栈为空,说明括号匹配
			else cout<<"no"<<endl;//否则就说明不匹配 
		}
	}
	return 0;
}

summary

In general, the problem of the stack is nothing more than to let you calculate the value of the prefix, infix, and suffix expression, or the problem of matching parentheses. Among them, the problem of matching parentheses is relatively simple, but the value of the calculation expression is more. It takes some effort. If your thoughts are a little unclear, you will encounter problems such as top () or pop () on an empty stack. At this time, you must check the code. Is it logically not rigorous? , Think about the special circumstances that may arise to improve the code. If the value can be calculated, but the answer is wrong, it means that there is a problem in the algorithm. If it cannot be checked, it is recommended to draw the sample on the paper and manually simulate it according to the idea of ​​your program, you can know what is wrong.

The feeling of doing this kind of question is very similar to the problem of handling A1 ~ A5 in PAT level B, that is, the title itself is not difficult, and the idea is easy to think, that is, the large amount of code is prone to various small problems. At this time, you must calm down and think slowly, not to be irritable, otherwise you will never be able to solve the problem.

Published 54 original articles · won 27 · views 4984

Guess you like

Origin blog.csdn.net/weixin_42257812/article/details/105340889