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


    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)
        )
        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		", root.Val)
            if root.Left != nil {
                spew.Printf("l = %d		", root.Left.Val)
            } else {
                spew.Printf("l = nil		")
            }
            if root.Right != nil {
                spew.Printf("r = %d
    ", 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
    }
    
  • 相关阅读:
    CentOS7 时间设置与网络同步
    CentOS7 系统升级,删除centos7开机界面多余选,升级至最新的内核
    Docker 编排工具Rancher 2.0
    Docker 编排工具Rancher 1.6.18
    通过WSL在Windows下安装子Linux系统
    Docker 使用Dockerfile构建redis镜像
    初探PHP多进程
    nginx转发
    mime类型
    socket php
  • 原文地址:https://www.cnblogs.com/janbar/p/13698970.html
Copyright © 2020-2023  润新知