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

1.简介

  1. 熟悉二叉树的各种特性,包括前序、中序、后序遍历,以及还原二叉树等等
  2. 主要搜集了递归和非递归方案,可以对比研究下
  3. 学习这个也是为了再leetcode上刷题
  4. 下面程序运行结果
    <*>{1 <*>{2 <*>{0 <*>{3 <*>{4 <*>{0 <*>{5 <nil>}}}}}}}

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)
    )
    length--
    isVisited[rootIndex] = true
    for i >= 0 {
        if rootIndex < length && !isVisited[rootIndex+1] {
            cur.Right = &TreeNode{Val: post[i]}
            rootIndex = intIndex(mid, post[i])
            isVisited[rootIndex] = true
            i--
            st.LeftPush(cur)
            cur = cur.Right
        } else if rootIndex > 0 && !isVisited[rootIndex-1] {
            cur.Left = &TreeNode{Val: post[i]}
            rootIndex = intIndex(mid, post[i])
            isVisited[rootIndex] = true
            i--
            cur = cur.Left
        } else {
            cur = st.LeftPop().(*TreeNode)
            rootIndex = intIndex(mid, cur.Val)
        }
    }
    return root
}

func intIndex(val []int, k int) int {
    for i, v := range val {
        if k == v {
            return i
        }
    }
    return -1
}

/*先序+中序还原二叉树,非递归*/
func preOrMidTraverse(pre []int, mid []int, length int) *TreeNode {
    var (
        root      = &TreeNode{Val: pre[0]}
        isVisited = make([]bool, length)
        rootIndex = intIndex(mid, pre[0])
        i, cur    = 1, root
        st        = NewStackQueue(nil, nil)
    )
    isVisited[rootIndex] = true
    for i < length {
        if rootIndex > 0 && !isVisited[rootIndex-1] {
            cur.Left = &TreeNode{Val: pre[i]}
            rootIndex = intIndex(mid, pre[i])
            isVisited[rootIndex] = true
            i++
            st.LeftPush(cur)
            cur = cur.Left
        } else if rootIndex < length && !isVisited[rootIndex+1] {
            cur.Right = &TreeNode{Val: pre[i]}
            rootIndex = intIndex(mid, pre[i])
            i++
            isVisited[rootIndex] = true
            cur = cur.Right
        } else {
            cur = st.LeftPop().(*TreeNode)
            rootIndex = intIndex(mid, cur.Val)
        }
    }
    return root
}

/*中序+后序还原二叉树,递归*/
func midOrPostRecursive(mid, post []int, mid0, mid1, post0, post1 int) *TreeNode {
    if mid0 < mid1 && post0 < post1 {
        val, span := post[post1-1], 0
        for ; span < mid1; span++ {
            if val == mid[span+mid0] {
                break
            }
        }
        return &TreeNode{
            Val:   val,
            Left:  midOrPostRecursive(mid, post, mid0, mid0+span, post0, post0+span),
            Right: midOrPostRecursive(mid, post, mid0+span+1, mid1, post0+span, post1-1),
        }
    }
    return nil
}

/*先序+中序还原二叉树,递归*/
func preOrMidRecursive(pre, mid []int, pre0, pre1, mid0, mid1 int) *TreeNode {
    if pre0 < pre1 && mid0 < mid1 {
        val, span := pre[pre0], 0
        for ; span < mid1; span++ {
            if val == mid[span+mid0] {
                break
            }
        }
        return &TreeNode{
            Val:   val,
            Left:  preOrMidRecursive(pre, mid, pre0+1, pre0+1+span, mid0, mid0+span),
            Right: preOrMidRecursive(pre, mid, pre0+1+span, pre1, mid0+span+1, mid1),
        }
    }
    return nil
}

/*递归得到先序,中序,后序,层次遍历结果*/
func treeOrder(root *TreeNode, mode int) []int {
    var (
        ret []int      /*结果*/
        dep = []int{0} /*最大深度+与ret对应深度*/
    )
    listTree(root, &ret, &dep, 1, mode)
    if mode < 4 {
        return ret
    }
    tmp := make([]int, 0, len(ret))
    for i := 1; i <= dep[0]; i++ {
        for j := 1; j < len(dep); j++ {
            if dep[j] == i {
                tmp = append(tmp, ret[j-1])
            }
        }
    }
    return tmp
}

func listTree(root *TreeNode, ret, dep *[]int, depI, mode int) {
    if root == nil {
        return
    }
    if mode == 1 { /*先序*/
        *ret = append(*ret, root.Val)
    } else if mode == 4 { /*层次*/
        *ret = append(*ret, root.Val)
        *dep = append(*dep, depI)
        if (*dep)[0] < depI {
            (*dep)[0] = depI
        }
    }
    listTree(root.Left, ret, dep, depI+1, mode)
    if mode == 2 { /*中序*/
        *ret = append(*ret, root.Val)
    }
    listTree(root.Right, ret, dep, depI+1, mode)
    if mode == 3 { /*后序*/
        *ret = append(*ret, root.Val)
    }
}

