leetcode 94. 二叉树的中序遍历
题目如下
中序遍历通过递归来执行是非常简单的,简单到哪里呢?递归的出栈和入栈的过程很容易帮忙记录下当前节点的双亲节点的信息,当遍历完当前节点后,当前遍历方法出栈,就又回到遍历双亲节点的方法了。若不使用递归的方式,最大的问题就在于,怎么记录双亲节点。
在数据结构上,我们可以在定义树的节点结构时就给他加一个parent属性指向其双亲节点,但是在这道题目中是不可行的,leetcode给的数据结构中树的节点是不包含双亲节点的。
他只是一个最简单的二叉树节点结构,就需要考虑怎么存储子节点和双亲的关系了。我这里使用一个链栈来存储双亲和子节点的关系。
首先,根据中序遍历规则,先遍历左子树。遍历到一个非空节点时,先将其入栈,然后判断其左子树是否为空,若为空,就需要出栈获取第一个右子树不为空的节点(如果在寻找过程中遇到右子树为空的节点,那么根据中序遍历规则,该结点没有右子树,就可以直接输出)。如果找不到一个右子树不为空的节点,也就是说到最后栈为空,表示该树遍历完毕,跳出循环。否则将找到的节点右子树入栈,开始下一次循环,知道栈为空为止。
package main
import "fmt"
//Definition for a binary tree node.
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
type sNode struct {
Node *TreeNode
Next *sNode
}
type stract struct {
Top *sNode
Bottom *sNode
}
func inorderTraversal(root *TreeNode) []int {
tmpv := []int{}
st := stract{
nil,
nil,
}
node := &sNode{
root,
st.Bottom,
}
for (true) {
st.Top = node;
tmp_tn := node.Node;
if (tmp_tn.Left != nil) {
tmp_node := &sNode{
tmp_tn.Left,
node,
}
node = tmp_node
} else {
for (st.Top != nil && st.Top.Node.Right == nil) {
//println(st.Top.Node.Val)
tmpv = append(tmpv,st.Top.Node.Val)
st.Top = st.Top.Next
}
if(st.Top == st.Bottom){
break;
}else{
//println(st.Top.Node.Val)
tmpv = append(tmpv,st.Top.Node.Val)
node = &sNode{
st.Top.Node.Right,
st.Top.Next,
}
st.Top = node
}
}
}
return tmpv
}
func main() {
t1 := &TreeNode{
1,
nil,
nil,
}
t2 := &TreeNode{
2,
nil,
nil,
}
t3 := &TreeNode{
3,
nil,
nil,
}
t4 := &TreeNode{
4,
nil,
nil,
}
t5 := &TreeNode{
5,
nil,
nil,
}
t1.Left = t2
t1.Right = t3
t3.Left = t4
t4.Right = t5
tmm := inorderTraversal(t1)
fmt.Print(tmm)
}