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