郁闷的C小加(一)
描述
我们熟悉的表达式如a+b、a+b*(c+d)等都属于中缀表达式。中缀表达式就是(对于双目运算符来说)操作符在两个操作数中间:num1 operand num2。同理,后缀表达式就是操作符在两个操作数之后:num1 num2 operand。ACM队的“C小加”正在郁闷怎样把一个中缀表达式转换为后缀表达式,现在请你设计一个程序,帮助C小加把中缀表达式转换成后缀表达式。为简化问题,操作数均为个位数,操作符只有+-*/ 和小括号。
输入
第一行输入T,表示有T组测试数据(T<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个表达式。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。并且输入数据不会出现不匹配现象。
输出
每组输出都单独成行,输出转换的后缀表达式。
样例输入
2
1+2
(1+2)*3+4*5
样例输出
12+
12+3*45*+
分析:
将中缀表达式转化成后缀表达式的方法的算法描述如下:
2. If 当前遍历到的字符 ch 是操作数,则打印
3. Else If 当前遍历的ch是 ‘(‘, 入栈
4. Else If 当前遍历的ch是 ‘)’, 不断弹出栈顶元素,直到栈为空或弹出’(‘
5. Else,
…….5.1 If 上一个操作符的优先级比当前操作符ch的优先级小,或栈是空的就入栈。
……. 5.2 Else, 不断弹出栈顶的操作符,并打印,直到栈为空或当前的操作符ch的优先级大于栈顶的操作符。将当前操作符入栈。
6. 重复2-6步,直到遍历完成
7. 弹出并打印栈中的剩余的操作符
Java代码:
import java.util.Scanner;
import java.util.Stack;
public class Main {
//判断字符ch是否是一个操作数
static boolean isOperand(char ch) {
return (ch >= '0' && ch <= '9');
}
public static void infixToPostfix(String exp) {
char expArr[] = exp.toCharArray();
Stack<Character> stack = new Stack<Character>();
//1. 从左向右扫遍历达式
for(int i=0; i<expArr.length; i++){
char ch = expArr[i];
//2. If 当前遍历到的字符 ch 是操作数,则打印
if( isOperand(ch) ){
System.out.print(ch);
}
//Else If 当前遍历的ch是 ‘(‘, 入栈
else if(ch == '('){
stack.push(ch);
}
//Else If 当前遍历的ch是 ‘)’, 不断弹出栈顶元素,直到栈为空或弹出'('
else if(ch == ')'){
char top = stack.pop();
while(top != '('){
System.out.print(top);
top = stack.pop();
}
}
else{
int r = getRank(ch);
//5.1 If 上一个操作符的优先级比操作符ch的优先级小,或栈是空的就入栈。
if(stack.isEmpty() || r > getRank(stack.peek())){
stack.push(ch);
}else{
//5.2 Else, 不断弹出栈顶的操作符,并打印,直到栈为空或当前的操作符ch的优先级大于栈顶的操作符。将当前操作符入栈。
while( !stack.isEmpty() && r <=getRank(stack.peek()) )
System.out.print(stack.pop());
stack.push(ch);
}
}
}
// 7. 弹出并打印栈中的剩余的操作符
while(!stack.isEmpty()) System.out.print(stack.pop());
System.out.println();
}
static int getRank(char c) {
switch (c) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
}
return -1;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String p = in.nextLine();
int t = Integer.parseInt(p);
for (int i = 0; i < t; i++){
String str = in.nextLine();
infixToPostfix(str);
}
}
}
C++代码:
import java.util.Scanner;
import java.util.Stack;
public class Main {
//判断字符ch是否是一个操作数
static boolean isOperand(char ch) {
return (ch >= '0' && ch <= '9');
}
public static void infixToPostfix(String exp) {
char expArr[] = exp.toCharArray();
Stack<Character> stack = new Stack<Character>();
//1. 从左向右扫遍历达式
for(int i=0; i<expArr.length; i++){
char ch = expArr[i];
//2. If 当前遍历到的字符 ch 是操作数,则打印
if( isOperand(ch) ){
System.out.print(ch);
}
//Else If 当前遍历的ch是 ‘(‘, 入栈
else if(ch == '('){
stack.push(ch);
}
//Else If 当前遍历的ch是 ‘)’, 不断弹出栈顶元素,直到栈为空或弹出'('
else if(ch == ')'){
char top = stack.pop();
while(top != '('){
System.out.print(top);
top = stack.pop();
}
}
else{
int r = getRank(ch);
//5.1 If 上一个操作符的优先级比操作符ch的优先级小,或栈是空的就入栈。
if(stack.isEmpty() || r > getRank(stack.peek())){
stack.push(ch);
}else{
//5.2 Else, 不断弹出栈顶的操作符,并打印,直到栈为空或当前的操作符ch的优先级大于栈顶的操作符。将当前操作符入栈。
while( !stack.isEmpty() && r <=getRank(stack.peek()) )
System.out.print(stack.pop());
stack.push(ch);
}
}
}
// 7. 弹出并打印栈中的剩余的操作符
while(!stack.isEmpty()) System.out.print(stack.pop());
System.out.println();
}
static int getRank(char c) {
switch (c) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
}
return -1;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String p = in.nextLine();
int t = Integer.parseInt(p);
for (int i = 0; i < t; i++){
String str = in.nextLine();
infixToPostfix(str);
}
}
}
C++代码:
#include <iostream>
#include <cstdio>
#include <stack>
#include <cstring>
using namespace std;
const int maxn = 1000 + 10;
stack<char> st;
int main()
{
int t;
char str[maxn];
cin >> t;
while (t--){
scanf("%s", &str[1]);
str[0] = '(';
int len = strlen(str);
str[len] = ')';
len++;
for (int i = 0; i < len; i++){
if(isdigit(str[i]))
cout << str[i];
else if (str[i] == '(')
st.push(str[i]);
else if (str[i] == ')'){
while (st.top() != '('){
cout << st.top();
st.pop();
}
st.pop();
}
else if (str[i] == '+' || str[i] == '-'){
while (st.top() != '('){
cout << st.top();
st.pop();
}
st.push(str[i]);
}
else{
if (st.top() == '*' || st.top() == '/'){
cout << st.top();
st.pop();
}
st.push(str[i]);
}
}
cout << endl;
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <stack>
#include <cstring>
using namespace std;
const int maxn = 1000 + 10;
stack<char> st;
int main()
{
int t;
char str[maxn];
cin >> t;
while (t--){
scanf("%s", &str[1]);
str[0] = '(';
int len = strlen(str);
str[len] = ')';
len++;
for (int i = 0; i < len; i++){
if(isdigit(str[i]))
cout << str[i];
else if (str[i] == '(')
st.push(str[i]);
else if (str[i] == ')'){
while (st.top() != '('){
cout << st.top();
st.pop();
}
st.pop();
}
else if (str[i] == '+' || str[i] == '-'){
while (st.top() != '('){
cout << st.top();
st.pop();
}
st.push(str[i]);
}
else{
if (st.top() == '*' || st.top() == '/'){
cout << st.top();
st.pop();
}
st.push(str[i]);
}
}
cout << endl;
}
return 0;
}