преобразование из инфикса в префикс - PullRequest
15 голосов
/ 22 декабря 2009

Я готовлюсь к экзамену, на котором я не смог понять преобразование инфиксной записи в польскую для следующего выражения:

(a–b)/c*(d + e – f / g)

Может ли кто-нибудь шаг за шагом рассказать, как данное выражение будет преобразовано в префикс?

Ответы [ 14 ]

26 голосов
/ 09 января 2010
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
5 голосов
/ 22 декабря 2009

(a–b)/c*(d + e – f / g)

Префиксная нотация (у оператора обратной полировки последний оператор, неясно, какой вы имели в виду, но принцип будет точно таким же):

  1. (/ f g)
  2. (+ d e)
  3. (- (+ d e) (/ f g))
  4. (- a b)
  5. (/ (- a b) c)
  6. (* (/ (- a b) c) (- (+ d e) (/ f g)))
5 голосов
/ 22 декабря 2009

Если есть что-то о том, что инфикс и префикс означают, что вы не совсем понимаете, я настоятельно рекомендую вам перечитать этот раздел вашего учебника . Вы не делаете себе никаких одолжений, если выходите из этого с правильным ответом на эту одну проблему, но все еще не понимаете концепцию.

С точки зрения алгоритма, это чертовски просто. Вы просто немного ведете себя как компьютер. Начните с помещения паренов в каждый расчет в том порядке, в котором он будет рассчитан. Затем (снова в порядке от первого вычисления до последнего) просто переместите оператор перед выражением в его левой части. После этого вы можете упростить, удалив парены.

4 голосов
/ 04 марта 2012
(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

Это префиксная запись.

3 голосов
/ 18 апреля 2013

Я видел этот метод на YouTube, поэтому размещать здесь.

данное инфиксное выражение: (a – b) / c * (d + e - f / g)

отменить это:

) г / е-е + d (* с /) б-а (

читать символы слева направо.
поддерживать один стек для операторов

 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

1 голос
/ 07 февраля 2011

(a – b) / c * (d + e - f / g)

не забывайте сканировать выражение слева направо начать в скобках следуйте тому, что приходит первым правилом ... *, /,% находятся на том же уровне и выше, чем + и -.... так (a-b) = -bc префикс (a-b) = bc- для постфикса другой заключенный в скобки термин: (d + e - f / g) = сначала переместите / затем плюс «+» стоит перед минусом вздоха «-» (помните, что они на одном уровне ..) (д + е - ж / г) двигаться / первым (d + e - (/ fg)) = префикс (d + e - (fg /)) = постфикс затем + затем - ((+ de) - (/ fg)) = префикс ((de +) - (fg /)) = постфикс

(- (+ de) (/ fg)) = префикс, поэтому новое выражение теперь - + de / fg (1) ((de +) (fg /) -) = постфикс, поэтому новое выражение теперь de + fg / - (2)

(a – b) / c *, следовательно

  1. (a-b) / c * (d + e - f / g) = -bc префикс [-ab] / c * [- + de / fg] ---> взято из (1) / c * пока не двигайся поэтому «/» стоит перед «*», потому что они на одном уровне перемещаются «/» справа: / [- ab] c * [- + de / fg] затем переместите '*' вправо

    • / [-ab] c [- + de / fg] = удалить символы группировки = * / - abc- + de / fg -> префикс
  2. (a-b) / c * (d + e - f / g) = bc- для постфикса [ab -] / c * [de + fg / -] ---> взято из (2) поэтому «/» стоит перед «», потому что они на одном уровне перемещаются «/» крайний левый: [ab-] c [de + fg / -] / затем переместите '' в крайнее левое положение [ab-] c [de + fg / -] / = удалить символы группировки = a b - c d e + f g / - / * -> Postfix

0 голосов
/ 24 октября 2017

Инфикс для 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
0 голосов
/ 15 сентября 2016

В префиксных выражениях сначала идут операторы выражения, затем операнды: + ab [oprator ab]

Инфикс: (a–b)/c*(d + e – f / g)


Шаг 1: (a - b) = (- ab) ['(' имеет наивысший приоритет]

шаг 2: (d + e - f / g) = (d + e - / fg) ['/' имеет наивысший приоритет]

                       = (+ de - / fg )

          ['+','-' has same priority but left to right associativity]

                       = (- + de / fg)

Шаг 3: (-ab )/ c * (- + de / fg) = / - abc * (- + de / fg)

                                 = * / - abc - + de / fg 

Префикс: * / - abc - + de / fg

0 голосов
/ 12 мая 2016

здесь - реализация Java для преобразования инфикса в префикс и оценки выражения префикса (на основе алгоритма Радждипа)

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));
    }
}
0 голосов
/ 27 ноября 2015

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 ]
...