当前位置 博文首页 > Janbar:二叉树相关处理,包含递归和非递归方法

    Janbar:二叉树相关处理,包含递归和非递归方法

    作者:[db:作者] 时间:2021-06-17 18:17

    1.简介

    1. 熟悉二叉树的各种特性,包括前序、中序、后序遍历,以及还原二叉树等等
    2. 主要搜集了递归和非递归方案,可以对比研究下
    3. 学习这个也是为了再leetcode上刷题
    4. 下面程序运行结果
      <*>{1 <*>{2 <*>{0 <*>{3 <*>{4 <*>{0 <*>{5 }}}}}}}
      node = 1 l = 2 r = 3
      node = 2 l = 4 r = 5
      node = 4 l = 8 r = nil
      node = 8 l = nil r = nil
      node = 5 l = nil r = 9
      node = 9 l = nil r = nil
      node = 3 l = 6 r = 7
      node = 6 l = nil r = 10
      node = 10 l = nil r = nil
      node = 7 l = 11 r = nil
      node = 11 l = nil r = nil
      ----------- in testRecursive
      pre: [1,2,4,8,5,9,3,6,10,7,11]
      mid: [8,4,2,5,9,1,6,10,3,11,7]
      post: [8,4,9,5,2,10,6,11,7,3,1]
      level: [1,2,3,4,5,6,7,8,9,10,11]
      pre+mid: true
      mid+post: true
      ----------- out testRecursive
      ----------- in testTraverse
      pre: [1,2,4,8,5,9,3,6,10,7,11]
      mid: [8,4,2,5,9,1,6,10,3,11,7]
      post: [8,4,9,5,2,10,6,11,7,3,1]
      level: [1,2,3,4,5,6,7,8,9,10,11]
      pre+mid: true
      mid+post: true
      ----------- out testTraverse
    package main
    
    import (
        "encoding/json"
    
        "github.com/davecgh/go-spew/spew"
    )
    
    func main() {
        list := NewListNode("[1,2,null,3,4,null,5]")
        spew.Println(list)
        /*
                  1
               /     \
              2        3
             / \     /   \
            4   5   6     7
           /     \   \   /
          8       9  10 11   */
        root := &TreeNode{
            Val: 1,
            Left: &TreeNode{
                Val: 2,
                Left: &TreeNode{
                    Val: 4,
                    Left: &TreeNode{
                        Val: 8,
                    },
                },
                Right: &TreeNode{
                    Val: 5,
                    Right: &TreeNode{
                        Val: 9,
                    },
                },
            },
            Right: &TreeNode{
                Val: 3,
                Left: &TreeNode{
                    Val: 6,
                    Right: &TreeNode{
                        Val: 10,
                    },
                },
                Right: &TreeNode{
                    Val: 7,
                    Left: &TreeNode{
                        Val: 11,
                    },
                },
            },
        }
        printTree(root)
        testRecursive(root)
        testTraverse(root)
    }
    
    /*测试非递归解法*/
    func testTraverse(root *TreeNode) {
        spew.Println("----------- in testTraverse")
        defer spew.Println("----------- out testTraverse")
        b, _ := json.Marshal(preOrder(root))
        pre := string(b)
        b, _ = json.Marshal(midOrder(root))
        mid := string(b)
        b, _ = json.Marshal(postOrder(root))
        post := string(b)
        b, _ = json.Marshal(levelOrder(root))
        level := string(b)
        spew.Println("pre:", pre)
        spew.Println("mid:", mid)
        spew.Println("post:", post)
        spew.Println("level:", level)
        tmp := NewTreeNode(pre, mid, 1, false)
        spew.Println("pre+mid:", isSameTree(root, tmp))
        tmp = NewTreeNode(mid, post, 2, false)
        spew.Println("mid+post:", isSameTree(root, tmp))
    }
    
    /*测试递归解法*/
    func testRecursive(root *TreeNode) {
        spew.Println("----------- in testRecursive")
        defer spew.Println("----------- out testRecursive")
        b, _ := json.Marshal(treeOrder(root, 1))
        pre := string(b)
        b, _ = json.Marshal(treeOrder(root, 2))
        mid := string(b)
        b, _ = json.Marshal(treeOrder(root, 3))
        post := string(b)
        b, _ = json.Marshal(treeOrder(root, 4))
        level := string(b)
        spew.Println("pre:", pre)
        spew.Println("mid:", mid)
        spew.Println("post:", post)
        spew.Println("level:", level)
        tmp := NewTreeNode(pre, mid, 1, true)
        spew.Println("pre+mid:", isSameTree(root, tmp))
        tmp = NewTreeNode(mid, post, 2, true)
        spew.Println("mid+post:", isSameTree(root, tmp))
    
    }
    
    type (
        TreeNode struct {
            Val   int
            Left  *TreeNode
            Right *TreeNode
        }
        ListNode struct {
            Val  int
            Next *ListNode
        }
    )
    
    func arrayFromString(val string) ([]int, int) {
        var res []int /* [1,2,3,null,4,5],null=0 */
        if json.Unmarshal([]byte(val), &res) != nil {
            return nil, 0
        }
        return res, len(res)
    }
    
    /*根据输入得到一个链表*/
    func NewListNode(val string) *ListNode {
        arr, la := arrayFromString(val)
        if la == 0 {
            return nil
        }
        head := &ListNode{Val: arr[0]}
        p := head
        for i := 1; i < la; i++ {
            p.Next = &ListNode{Val: arr[i]}
            p = p.Next
        }
        return head
    }
    
    /*根据2个序列还原二叉树*/
    func NewTreeNode(s0, s1 string, mode int, isRecursive bool) *TreeNode {
        a0, l0 := arrayFromString(s0)
        a1, l1 := arrayFromString(s1)
        if l0 != l1 || l0 == 0 {
            return nil
        }
        switch mode {
        case 1: /*先序+中序*/
            if isRecursive { /*递归*/
                return preOrMidRecursive(a0, a1, 0, l0, 0, l0)
            }
            return preOrMidTraverse(a0, a1, l0)
        case 2: /*中序+后序*/
            if isRecursive { /*递归*/
                return midOrPostRecursive(a0, a1, 0, l0, 0, l0)
            }
            return midOrPostTraverse(a0, a1, l0)
        }
        return nil
    }
    
    /*中序+后序还原二叉树,非递归*/
    func midOrPostTraverse(mid []int, post []int, length int) *TreeNode {
        var (
            root      = &TreeNode{Val: post[length-1]}
            isVisited = make([]bool, length)
            rootIndex = intIndex(mid, post[length-1])
            i, cur    = length - 2, root
            st        = NewStackQueue(nil, nil)
        )