递归序
graph TB
A((1))
B((2))
C((3))
D((4))
E((5))
F((6))
G((7))
A-->B
A-->C
B-->D
B-->E
C-->F
C-->G
那么我们用递归遍历这个二叉树
package main
import "fmt"
type Node struct {
value int
left *Node
Right *Node
}
func f(node *Node) {
if node == nil {
return
}
fmt.Print(node.value)
f(node.left)
fmt.Print(node.value)
f(node.Right)
fmt.Print(node.value)
}
func main() {
node1 := &Node{value: 1}
node2 := &Node{value: 2}
node3 := &Node{value: 3}
node4 := &Node{value: 4}
node5 := &Node{value: 5}
node6 := &Node{value: 6}
node7 := &Node{value: 7}
node1.left = node2
node1.Right = node3
node2.left = node4
node2.Right = node5
node3.left = node6
node3.Right = node7
f(node1)
}
打印结果为: 124442555213666377731 ,每个数都调用三次,这个就是递归序
先序就是 头左右的顺序:1245367 ,等效于递归序每个数字第一次打印
中序就是 左头右的顺序: 4251637, 等效于递归序每个数字第二次打印
后序就是 左右头的顺序:4526731,等效于递归序每个数字第三次打印
任何递归函数都可以改成非递归
先序遍历:创建一个栈,先将1丢入栈中,进入循环:从栈中弹出一个数,打印。再将右节点和左节点依次放入栈中,周而复始。
func stack(head *Node) {
// 初始化
var stack []*Node
// 入栈
stack = append(stack, head)
for len(stack) != 0 {
//弹出
head = stack[len(stack)-1]
//出栈
stack = stack[:len(stack)-1]
fmt.Print(head.value)
if head.Right != nil {
stack = append(stack, head.Right)
}
if head.left != nil {
stack = append(stack, head.left)
}
}
}
打印:1245367
后序:先序是头左右,将上面方法调整弹出顺序头右左,依次放入另一个栈中,得到逆序就是左右头
中序:将左边界的数存进stack,然后弹出一个数时打印,并且放入right
package main
import (
"fmt"
)
type Node struct {
value int
left *Node
Right *Node
}
func f(node *Node) {
if node == nil {
return
}
fmt.Print(node.value)
f(node.left)
fmt.Print(node.value)
f(node.Right)
fmt.Print(node.value)
}
func stack(head *Node) {
fmt.Println()
// 初始化
var stack []*Node
// 入栈
stack = append(stack, head)
for len(stack) != 0 {
head = stack[len(stack)-1]
//出栈
stack = stack[:len(stack)-1]
fmt.Print(head.value)
if head.Right != nil {
stack = append(stack, head.Right)
}
if head.left != nil {
stack = append(stack, head.left)
}
}
}
func stackM(head *Node) {
fmt.Println()
// 初始化
var stack []*Node
for len(stack) != 0 || head != nil {
if head != nil { //先把左的全部存完
stack = append(stack, head)
head = head.left
} else {
head = stack[len(stack)-1]
stack = stack[:len(stack)-1]
fmt.Print(head.value)
head = head.Right
}
}
}
func stackA(head *Node) {
fmt.Println()
// 初始化
var stack []*Node
var after []*Node
// 入栈
stack = append(stack, head)
for len(stack) != 0 {
head = stack[len(stack)-1]
//出栈
stack = stack[:len(stack)-1]
after = append(after, head)
if head.left != nil {
stack = append(stack, head.left)
}
if head.Right != nil {
stack = append(stack, head.Right)
}
}
for len(after) != 0 {
fmt.Print(after[len(after)-1].value)
after = after[:len(after)-1]
}
}
func main() {
node1 := &Node{value: 1}
node2 := &Node{value: 2}
node3 := &Node{value: 3}
node4 := &Node{value: 4}
node5 := &Node{value: 5}
node6 := &Node{value: 6}
node7 := &Node{value: 7}
node1.left = node2
node1.Right = node3
node2.left = node4
node2.Right = node5
node3.left = node6
node3.Right = node7
f(node1)
stack(node1)
stackM(node1)
stackA(node1)
}
宽度遍历
func w(head *Node) {
fmt.Println()
if head == nil {
return
}
var queue []*Node
queue = append(queue, head)
for len(queue) != 0 {
cur := queue[0]
queue = queue[1:]
fmt.Print(cur.value)
if cur.left != nil {
queue = append(queue, cur.left)
}
if cur.Right != nil {
queue = append(queue, cur.Right)
}
}
}
获取最大宽度
package main
import (
"fmt"
)
type Node struct {
value int
left *Node
Right *Node
}
func f(node *Node) {
if node == nil {
return
}
fmt.Print(node.value)
f(node.left)
fmt.Print(node.value)
f(node.Right)
fmt.Print(node.value)
}
func stack(head *Node) {
fmt.Println()
// 初始化
var stack []*Node
// 入栈
stack = append(stack, head)
for len(stack) != 0 {
head = stack[len(stack)-1]
//出栈
stack = stack[:len(stack)-1]
fmt.Print(head.value)
if head.Right != nil {
stack = append(stack, head.Right)
}
if head.left != nil {
stack = append(stack, head.left)
}
}
}
func stackM(head *Node) {
fmt.Println()
// 初始化
var stack []*Node
for len(stack) != 0 || head != nil {
if head != nil { //先把左的全部存完
stack = append(stack, head)
head = head.left
} else {
head = stack[len(stack)-1]
stack = stack[:len(stack)-1]
fmt.Print(head.value)
head = head.Right
}
}
}
func stackA(head *Node) {
fmt.Println()
// 初始化
var stack []*Node
var after []*Node
// 入栈
stack = append(stack, head)
for len(stack) != 0 {
head = stack[len(stack)-1]
//出栈
stack = stack[:len(stack)-1]
after = append(after, head)
if head.left != nil {
stack = append(stack, head.left)
}
if head.Right != nil {
stack = append(stack, head.Right)
}
}
for len(after) != 0 {
fmt.Print(after[len(after)-1].value)
after = after[:len(after)-1]
}
}
func w(head *Node) {
fmt.Println()
if head == nil {
return
}
var queue []*Node
queue = append(queue, head)
for len(queue) != 0 {
cur := queue[0]
queue = queue[1:]
fmt.Print(cur.value)
if cur.left != nil {
queue = append(queue, cur.left)
}
if cur.Right != nil {
queue = append(queue, cur.Right)
}
}
}
func getMaxWidth(head *Node) {
fmt.Println()
if head == nil {
return
}
var queue []*Node
queue = append(queue, head)
levelMap := make(map[*Node]int)
levelMap[head] = 1
curLevel, nodeCounts, max := 1, 0, 0
for len(queue) != 0 {
cur := queue[0]
queue = queue[1:]
nodeLevel := levelMap[cur]
if nodeLevel == curLevel {
nodeCounts++
} else {
if nodeCounts > max {
max = nodeCounts
}
curLevel++
nodeCounts = 1
}
if cur.left != nil {
levelMap[cur.left] = nodeLevel + 1
queue = append(queue, cur.left)
}
if cur.Right != nil {
levelMap[cur.Right] = nodeLevel + 1
queue = append(queue, cur.Right)
}
}
if nodeCounts > max {
max = nodeCounts
}
fmt.Print(max)
}
func main() {
node1 := &Node{value: 1}
node2 := &Node{value: 2}
node3 := &Node{value: 3}
node4 := &Node{value: 4}
node5 := &Node{value: 5}
node6 := &Node{value: 6}
node7 := &Node{value: 7}
node1.left = node2
node1.Right = node3
node2.left = node4
node2.Right = node5
node3.left = node6
node3.Right = node7
f(node1)
stack(node1)
stackM(node1)
stackA(node1)
w(node1)
getMaxWidth(node1)
}
判断是否是搜索二叉树
每个节点都大于左,小于右
graph TB
A((1))
B((2))
C((3))
D((4))
E((5))
F((6))
G((7))
D-->B
D-->F
B-->A
B-->C
F-->E
F-->G
我们利用中序遍历(左头右)得到1234567的数组,如果它是从小到大排列,则是搜索二叉树
package main
import (
"fmt"
"math"
)
type Node struct {
value int
left *Node
Right *Node
}
var LastValue = math.MinInt
func checkBST(head *Node) bool {
if head == nil {
return true
}
if !checkBST(head.left) {
return false
}
fmt.Print(head.value)
if head.value >= LastValue {
LastValue = head.value
} else {
return false
}
return checkBST(head.Right)
}
func main() {
node1 := &Node{value: 1}
node2 := &Node{value: 2}
node3 := &Node{value: 3}
node4 := &Node{value: 4}
node5 := &Node{value: 5}
node6 := &Node{value: 6}
node7 := &Node{value: 7}
node4.left = node2
node4.Right = node6
node2.left = node1
node2.Right = node3
node6.left = node5
node6.Right = node7
fmt.Print(checkBST(node4))
}
套路
对于所有的树形DP(动态规划),适用于跟左数和右树要信息,就可以得到当前解的题目。
我们根据 条件-返回值 ,就可以实现
如搜索二叉树,条件是当前节点的左树和右树都是BST,当前值要大于左树最大值,当前值要小于右树最小值
所以返回值需要IsBST,min,max
type returnValue struct {
IsBST bool
Min int
Max int
}
func checkBST(head *Node) *returnValue {
if head == nil {
return nil
}
left := checkBST(head.left)
right := checkBST(head.Right)
var rV = &returnValue{IsBST: true, Min: head.value, Max: head.value}
if left != nil {
if left.IsBST == false || head.value < left.Max {
rV.IsBST = false
} else {
rV.Min = left.Min
}
}
if right != nil {
if right.IsBST == false || head.value > right.Min {
rV.IsBST = false
} else {
rV.Max = right.Max
}
}
return rV
}
如判断是否满二叉树,条件是所有节点的个数和高度满足 nodes=2^height-1
那么返回值就是nodes,左树节点个数加上右树节点个数加上当前节点个数 height,左树和右树比较高的那个,加上当前的节点1的高度
type fullRetrun struct {
height int
nodes int
}
func fullProcess(head *Node) *fullRetrun {
var fr = &fullRetrun{
height: 0,
nodes: 0,
}
if head == nil {
return fr
}
left := fullProcess(head.left)
right := fullProcess(head.Right)
fr.height = max(left.height, right.height) + 1
fr.nodes = left.nodes + right.nodes + 1
return fr
}
func isFull(head *Node) bool {
fr := fullProcess(head)
return fr.nodes == (1<<fr.height - 1)
}
经验
看别人二叉树的代码
拿张纸,拿只笔
他们有多少变量,我们就在纸上画多少个变量
然后根据他的循环在纸上还原出来,比一直硬着看好很多