二叉树树的前,中,后序遍历非递归--go语言实现

递归遍历二叉树非常简单,只要交换调用顺序即可,那么非递归呢,我这里都是借用栈的思想实现的

前序遍历

实现:第一次访问的时候就记录到结果数组中,然后进栈,依次访问其左孩子,知道左孩子为空弹出栈顶,访问其右孩子,循环这个过程,直到栈为空,root也为空

代码:

func (root *TreeNode) preorder() []int{       //非递归前序遍历
	res:=[]int{}
	if root==nil{
		return res
	}
	stack:=[]*TreeNode{}           //定义一个栈储存节点信息
	for root!=nil || len(stack)!=0{
		if root!=nil{
			res=append(res,root.data)
			stack=append(stack,root)        
			root=root.Lchild
		}else{
			root=stack[len(stack)-1]
			stack=stack[:len(stack)-1]
			root=root.Rchild
		}
	}
	return res
}

中序遍历

实现:根前序很相似,只是改变一下顺序,从栈中弹出的时候(第二次访问)才放进结果数组

代码:

func (root *TreeNode) inorder()[]int{
	res:=[]int{}
	if root==nil{
		return res
	}
	stack:=[]*TreeNode{}
	for root!=nil || len(stack)!=0{
		if root!=nil{
			stack=append(stack,root)
			root=root.Lchild
		}else{
			root=stack[len(stack)-1]
			res=append(res,root.data)
			stack=stack[:len(stack)-1]
			root=root.Rchild
		}
	}
	return res
}

后序遍历

前序中序都比较简单,而且很相似,后序就稍微复杂一下了

实现:这里要增加一个辅助节点来节点上一次放入结果数组的值,当一个节点左右都是空的时候,就可以放入结果集,当上一个放入结果集的节点是他的孩子节点的时候,说明他的孩子已经访问完成了,到这里就是第三次了就可以放入了,还有一点要注意的是,当一个节点的左右不为空时,要先加入右孩子,再加入左孩子,这样才能先访问左孩子。

func (root *TreeNode)postorder() []int {
	res:=[]int{}
	if root==nil{
		return res
	}
	stack:=[]*TreeNode{}
	pre:=&TreeNode{}
	stack=append(stack,root)
	for len(stack)!=0{
		cur:=stack[len(stack)-1]
		if (cur.Lchild==nil && cur.Rchild==nil) || (pre!=nil &&(pre==cur.Lchild || pre==cur.Rchild)){
			res=append(res,cur.data)
			pre=cur
			stack=stack[:len(stack)-1]
		}else{
			if cur.Rchild!=nil{
				stack=append(stack,cur.Rchild)
			}
			if cur.Lchild!=nil{
				stack=append(stack,cur.Lchild)
			}
		}
	}
	return res
}

猜你喜欢

转载自blog.csdn.net/LYue123/article/details/88836008