线性表又有多种分类

1. 顺序表(数组)

2. 链表

2.1 单链表

2.2 双链表

3. 栈

自定义栈帧实现

  1. const MaxSize int = 20
  2. type Stack struct {
  3. Data []string
  4. top int
  5. }
  6. // 创建一个栈帧
  7. func CreateStack() *Stack {
  8. return &Stack{Data: make([]string, MaxSize), top: -1}
  9. }
  10. // 栈帧是否为空
  11. func (s *Stack) IsEmpty() bool {
  12. return s.top == -1
  13. }
  14. // 栈帧是否满了
  15. func (s *Stack) IsFull() bool {
  16. return s.top == MaxSize-1
  17. }
  18. // 入栈
  19. func (s *Stack) push(ele string) bool {
  20. if s.IsFull() {
  21. return false
  22. }
  23. s.top++
  24. s.Data[s.top] = ele
  25. return true
  26. }
  27. // 出栈
  28. func (s *Stack) pop() string {
  29. //
  30. if s.IsEmpty() {
  31. return "" // go语言的默认值就是"",且不能赋值nil
  32. }
  33. ele := s.Data[s.top]
  34. s.Data[s.top] = "" // 置空
  35. s.top--
  36. return ele
  37. }

3.1 栈在括号匹配中的运用

最后出现的左括号最先被匹配(LIFO),使用上面的栈帧实现

  1. func checkBracket(str string, stack *Stack) {
  2. for _, s := range str {
  3. ele := string(s)
  4. if ele == "{" || ele == "(" || ele == "[" {
  5. stack.push(string(s))
  6. } else if ele == "}" {
  7. curr := stack.pop()
  8. if curr != "{" {
  9. fmt.Println("}匹配错误,期望出现{,但是匹配到", curr)
  10. }
  11. } else if ele == "]" {
  12. curr := stack.pop()
  13. if curr != "[" {
  14. fmt.Println("]匹配错误,期望出现[,但是匹配到", curr)
  15. }
  16. } else if ele == ")" {
  17. curr := stack.pop()
  18. if curr != "(" {
  19. fmt.Println(")匹配错误,期望出现(,但是匹配到", curr)
  20. }
  21. }
  22. }
  23. if !stack.IsEmpty() {
  24. fmt.Print("括号不匹配,未找到配对:")
  25. for i := 0; i <= stack.top; i++ {
  26. fmt.Print(stack.Data[i], " ")
  27. }
  28. }
  29. }
  30. // main
  31. func main() {
  32. var str = "((([[{}]]))"
  33. stack := CreateStack()
  34. checkBracket(str, stack)
  35. }

3.2 中缀表达式转后缀表达式

利用前面实现的栈帧实现中缀表达式,转后缀表达式

中缀表达式a + bc + (d e + f) g,其转换成后缀表达式则为a b c + d e f + g +。

