私は、下式の表記法を洗練するために中置表記法の変換を理解できなかった試験の準備をしています:
(a–b)/c*(d + e – f / g)
与えられた式がどのようにプレフィックスに変換されるかを段階的に伝えることはできますか?
Algorithm ConvertInfixtoPrefix
Purpose: Convert an infix expression into a prefix expression. Begin
// Create operand and operator stacks as empty stacks.
Create OperandStack
Create OperatorStack
// While input expression still remains, read and process the next token.
while( not an empty input expression ) read next token from the input expression
// Test if token is an operand or operator
if ( token is an operand )
// Push operand onto the operand stack.
OperandStack.Push (token)
endif
// If it is a left parentheses or operator of higher precedence than the last, or the stack is empty,
else if ( token is '(' or OperatorStack.IsEmpty() or OperatorHierarchy(token) > OperatorHierarchy(OperatorStack.Top()) )
// Push it to the operator stack
OperatorStack.Push ( token )
endif
else if( token is ')' )
// Continue to pop operator and operand stacks, building
// prefix expressions until left parentheses is found.
// Each prefix expression is Push back onto the operand
// stack as either a left or right operand for the next operator.
while( OperatorStack.Top() not equal '(' )
OperatorStack.Pop(operator)
OperandStack.Pop(RightOperand)
OperandStack.Pop(LeftOperand)
operand = operator + LeftOperand + RightOperand
OperandStack.Push(operand)
endwhile
// Pop the left parthenses from the operator stack.
OperatorStack.Pop(operator)
endif
else if( operator hierarchy of token is less than or equal to hierarchy of top of the operator stack )
// Continue to pop operator and operand stack, building prefix
// expressions until the stack is empty or until an operator at
// the top of the operator stack has a lower hierarchy than that
// of the token.
while( !OperatorStack.IsEmpty() and OperatorHierarchy(token) lessThen Or Equal to OperatorHierarchy(OperatorStack.Top()) )
OperatorStack.Pop(operator)
OperandStack.Pop(RightOperand)
OperandStack.Pop(LeftOperand)
operand = operator + LeftOperand + RightOperand
OperandStack.Push(operand)
endwhile
// Push the lower precedence operator onto the stack
OperatorStack.Push(token)
endif
endwhile
// If the stack is not empty, continue to pop operator and operand stacks building
// prefix expressions until the operator stack is empty.
while( !OperatorStack.IsEmpty() ) OperatorStack.Pop(operator)
OperandStack.Pop(RightOperand)
OperandStack.Pop(LeftOperand)
operand = operator + LeftOperand + RightOperand
OperandStack.Push(operand)
endwhile
// Save the prefix expression at the top of the operand stack followed by popping // the operand stack.
print OperandStack.Top()
OperandStack.Pop()
End
中置辞と接頭辞があなたがよく理解していないことを意味するものがあれば、強くお勧めします教科書のそのセクションを読んでください。この1つの問題に対する正しい答えでこれから出てきても、あなたは自分自身に何の恩恵も与えていませんが、それでも概念を理解していません。
アルゴリズム面では、非常にシンプルです。あなたはちょっとコンピューターのように振る舞います。最初に、計算される順序ですべての計算の周りに括弧を配置します。次に(最初の計算から最後の計算まで)、演算子を式の左側に移動します。その後、括弧を削除して単純化できます。
(a–b)/c*(d + e – f / g)
プレフィックス表記(リバースポリッシュでは最後に演算子があり、どちらを意味するかは明確ではありませんが、原則はまったく同じです):
(/ f g)
(+ d e)
(- (+ d e) (/ f g))
(- a b)
(/ (- a b) c)
(* (/ (- a b) c) (- (+ d e) (/ f g)))
(a–b)/c*(d + e – f / g)
ステップ1: (a-b)/c*(d+e- /fg))
ステップ2: (a-b)/c*(+de - /fg)
ステップ3:(a-b)/c * -+de/fg
ステップ4:-ab/c * -+de/fg
ステップ5:/-abc * -+de/fg
ステップ6:*/-abc-+de/fg
これはプレフィックス表記です。
YouTubeでこの方法を見たので、ここに投稿します。
指定された挿入表現:(a–b)/ c *(d + e – f/g)
逆に:
)g/f-e + d(* c /)b-a(
左から右に文字を読みます。
オペレーター用に1つのスタックを維持する
1. if character is operand add operand to the output
2. else if character is operator or )
2.1 while operator on top of the stack has lower or **equal** precedence than this character pop
2.2 add the popped character to the output.
Push the character on stack
3. else if character is parenthesis (
3.1 [ same as 2 till you encounter ) . pop ) as well
4. // no element left to read
4.1 pop operators from stack till it is not empty
4.2 add them to the output.
reverse the output and print.
クレジット: youtube
(a–b)/ c *(d + e – f/g)
括弧で囲まれた用語の左端から右端まで式をスキャンすることを忘れないでください。最初のルールに従ってください。*、/、%は同じレベルで、+および-....よりも高いです。したがって、(ab)= -bcプレフィックス(ab)= bc-別の括弧で囲まれた用語の後置:(d + e-f/g)= /最初に移動し、プラス '+'が最初に来てマイナスため息 '-'になる(それらは同じレベルにあることを思い出してください.. )(d + e-f/g)move/first(d + e-(/ fg))= prefix(d + e-(fg /))= postfixに続いて+ then-((+ de)-(/ fg))=プレフィックス((de +)-(fg /))=ポストフィックス
(-(+ de)(/ fg))=プレフィックスなので、新しい式は-+ de/fg(1)((de +)(fg /)-)=後置記号なので、新しい式はde + fg /- (2)
(a–b)/ c *したがって
(ab)/ c *(d + e – f/g)= -bc prefix [-ab]/c * [-+ de/fg] --->(1)/ c *から取得'/'は同じレベルにあるため、 '*'の前に最初に来ます。これは、 '/'を右端に移動するためです:/ [-ab] c * [-+ de/fg]次に '*'を右端に移動します
(ab)/ c *(d + e – f/g)= bc-接尾辞[ab-]/c * [de + fg /-] --->は(2)から取得されるため、「/」が最初に来る「」は同じレベルにあるため、「/」を左端に移動します:[ab-] c[de + fg /-] /その後移動''を左端に[ab-] c [de + fg /-] /=グループ化シンボルを削除= ab-cde + fg /-/ *->後置
このアルゴリズムは、理解を深めるのに役立ちます。
ステップ1.「)」をスタックに押し、「(」をAの最後に追加します。
ステップ2. Aを右から左にスキャンし、スタックが空になるまでAの各要素に対してステップ3から6を繰り返します。
ステップ3.オペランドが検出された場合、それをBに追加します。
ステップ4.右括弧が見つかった場合、それをSTACKにプッシュします。
ステップ5.オペレーターに遭遇した場合:a。 STACKから繰り返しポップし、Bに各演算子(STACKの上部)を追加します。各演算子は、演算子と同じか、より高い優先順位を持ちます。 b。 STACKに演算子を追加します。
ステップ6.左括弧が続く場合、a。スタックから繰り返しポップし、Bに追加します(左括弧が見つかるまでスタックの最上位にある各演算子)b。左括弧を削除します。
ステップ7.終了
簡単なグーグル検索で this が思いつきました。誰でもこれをもっと簡単に説明できると思います。しかし、編集後、私はあなたがあなた自身の質問に答えることができるように概念を前に進めようとすることができると思います。
ヒント:
試験のために一生懸命勉強する必要があります。あなたを予測し、成績が高くなります、私はそうします:D
説明 :
操作がオペランドに関連付けられる方法がすべてです。各表記タイプには独自のルールがあります。これらのルールを分解して覚えておくだけです。 [* /](2,2,3)として(2 * 2)/ 3と書いたと言ったら、前者の表記で後者の表記を変える方法を学ぶだけです。
私のカスタム表記では、最初の2つのオペランドを取得し、複数のオペランドを取得し、結果のオペランドを3番目のオペランドで除算する必要があります。それを得る ?彼らはあなたに3つのことを教えようとしています。
スタックを使用したPostFixへの挿入:
Example: Infix--> P-Q*R^S/T+U *V
Postfix --> PQRS^*T/-UV
Rules:
Operand ---> Add it to postfix
"(" ---> Push it on the stack
")" ---> Pop and add to postfix all operators till 1st left parenthesis
Operator ---> Pop and add to postfix those operators that have preceded
greater than or equal to the precedence of scanned operator.
Push the scanned symbol operator on the stack
https://en.wikipedia.org/wiki/Shunting-yard_algorithm
シャンティングヤードアルゴリズムは、プレフィックス表記(ポーランド語表記とも呼ばれる)の生成にも適用できます。これを行うには、解析するトークンの文字列の最後から単純に開始し、逆方向に作業し、出力キューを逆にし(したがって出力キューを出力スタックにします)、左右の括弧の動作を反転します(今を思い出してください) -左括弧の動作は、右括弧が見つかるまでポップする必要があります)。
from collections import deque
def convertToPN(expression):
precedence = {}
precedence["*"] = precedence["/"] = 3
precedence["+"] = precedence["-"] = 2
precedence[")"] = 1
stack = []
result = deque([])
for token in expression[::-1]:
if token == ')':
stack.append(token)
Elif token == '(':
while stack:
t = stack.pop()
if t == ")": break
result.appendleft(t)
Elif token not in precedence:
result.appendleft(token)
else:
# XXX: associativity should be considered here
# https://en.wikipedia.org/wiki/Operator_associativity
while stack and precedence[stack[-1]] > precedence[token]:
result.appendleft(stack.pop())
stack.append(token)
while stack:
result.appendleft(stack.pop())
return list(result)
expression = "(a - b) / c * (d + e - f / g)".replace(" ", "")
convertToPN(expression)
ステップスルー:
step 1 : token ) ; stack:[ ) ]
result:[ ]
step 2 : token g ; stack:[ ) ]
result:[ g ]
step 3 : token / ; stack:[ ) / ]
result:[ g ]
step 4 : token f ; stack:[ ) / ]
result:[ f g ]
step 5 : token - ; stack:[ ) - ]
result:[ / f g ]
step 6 : token e ; stack:[ ) - ]
result:[ e / f g ]
step 7 : token + ; stack:[ ) - + ]
result:[ e / f g ]
step 8 : token d ; stack:[ ) - + ]
result:[ d e / f g ]
step 9 : token ( ; stack:[ ]
result:[ - + d e / f g ]
step 10 : token * ; stack:[ * ]
result:[ - + d e / f g ]
step 11 : token c ; stack:[ * ]
result:[ c - + d e / f g ]
step 12 : token / ; stack:[ * / ]
result:[ c - + d e / f g ]
step 13 : token ) ; stack:[ * / ) ]
result:[ c - + d e / f g ]
step 14 : token b ; stack:[ * / ) ]
result:[ b c - + d e / f g ]
step 15 : token - ; stack:[ * / ) - ]
result:[ b c - + d e / f g ]
step 16 : token a ; stack:[ * / ) - ]
result:[ a b c - + d e / f g ]
step 17 : token ( ; stack:[ * / ]
result:[ - a b c - + d e / f g ]
# the final while
step 18 : token ( ; stack:[ ]
result:[ * / - a b c - + d e / f g ]
Java infixをプレフィックスに変換し、プレフィックス式を評価するための実装(rajdipのアルゴリズムに基づく)
import Java.util.*;
public class Expression {
private static int isp(char token){
switch (token){
case '*':
case '/':
return 2;
case '+':
case '-':
return 1;
default:
return -1;
}
}
private static double calculate(double oprnd1,double oprnd2,char oprt){
switch (oprt){
case '+':
return oprnd1+oprnd2;
case '*':
return oprnd1*oprnd2;
case '/':
return oprnd1/oprnd2;
case '-':
return oprnd1-oprnd2;
default:
return 0;
}
}
public static String infix2prefix(String infix) {
Stack<String> OperandStack = new Stack<>();
Stack<Character> OperatorStack = new Stack<>();
for(char token:infix.toCharArray()){
if ('a' <= token && token <= 'z')
OperandStack.Push(String.valueOf(token));
else if (token == '(' || OperatorStack.isEmpty() || isp(token) > isp(OperatorStack.peek()))
OperatorStack.Push(token);
else if(token == ')'){
while (OperatorStack.peek() != '(') {
Character operator = OperatorStack.pop();
String RightOperand = OperandStack.pop();
String LeftOperand = OperandStack.pop();
String operand = operator + LeftOperand + RightOperand;
OperandStack.Push(operand);
}
OperatorStack.pop();
}
else if(isp(token) <= isp(OperatorStack.peek())){
while (!OperatorStack.isEmpty() && isp(token)<= isp(OperatorStack.peek())) {
Character operator = OperatorStack.pop();
String RightOperand = OperandStack.pop();
String LeftOperand = OperandStack.pop();
String operand = operator + LeftOperand + RightOperand;
OperandStack.Push(operand);
}
OperatorStack.Push(token);
}
}
while (!OperatorStack.isEmpty()){
Character operator = OperatorStack.pop();
String RightOperand = OperandStack.pop();
String LeftOperand = OperandStack.pop();
String operand = operator + LeftOperand + RightOperand;
OperandStack.Push(operand);
}
return OperandStack.pop();
}
public static double evaluatePrefix(String prefix, Map values){
Stack<Double> stack = new Stack<>();
prefix = new StringBuffer(prefix).reverse().toString();
for (char token:prefix.toCharArray()){
if ('a'<=token && token <= 'z')
stack.Push((double) values.get(token));
else {
double oprnd1 = stack.pop();
double oprnd2 = stack.pop();
stack.Push(calculate(oprnd1,oprnd2,token));
}
}
return stack.pop();
}
public static void main(String[] args) {
Map dictionary = new HashMap<>();
dictionary.put('a',2.);
dictionary.put('b',3.);
dictionary.put('c',2.);
dictionary.put('d',5.);
dictionary.put('e',16.);
dictionary.put('f',4.);
dictionary.put('g',7.);
String s = "((a+b)/(c-d)+e)*f-g";
System.out.println(evaluatePrefix(infix2prefix(s),dictionary));
}
}