在Go(Golang)中评估Postfix表达式

208 阅读2分钟

后缀表达式的评估

在本教程中,我们将评估一个后缀表达式。

算法:

  • 从左到右扫描后缀表达式。

  • 如果当前扫描到的字符是一个操作数,则将其推入堆栈。

  • 如果当前扫描的字符是一个操作数,那么从堆栈中弹出两个操作数。在弹出的两个操作数上评估运算符,并将结果推入堆栈。

  • 当后缀表达式被完全扫描后,堆栈中应该只有一个值,这就是后缀表达式的结果。

实现方法

下面是golang中Infix到Postfix转换的实现。

package main

import (
    "fmt"
    "math"
    "strconv"
)

type Stack []int

//IsEmpty: check if stack is empty
func (st *Stack) IsEmpty() bool {
    return len(*st) == 0
}

//Push a new value onto the stack
func (st *Stack) Push(data int) {
    *st = append(*st, data) //Simply append the new value to the end of the stack
    //fmt.Println("st after push", st)
}

//Remove top element of stack. Return false if stack is empty.
func (st *Stack) Pop() bool {
    if st.IsEmpty() {
        return false
    } else {
        index := len(*st) - 1 // Get the index of top most element.
        *st = (*st)[:index]   // Remove it from the stack by slicing it off.
        //fmt.Println("st after pops", *st)
        return true
    }
}

//Return top element of stack. Return false if stack is empty.
func (st *Stack) Top() int {
    if st.IsEmpty() {
        return 0
    } else {
        index := len(*st) - 1   // Get the index of top most element.
        element := (*st)[index] // Index onto the slice and obtain the element.
        return element
    }
}

//function to evaluate postfix expression
func evaluationPostfix(postfix string) int {
    var intStack Stack
    for _, char := range postfix {
        opchar := string(char)
        //fmt.Println(opchar)
        if opchar >= "0" && opchar <= "9" {
            i1, _ := strconv.Atoi(opchar)
            //fmt.Println("Integer value is: ", i1)
            intStack.Push(i1)
            //fmt.Println(intStack)
        } else {
            opr1 := intStack.Top()
            intStack.Pop()
            opr2 := intStack.Top()
            intStack.Pop()
            switch char {
            case '^':
                x := math.Pow(float64(opr2), float64(opr1))
                intStack.Push(int(x))
            case '+':
                intStack.Push(opr2 + opr1)

            case '-':
                intStack.Push(opr2 - opr1)

            case '*':
                intStack.Push(opr2 * opr1)

            case '/':
                intStack.Push(opr2 / opr1)

            }

        }
    }
    return intStack.Top()
}

func main() {
    postfix := "2323^5-212*+^*+4-"
    evaluationReslt := evaluationPostfix(postfix)
    fmt.Printf("evaluation of %s is %d", postfix, evaluationReslt)
}

输出。

2+3*(2^3-5)^(2+1*2)-4 infix has 2323^5-212*+^*+4- postfix

我们可以通过在Push和Pop函数声明中取消对fmt.Println行的注释来检查每次推送和弹出操作后堆栈的状态。