转换过程需要用到栈,具体过程如下:

  1. 如果遇到操作数,我们就直接将其输出。
  2. 如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
  3. 如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
  4. 如果遇到任何其他的操作符,如(“+”, “”,“(”)等,从栈中弹出元素直到遇到发现*更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到” ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( “。
  5. 如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

    1. func transToEndExpression(str string) (string, bool) {
    2. // 操作符
    3. OpMap := map[string]int{
    4. "+": 1,
    5. "-": 1,
    6. "*": 2,
    7. "/": 2,
    8. "(": 3,
    9. ")": 3,
    10. }
    11. // 特殊定义左右括号
    12. BracketMap := map[string]bool{
    13. "(": true,
    14. ")": true,
    15. }
    16. // 校验括号
    17. var ops string = ""
    18. for i := 0; i < len(str); i++ {
    19. if BracketMap[string(str[i])] {
    20. ops += string(str[i])
    21. }
    22. }
    23. if len(ops) > 0 {
    24. canDo := checkBracket(ops, CreateStack())
    25. if !canDo {
    26. // 括号不符合规则
    27. return "", false
    28. }
    29. }
    30. // 处理掉空字符
    31. exp := strings.ReplaceAll(str, " ", "")
    32. // 存放操作符的栈
    33. stack := CreateStack()
    34. // 最终后缀表达式
    35. var result string = ""
    36. // 遍历表达式
    37. for _, ch := range exp {
    38. arg := string(ch)
    39. x := OpMap[arg]
    40. if x == 0 {
    41. // 操作数,直接追加到表达式后面
    42. result = result + arg
    43. } else {
    44. // 是否是右括号
    45. if ")" == arg {
    46. // 遇到右括号")",需要弹出栈中所有的操作符,直到遇到左括号"("
    47. for true {
    48. topEle := stack.pop()
    49. if topEle == "(" {
    50. // 遇到左括号退出循环
    51. break
    52. }
    53. // 将操作符追加到表达式后面
    54. result += topEle
    55. }
    56. } else {
    57. for true {
    58. // 将栈中所有优先级大于或等于当前操作符的,全部出栈追加到表达式后面
    59. topOperator := stack.getTopEle()
    60. if "(" != topOperator && OpMap[topOperator] >= OpMap[arg] {
    61. result += stack.pop()
    62. } else {
    63. break
    64. }
    65. }
    66. // 最后,将当前操作符入栈
    67. stack.push(arg)
    68. }
    69. }
    70. }
    71. // 处理栈帧剩余元素
    72. for !stack.IsEmpty() {
    73. result += stack.pop()
    74. }
    75. return result, true
    76. }

    测试

    1. func main() {
    2. // a + b - c * (d-f) - r
    3. var str string = "a + b - c * ((d-f) - r"
    4. result, err := transToEndExpression(str)
    5. if !err {
    6. fmt.Println("表达式:\t\t", str)
    7. fmt.Println("后缀表达式为:\t", result)
    8. }
    9. }

    我们实现了中缀转后缀,接下来就是实现计算机如何计算后缀表达式

    3.3 计算后缀表达式结果

    利用go语言模拟计算机计算后缀表达式 ```go

/**

  • 计算后缀表达式 */ func calculateSuffixExp(expression string) (string, bool) { stack := CreateStack() arr := strings.Split(expression, “ “)

    for _, ele := range arr {

    1. if ele == "" {
    2. continue
    3. }
    4. // 遇到操作数压栈,遇到操作符,取出两个操作数计算
    5. if "+" == ele {
    6. second := stack.pop()
    7. first := stack.pop()
    8. firstNum, _ := strconv.Atoi(first)
    9. secondNum, _ := strconv.Atoi(second)
    10. result := firstNum + secondNum
    11. // 再压入栈
    12. stack.push(strconv.Itoa(result))
    13. } else if "-" == ele {
    14. second := stack.pop()
    15. first := stack.pop()
    16. firstNum, _ := strconv.Atoi(first)
    17. secondNum, _ := strconv.Atoi(second)
    18. result := firstNum - secondNum
    19. // 再压入栈
    20. stack.push(strconv.Itoa(result))
    21. } else if "*" == ele {
    22. second := stack.pop()
    23. first := stack.pop()
    24. firstNum, _ := strconv.Atoi(first)
    25. secondNum, _ := strconv.Atoi(second)
    26. result := firstNum * secondNum
    27. // 再压入栈
    28. stack.push(strconv.Itoa(result))
    29. } else if "/" == ele {
    30. second := stack.pop()
    31. first := stack.pop()
    32. firstNum, _ := strconv.Atoi(first)
    33. secondNum, _ := strconv.Atoi(second)
    34. result := firstNum / secondNum
    35. // 再压入栈
    36. stack.push(strconv.Itoa(result))
    37. } else {
    38. _, err := strconv.Atoi(ele)
    39. if err != nil {
    40. fmt.Println("非数字错误.....")
    41. return "", true
    42. }
    43. stack.push(ele)
    44. }

    } result := stack.pop() return result, false }

//

  1. 测试
  2. ```go
  3. func main() {
  4. var exp string = "1+3+5*5+2-9/3-4"
  5. // 后缀表达式 1 3 + 5 5 * + 2 + 10 5 / - 3 -
  6. expression, succ := transToEndExpression(exp)
  7. if succ {
  8. // 计算
  9. result, done := calculateSuffixExp(expression)
  10. if done {
  11. return
  12. }
  13. fmt.Println("计算结果:", exp, "=", result)
  14. }
  15. }

卡特兰数

4. 队列

4.1 队列

4.2 双端队列