递归

前序遍历

  1. func preorder(root *TreeNode)[]int{
  2. res := make([]int, 0)
  3. var order func(*TreeNode)
  4. order = func (node *TreeNode){
  5. if node ==nil{
  6. return
  7. }
  8. // 递归方法 先写入值 再递归左节点 再递归右节点
  9. res = append(res,node.Val)
  10. order(node.Left)
  11. order(node.Right)
  12. }
  13. order(root)
  14. return res
  15. }

中序遍历

  1. func inorderTraversal(root *TreeNode) []int {
  2. res := make([]int, 0)
  3. stack := []*TreeNode{}
  4. node := root
  5. for node != nil || len(stack) > 0{
  6. res = append(res, node.Val)
  7. stack = append(stack, node)
  8. node = node.Left
  9. }
  10. }

后序遍历

  1. func postorderTraversal(root *TreeNode) []int {
  2. res := make([]int, 0)
  3. var postorder func(*TreeNode)
  4. postorder = func(node *TreeNode){
  5. if node == nil{
  6. return
  7. }
  8. postorder(node.Left)
  9. postorder(node.Right)
  10. res = append(res, node.Val)
  11. }
  12. postorder(root)
  13. return res
  14. }

迭代

前序遍历

  1. func preorderTraversal(root *TreeNode) []int {
  2. res := make([]int, 0)
  3. stack := []*TreeNode{}
  4. if root == nil{
  5. return res
  6. }
  7. node := root
  8. stack = append(stack, node)
  9. for len(stack) > 0{
  10. tmp := stack[len(stack) - 1]
  11. stack = stack[:len(stack) - 1]
  12. res = append(res, tmp.Val)
  13. if tmp.Right != nil{
  14. stack = append(stack, tmp.Right)
  15. }
  16. if tmp.Left != nil{
  17. stack = append(stack, tmp.Left)
  18. }
  19. }
  20. return res
  21. }

中序遍历

思路:每到一个节点 A,因为根的访问在中间,将 A 入栈。然后遍历左子树,接着访问 A,最后遍历右子树。

在访问完 A 后,A 就可以出栈了。因为 A 和其左子树都已经访问完成。

  1. func inorderTraversal(root *TreeNode) []int {
  2. res := make([]int, 0)
  3. stack := []*TreeNode{}
  4. if root == nil{
  5. return res
  6. }
  7. node := root
  8. for node != nil || len(stack) > 0{
  9. for node != nil{
  10. stack = append(stack, node)
  11. node = node.Left
  12. }
  13. node = stack[len(stack) - 1]
  14. stack = stack[:len(stack) - 1]
  15. res = append(res, node.Val)
  16. node = node.Right
  17. }
  18. return res
  19. }

后序遍历

再来看后序遍历,先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了,如下图:
image.png

  1. func postorderTraversal(root *TreeNode) []int {
  2. res := make([]int, 0)
  3. stack := []*TreeNode{}
  4. if root == nil{
  5. return res
  6. }
  7. node := root
  8. stack = append(stack, node)
  9. for len(stack) > 0{
  10. tmp := stack[len(stack) - 1]
  11. stack = stack[:len(stack) - 1]
  12. res = append(res, tmp.Val)
  13. if tmp.Left != nil{
  14. stack = append(stack, tmp.Left) // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)
  15. }
  16. if tmp.Right != nil{
  17. stack = append(stack, tmp.Right) // 空节点不入栈
  18. }
  19. }
  20. for i := 0; i < len(res) / 2; i++{
  21. res[i], res[len(res) - i - 1] = res[len(res) - i - 1], res[i]
  22. }
  23. return res
  24. }

使用slice模拟栈

普通版的模拟写入和读取的栈

  1. package main
  2. import "fmt"
  3. //栈的特点是先进后出
  4. //使用一个切片的全局变量来模拟栈
  5. var stack []int
  6. //向栈中添加数据
  7. func push(value int) {
  8. stack = append(stack, value)
  9. }
  10. //从栈中获取数据
  11. func pop() (int, bool) {
  12. ok := false
  13. value := 0
  14. if len(stack) > 0 {
  15. value = stack[len(stack)-1]
  16. stack = stack[:len(stack)-1]
  17. ok = true
  18. return value, ok
  19. } else {
  20. return value, ok
  21. }
  22. }
  23. func main() {
  24. //向栈中添加数据
  25. for i := 0; i < 10; i++ {
  26. push(i)
  27. fmt.Println(stack)
  28. }
  29. //从栈中获取数据
  30. for {
  31. v, ok := pop()
  32. if ok {
  33. fmt.Println(v)
  34. } else {
  35. break
  36. }
  37. }
  38. }

使用goroutine来异步读取栈中数据或往栈中写入数据

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. //栈的特点是先进后出
  6. //使用一个切片的全局变量来模拟栈
  7. var stack1 []int
  8. //此通道用于通知主协程已经完成操作了
  9. //但是此操作有可能不会输出全部数据
  10. //因为添加数据和获取数据是异步的
  11. //当获取数据的速度快于写入数据
  12. //便不会输出全部数据
  13. var e chan int = make(chan int)
  14. //向栈中添加数据
  15. func push1(value int) {
  16. stack1 = append(stack1, value)
  17. fmt.Println(stack1)
  18. }
  19. //从栈中获取数据
  20. func pop1() {
  21. for {
  22. if len(stack1) > 0 {
  23. value := stack1[len(stack1)-1]
  24. stack1 = stack1[:len(stack1)-1]
  25. fmt.Println(value)
  26. } else {
  27. e <- 0
  28. }
  29. }
  30. }
  31. func main() {
  32. for i := 0; i < 10; i++ {
  33. go push1(i)
  34. }
  35. go pop1()
  36. <-e
  37. }

参考:

https://m.imooc.com/article/271255