/*先序*/
func preOrder(root *TreeNode) []int {
    if root == nil {
        return nil
    }
    s := NewStackQueue(root, nil)
    var ret []int
    for !s.IsEmpty() {
        root = s.LeftPop().(*TreeNode)
        ret = append(ret, root.Val)
        if root.Right != nil {
            s.LeftPush(root.Right)
        }
        if root.Left != nil {
            s.LeftPush(root.Left)
        }
    }
    return ret
}

/*中序*/
func midOrder(root *TreeNode) []int {
    s := NewStackQueue(nil, nil)
    var ret []int
    for {
        if root != nil {
            s.LeftPush(root)
            root = root.Left
        } else if s.IsEmpty() {
            break
        } else {
            root = s.LeftPop().(*TreeNode)
            ret = append(ret, root.Val)
            root = root.Right
        }
    }
    return ret
}

/*后序*/
func postOrder(root *TreeNode) []int {
    var ret []int
    s := NewStackQueue(nil, nil)
    last := root
    for root != nil || !s.IsEmpty() {
        for root != nil {
            s.LeftPush(root)
            root = root.Left
        }
        top := s.LeftTop().(*TreeNode)
        if top.Right == nil || top.Right == last {
            ret = append(ret, top.Val)
            s.LeftPop()
            last = top
        } else {
            root = top.Right
        }
    }
    return ret
}

/*层次*/
func levelOrder(root *TreeNode) []int {
    if root == nil {
        return nil
    }
    q := NewStackQueue(root, nil)
    var res []int
    for !q.IsEmpty() {
        node := q.RightPop().(*TreeNode)
        res = append(res, node.Val)
        if node.Left != nil {
            q.LeftPush(node.Left)
        }
        if node.Right != nil {
            q.LeftPush(node.Right)
        }
    }
    return res
}

/*比较2个树是否完全相等*/
func isSameTree(t1, t2 *TreeNode) bool {
    if t1 == nil && t2 == nil {
        return true
    }
    if t1 == nil || t2 == nil {
        return false
    }
    return t1.Val == t2.Val &&
        isSameTree(t1.Left, t2.Left) && isSameTree(t1.Right, t2.Right)
}

/*打印树*/
func printTree(root *TreeNode) {
    if root != nil {
        spew.Printf("node = %d\t\t", root.Val)
        if root.Left != nil {
            spew.Printf("l = %d\t\t", root.Left.Val)
        } else {
            spew.Printf("l = nil\t\t")
        }
        if root.Right != nil {
            spew.Printf("r = %d\n", root.Right.Val)
        } else {
            spew.Println("r = nil")
        }
        if root.Left != nil {
            printTree(root.Left)
        }
        if root.Right != nil {
            printTree(root.Right)
        }
    }
}

/**
* 创建一个栈或者队列,data表示初始元素,为nil表示创建空栈或空队列
* p判断优先级,p != nil时所有元素按照p的规则排序
* 我的leetcode刷题专用栈和队列结构
**/
func NewStackQueue(data interface{}, p func(a, b interface{}) bool) *StackQueue {
    res := &StackQueue{priority: p}
    if data != nil {
        res.length = 1
        res.data = &sqData{data: data}
    }
    return res
}

type (
    StackQueue struct {
        length   int
        priority func(a, b interface{}) bool
        data     *sqData
    }
    sqData struct {
        data interface{}
        next *sqData
    }
)

func (sq *StackQueue) IsEmpty() bool {
    return sq.length == 0
}

func (sq *StackQueue) Len() int {
    return sq.length
}

func (sq *StackQueue) LeftTop() interface{} {
    if sq.length == 0 {
        return nil
    }
    return sq.data.data
}

func (sq *StackQueue) LeftPush(data interface{}) {
    if sq.priority == nil {
        sq.data = &sqData{data: data, next: sq.data}
    } else { /* 按照优先级插入 */
        if p := sq.data; p == nil {
            sq.data = &sqData{data: data}
        } else if p.next == nil {
            if sq.priority(p.data, data) {
                p.next = &sqData{data: data}
            } else {
                sq.data = &sqData{data: data, next: p}
            }
        } else {
            q := p
            for p.next != nil && sq.priority(p.data, data) {
                q = p
                p = p.next
            }
            if p == sq.data {
                sq.data = &sqData{data: data, next: p}
            } else if p.next == nil && sq.priority(p.data, data) {
                p.next = &sqData{data: data}
            } else {
                q.next = &sqData{data: data, next: q.next}
            }
        }
    }
    sq.length++
}

func (sq *StackQueue) LeftPop() interface{} {
    if sq.length == 0 {
        return nil
    }
    data := sq.data.data
    sq.data = sq.data.next
    sq.length--
    return data
}

func (sq *StackQueue) RightPop() (data interface{}) {
    if sq.length == 0 {
        return
    }
    if p := sq.data; p.next == nil {
        data = p.data
        sq.data = nil
    } else {
        for p.next.next != nil {
            p = p.next
        }
        data = p.next.data
        p.next = nil
    }
    sq.length--
    return
}

captcha