欲买桂花同载酒,荒泷天下第一斗。|

janbar

园龄:4年6个月 粉丝:29 关注:10

2020-09-17 21:14 阅读 78 评论 0 推荐

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

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
copy
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 }
posted @   janbar  阅读(78)  评论(0编辑  收藏  举报
编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~

FAVOURITE

点击右上角即可分享
微信分享提示
*✧⁺˚⁺ପ(๑・ω・)੭ु⁾⁾ 好好学习天天向上
进入亮色模式
进入亮色模式

FAVOURITE