func Test_Traversal_Ztree(t *testing.T){
head := new(TreeNode)
head.Val=5
left:= new(TreeNode)
left.Val=4
right:= new(TreeNode)
right.Val=6
head.Right=right
left01:= new(TreeNode)
left01.Val=1
left.Left=left01
right02:= new(TreeNode)
right02.Val=2
left.Right=right02
head.Left=left
fmt.Printf("bf_left_ztree:%v \n",traversal_left_ztree(head))
fmt.Printf("bf_center_ztree:%v \n",traversal_center_ztree(head))
fmt.Printf("bf_right_ztree:%v \n",traversal_right_ztree(head))
fmt.Printf("=================== \n")
fmt.Printf("bf_left_ztree:%v \n",traversal_left_ztree_unity(head))
fmt.Printf("bf_left_center_unity:%v \n",traversal_center_ztree_unity(head))
fmt.Printf("bf_right_ztree:%v \n",traversal_right_ztree_unity(head))
}
//
/*
那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。如何标记呢?
就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。 这种方法也可以叫做标记法。
前序遍历 遍历方法:根左右
故压栈顺序:右左根
*/
func traversal_left_ztree_unity(root *TreeNode) []int {
var at []int
st := list.New()
if root!=nil{
st.PushBack(root)
}
for st.Len()>0{
e:=st.Back()
st.Remove(e)
if e.Value==nil{//如果是标志符则说明下一个节点需要记录该节点的值
e=st.Back()
st.Remove(e)
node := e.Value.(*TreeNode)
at = append(at, node.Val)
continue
}
node := e.Value.(*TreeNode)
if node.Right != nil{
st.PushBack(node.Right)
}
if node.Left!=nil{
st.PushBack(node.Left)
}
st.PushBack(node)
st.PushBack(nil)//向栈中压入标志符
}
return at
}
//前序遍历 根左右
func traversal_left_ztree(root *TreeNode) []int {
var at []int
st := list.New()
if root!=nil{
st.PushBack(root)
}
for st.Len()>0{
node := st.Remove(st.Back()).(*TreeNode)
at = append(at, node.Val)
if node.Right != nil{//注意要点:先往队列或栈放右,栈原则是先进后出,最终根左右,故先放右,再放左
st.PushBack(node.Right)
}
if node.Left!=nil{
st.PushBack(node.Left)
}
}
return at
}
//中序遍历:左根右
func traversal_center_ztree(root *TreeNode) []int {
var at []int
st := list.New()
cur:=root
for cur!=nil || st.Len()>0{
if cur!=nil{
st.PushBack(cur)
cur=cur.Left
}else{
cur = st.Remove(st.Back()).(*TreeNode)
at=append(at, cur.Val)
cur=cur.Right
}
}
return at
}
/*
中序遍历,遍历方法:左根右
故压栈的顺序:右根左
*/
func traversal_center_ztree_unity(root *TreeNode) []int {
var at []int
st := list.New()
if root!=nil{
st.PushBack(root)
}
for st.Len()>0{
e:=st.Back()
st.Remove(e)
if e.Value==nil{//如果是标志符则说明下一个节点需要拼接
e=st.Back()
st.Remove(e)
node := e.Value.(*TreeNode)
at = append(at, node.Val)
continue
}
node := e.Value.(*TreeNode)
if node.Right != nil{
st.PushBack(node.Right)
}
st.PushBack(node)
st.PushBack(nil)//向栈中压入标志符
if node.Left!=nil{
st.PushBack(node.Left)
}
}
return at
}
//后序遍历:左右根 要点是前序遍历反转之后就成根左右了
func traversal_right_ztree(root *TreeNode) []int {
var at []int
st := list.New()
if root!=nil{
st.PushBack(root)
}
for st.Len()>0{
node := st.Remove(st.Back()).(*TreeNode)
at = append(at, node.Val)
if node.Left!=nil{
st.PushBack(node.Left)
}
if node.Right != nil{
st.PushBack(node.Right)
}
}
reverse(at)
return at
}
/*
后序遍历,遍历方法:左右根
故压栈的顺序:根右左
*/
func traversal_right_ztree_unity(root *TreeNode) []int {
var at []int
st := list.New()
if root!=nil{
st.PushBack(root)
}
for st.Len()>0{
e:=st.Back()
st.Remove(e)
if e.Value==nil{//如果是标志符则说明下一个节点需要拼接
e=st.Back()
st.Remove(e)
node := e.Value.(*TreeNode)
at = append(at, node.Val)
continue
}
node := e.Value.(*TreeNode)
st.PushBack(node)
st.PushBack(nil)//向栈中压入标志符
if node.Right != nil{
st.PushBack(node.Right)
}
if node.Left!=nil{
st.PushBack(node.Left)
}
}
return at
}
func reverse(arr []int) {
for i := 0; i < len(arr)/2; i++ {
arr[i], arr[len(arr)-i-1] = arr[len(arr)-i-1], arr[i]
}
}
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}