数据结构--堆栈--利用堆栈计算后缀表达式

文章目录

  • 后缀表达式的定义
  • 算法实现(go语言版)
    • 链表实现栈数据结构
    • 利用栈计算后缀表达式
    • 计算结果

后缀表达式的定义

以人类的思维,中缀表达式是正常的表达式形式,因为我们已经熟悉了各种运算符号的优先级,知道在一个表达式中第一个求哪一部分的值,最常见的就是先求括号内部,然后再求括号外部,但是这种求值顺序在计算机看来是很麻烦的,最好的办法是我们输入给计算机的表达式不需要知道操作符优先级,计算机只管按照我们输入的表达式从左到右求值即可,这就要用后缀表达式来实现。后缀表达式是针对中缀表达式而言的,大致可以理解为操作符在两个操作数之后,并不是像中缀表达式那样两个操作数之间必须有一个操作符,后缀表达式最大的特点就是没有必要知道任何运算符的优先规则,如下就是一个后缀表达式:

“23.2 1.43 * 4.43 + 5.32 1.90 * +”

其中缀表达式为:“23.21.43+4.43+5.321.90”

后缀表达式的求值规则为:从左到右扫描后缀表达式,如果遇到一个操作数,将其压入栈中,如果遇到一个操作符,则从栈中弹出两个操作数,注意:在弹出时被减(加、乘、除)数先被弹出,计算结果,然后把结果入栈,直到遍历完后缀表达式,则计算完成,此时的栈顶元素即为计算结果。如上的后缀表达式求值过程为:
1.初始,栈空
2.遇到操作数23.2,入栈
3.遇到操作数1.43,入栈
4.遇到操作符*,弹出栈中两个元素,计算结果入栈
5.遇到操作数4.43,入栈
6.遇到操作符+,弹出占中两个元素,计算结果入栈
7.遇到操作数5.32,入栈
8.遇到操作数1.90,入栈
9.遇到操作符*,弹出栈中两个元素,计算结果入栈
10.遇到操作符+,弹出占中两个元素,计算结果入栈

算法实现(go语言版)

链表实现栈数据结构

package data

type Node struct {
	value float64
	next  *Node
}

//栈,先进后出,后进先出
type MyStack struct {
	head *Node
	size int
}

//判断栈是否为空
func (st *MyStack) Empty() bool {
	if st.size > 0 {
		return false
	}
	return true
}

//获取栈的元素个数
func (st *MyStack) Size() int {
	return st.size
}

//入栈
func (st *MyStack) Push(v float64) {
	//使用头插法
	newHead := new(Node)
	newHead.value = v
	newHead.next = st.head
	st.head = newHead
	st.size += 1
}

//出栈
func (st *MyStack) Pop() {
	if st.size > 0 {
		next := st.head.next
		st.head.next = nil
		st.head = next
		st.size -= 1
	}
}

//获取栈顶元素
func (st *MyStack) Top() float64 {
	if st.size > 0 {
		return st.head.value
	}
	return 0
}

利用栈计算后缀表达式

package main

import (
	"algorithm/dataStruct/stack/data"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	str := "6 4 + 2.5 / 5 2 * +"
	fmt.Println(calSuffixExp(str))
}

//利用栈计算后缀表达式的值
func calSuffixExp(expStr string) float64 {
	opts := map[string]int{"+": 1, "-": 1, "*": 1, "/": 1}
	expElements := strings.Split(expStr, " ")
	mst := new(data.MyStack)
	for _, ele := range expElements {
		if _, ok := opts[ele]; ok {
			//如果是操作符则从栈中弹出两个元素,进行计算后,将结果入栈,注意:在弹出时被减(加、乘、除)数先被弹出
			num1 := mst.Top()
			mst.Pop()
			num2 := mst.Top()
			mst.Pop()
			result := 0.0
			switch ele {
			case "+":
				result = num2 + num1
			case "-":
				result = num2 - num1
			case "*":
				result = num2 * num1
			case "/":
				result = num2 / num1
			}
			//将结果入栈
			mst.Push(result)
		} else {
			//如果是操作数则直接入栈
			v, err := strconv.ParseFloat(ele, 64)
			if err != nil {
				fmt.Println("后缀表达式格式错误,操作数为float类型,操作符集合:+,-,*,/,元素间用空格分隔")
				os.Exit(1)
			}
			mst.Push(v)
		}
	}
	return mst.Top()
}

计算结果

在这里插入图片描述
计算过程为:(6+4)/2.5+(5*2) = 14

你可能感兴趣的:(算法)