1. 顺序表(数组)
2. 链表
2.1 单链表
2.2 双链表
3. 栈
自定义栈帧实现
const MaxSize int = 20type Stack struct {Data []stringtop int}// 创建一个栈帧func CreateStack() *Stack {return &Stack{Data: make([]string, MaxSize), top: -1}}// 栈帧是否为空func (s *Stack) IsEmpty() bool {return s.top == -1}// 栈帧是否满了func (s *Stack) IsFull() bool {return s.top == MaxSize-1}// 入栈func (s *Stack) push(ele string) bool {if s.IsFull() {return false}s.top++s.Data[s.top] = elereturn true}// 出栈func (s *Stack) pop() string {//if s.IsEmpty() {return "" // go语言的默认值就是"",且不能赋值nil}ele := s.Data[s.top]s.Data[s.top] = "" // 置空s.top--return ele}
3.1 栈在括号匹配中的运用
最后出现的左括号最先被匹配(LIFO),使用上面的栈帧实现
func checkBracket(str string, stack *Stack) {for _, s := range str {ele := string(s)if ele == "{" || ele == "(" || ele == "[" {stack.push(string(s))} else if ele == "}" {curr := stack.pop()if curr != "{" {fmt.Println("}匹配错误,期望出现{,但是匹配到", curr)}} else if ele == "]" {curr := stack.pop()if curr != "[" {fmt.Println("]匹配错误,期望出现[,但是匹配到", curr)}} else if ele == ")" {curr := stack.pop()if curr != "(" {fmt.Println(")匹配错误,期望出现(,但是匹配到", curr)}}}if !stack.IsEmpty() {fmt.Print("括号不匹配,未找到配对:")for i := 0; i <= stack.top; i++ {fmt.Print(stack.Data[i], " ")}}}// mainfunc main() {var str = "((([[{}]]))"stack := CreateStack()checkBracket(str, stack)}
3.2 中缀表达式转后缀表达式
利用前面实现的栈帧实现中缀表达式,转后缀表达式
中缀表达式a + bc + (d e + f) g,其转换成后缀表达式则为a b c + d e f + g +。
转换过程需要用到栈,具体过程如下:
- 如果遇到操作数,我们就直接将其输出。
- 如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
- 如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
- 如果遇到任何其他的操作符,如(“+”, “”,“(”)等,从栈中弹出元素直到遇到发现*更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到” ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( “。
如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
func transToEndExpression(str string) (string, bool) {// 操作符OpMap := map[string]int{"+": 1,"-": 1,"*": 2,"/": 2,"(": 3,")": 3,}// 特殊定义左右括号BracketMap := map[string]bool{"(": true,")": true,}// 校验括号var ops string = ""for i := 0; i < len(str); i++ {if BracketMap[string(str[i])] {ops += string(str[i])}}if len(ops) > 0 {canDo := checkBracket(ops, CreateStack())if !canDo {// 括号不符合规则return "", false}}// 处理掉空字符exp := strings.ReplaceAll(str, " ", "")// 存放操作符的栈stack := CreateStack()// 最终后缀表达式var result string = ""// 遍历表达式for _, ch := range exp {arg := string(ch)x := OpMap[arg]if x == 0 {// 操作数,直接追加到表达式后面result = result + arg} else {// 是否是右括号if ")" == arg {// 遇到右括号")",需要弹出栈中所有的操作符,直到遇到左括号"("for true {topEle := stack.pop()if topEle == "(" {// 遇到左括号退出循环break}// 将操作符追加到表达式后面result += topEle}} else {for true {// 将栈中所有优先级大于或等于当前操作符的,全部出栈追加到表达式后面topOperator := stack.getTopEle()if "(" != topOperator && OpMap[topOperator] >= OpMap[arg] {result += stack.pop()} else {break}}// 最后,将当前操作符入栈stack.push(arg)}}}// 处理栈帧剩余元素for !stack.IsEmpty() {result += stack.pop()}return result, true}
测试
func main() {// a + b - c * (d-f) - rvar str string = "a + b - c * ((d-f) - r"result, err := transToEndExpression(str)if !err {fmt.Println("表达式:\t\t", str)fmt.Println("后缀表达式为:\t", result)}}
我们实现了中缀转后缀,接下来就是实现计算机如何计算后缀表达式
3.3 计算后缀表达式结果
利用go语言模拟计算机计算后缀表达式 ```go
/**
计算后缀表达式 */ func calculateSuffixExp(expression string) (string, bool) { stack := CreateStack() arr := strings.Split(expression, “ “)
for _, ele := range arr {
if ele == "" {continue}// 遇到操作数压栈,遇到操作符,取出两个操作数计算if "+" == ele {second := stack.pop()first := stack.pop()firstNum, _ := strconv.Atoi(first)secondNum, _ := strconv.Atoi(second)result := firstNum + secondNum// 再压入栈stack.push(strconv.Itoa(result))} else if "-" == ele {second := stack.pop()first := stack.pop()firstNum, _ := strconv.Atoi(first)secondNum, _ := strconv.Atoi(second)result := firstNum - secondNum// 再压入栈stack.push(strconv.Itoa(result))} else if "*" == ele {second := stack.pop()first := stack.pop()firstNum, _ := strconv.Atoi(first)secondNum, _ := strconv.Atoi(second)result := firstNum * secondNum// 再压入栈stack.push(strconv.Itoa(result))} else if "/" == ele {second := stack.pop()first := stack.pop()firstNum, _ := strconv.Atoi(first)secondNum, _ := strconv.Atoi(second)result := firstNum / secondNum// 再压入栈stack.push(strconv.Itoa(result))} else {_, err := strconv.Atoi(ele)if err != nil {fmt.Println("非数字错误.....")return "", true}stack.push(ele)}
} result := stack.pop() return result, false }
//
测试```gofunc main() {var exp string = "1+3+5*5+2-9/3-4"// 后缀表达式 1 3 + 5 5 * + 2 + 10 5 / - 3 -expression, succ := transToEndExpression(exp)if succ {// 计算result, done := calculateSuffixExp(expression)if done {return}fmt.Println("计算结果:", exp, "=", result)}}
卡特兰数
