目次
まず、逆ポーランド語の表現を理解する必要があります。
中置式を後置式に変換する
いわゆる中置式は、実際には通常私たちが書くものです(例: ;)、そしてその接尾辞式 (逆ポーランド式とも呼ばれます)は;です。
後置式: 括弧が含まれていないことを意味し、演算子は2 つのオペランドの後に配置されます。すべての計算は、演算子が出現する順序で左から右に厳密に実行されます(演算子の優先規則は考慮されなくなりました)。 。
プログラムを使用して4 つの混合演算を実行する場合、最も重要なことは、入力の中置式を後置式に変換することです。
まず、演算子が足し算、引き算、掛け算、割り算、括弧だけだと仮定すると、プログラムが複雑になりすぎます(実際には書けません(泣))。
図
コード実装プロセス:
まず、戻り値が動的文字列配列(後で計算しやすくするため) であり、仮パラメータが文字列型であるメソッドを作成します(入力値には数値だけでなく演算子も含まれるため)。ここではスタックを使用するので、スタックも定義します。
public ArrayList<String> midChangeEng(String str) {
//这里用动态数组就不用担心不够用
ArrayList<String> ret = new ArrayList<String>();
Stack<Character> stack = new Stack<>();
}
この時点で、入力された文字が演算子であるかどうかを判断する 新しいメソッドを作成します。
public boolean isOperator(char s) {
if (s == '+' || s == '-' || s == '*' || s == '/' || s == '(' || s == ')') {
return true;
}
return false;
}
次に、ASCII コード内の演算子の位置を使用して、優先順位を表す配列を作成します。
int[] able = {1,0,0,0,0,1};//分别代表 * + (null) - (null) / 的优先级
文字列をループする
//遍历字符串
for (int i = 0; i < str.length(); i++) {
char a = str.charAt(i);
String tmp = "";//用来暂时存储出栈的数字
if (isOperator(a)) {
//是操作数
}else{
//如果是数字就放到ret中
}
}
return ret;
オペランドの操作については、このコードには繰り返されるコードが多すぎるため、メソッドにカプセル化できます。
if (isOperator(a)) {
//是操作数
switch (a) {
case '+'://判断如果优先级不大于栈顶的元素那么就先出栈在入栈
if(!stack.isEmpty()) {//出栈
while(!stack.isEmpty() && stack.peek() != '(' && able[(int)stack.peek() - 42] >= able[(int)a-42]) {
String b = "";
b += stack.pop();
ret.add(b);
}
}
stack.push(a);
break;
case '-':
if(!stack.isEmpty()) {//出栈
while(!stack.isEmpty() && stack.peek() != '(' && able[(int)stack.peek() - 42] >= able[(int)a-42]) {
String b = "";
b += stack.pop();
ret.add(b);
}
}
stack.push(a);
break;
case '*':
if(!stack.isEmpty()) {//出栈
while(!stack.isEmpty() && stack.peek() != '(' && able[(int)stack.peek() - 42] >= able[(int)a-42]) {
String b = "";
b += stack.pop();
ret.add(b);
}
}
stack.push(a);
break;
case '/':
if(!stack.isEmpty()) {//出栈
while(!stack.isEmpty() && stack.peek() != '(' && able[(int)stack.peek() - 42] >= able[(int)a-42]) {
String b = "";
b += stack.pop();
ret.add(b);
}
}
stack.push(a);
break;
case '(':
stack.push(a);
break;
case ')':
while(!stack.isEmpty() && stack.peek() != '(') {
String b = "";
b += stack.pop();
ret.add(b);
}
stack.pop();//删除‘(’
break;
}
}
数値の場合は次のようにします
else{
//如果是数字就放到ret中
String tmp = "";
while(i < str.length() && !isOperator(str.charAt(i))) {//数字有可能是多位的
tmp += str.charAt(i);
i++;
}
i--;
ret.add(tmp);
}
関数を終了する前に、まずスタック内のすべてをエクスポートする必要があります。
//将栈里面剩余的全部出栈
while(!stack.isEmpty()) {
String b = "";
b += stack.pop();
ret.add(b);
}
return ret;
完全なコード:
public static ArrayList<String> midChangeEng(String str) {
//这里用动态数组就不用担心不够用
ArrayList<String> ret = new ArrayList<String>();
Stack<Character> stack = new Stack<>();
int[] able = {1,0,0,0,0,1};//分别代表 * + (null) - (null) / 的优先级
//遍历字符串
for (int i = 0; i < str.length(); i++) {
char a = str.charAt(i);
if (isOperator(a)) {
//是操作数
switch (a) {
case '+'://判断如果优先级不大于栈顶的元素那么就先出栈在入栈
abcd(ret, stack, able, a);
break;
case '-':
abcd(ret, stack, able, a);
break;
case '*':
abcd(ret, stack, able, a);
break;
case '/':
abcd(ret, stack, able, a);
break;
case '(':
stack.push(a);
break;
case ')':
while(!stack.isEmpty() && stack.peek() != '(') {
String b = "";
b += stack.pop();
ret.add(b);
}
stack.pop();//删除‘(’
break;
}
}else{
//如果是数字就放到ret中
String tmp = "";
while(i < str.length() && !isOperator(str.charAt(i))) {//数字有可能是多位的
tmp += str.charAt(i);
i++;
}
i--;
ret.add(tmp);
}
}
//将栈里面剩余的全部出栈
while(!stack.isEmpty()) {
String b = "";
b += stack.pop();
ret.add(b);
}
return ret;
}
後置式を使用して評価します。
この部分は比較的単純なので、直接示します。
完全なコード:
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < tokens.length; i++) {
if (isOperator(tokens[i])) {
int num2 = stack.pop();
int num1 = stack.pop();
switch(tokens[i].charAt(0)) {
case '+':
stack.push(num1 + num2);
break;
case '-':
stack.push(num1 - num2);
break;
case '*':
stack.push(num1 * num2);
break;
case '/':
stack.push(num1 / num2);
break;
}
}else {
stack.push(Integer.parseInt(tokens[i]));
}
}
return stack.pop();
}
public boolean isOperator(String str) {
if (str.length() != 1) {
return false;
}
if (str.charAt(0) == '+' || str.charAt(0) == '-' || str.charAt(0) == '*' || str.charAt(0) == '/') {
return true;
}
return false;
}