先序遍历顺序:根=>左=>右
对于任一结点P:
1.访问结点P,并将结点P入栈;
2.判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
3.直到P为NULL并且栈为空,则遍历结束
1.访问结点P,并将结点P入栈;
2.判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
3.直到P为NULL并且栈为空,则遍历结束
所以:
(1)先将根节点入栈,并访问
(2)判断是否有左子树,如果有,将当前p入栈
(3)若当前节点没有左子树,判断其有没有右子树,若有,将其右子树的值给p,若栈已经被去空,将p置为空
(4)若右子树为空,用循环遍历,将stack中栈顶值pop给p,再判断其右子树是否存在,存在将值给p后跳出,不存在就将p置为null;
非递归方法:
public static void getValueFWithLoop(TreeNode node, List<int> outArr)//先序
{
Stack<TreeNode> stack = new Stack<TreeNode>();//作用相当于临时存储节点
TreeNode p = node;//定义临时节点p
while (p!= null||stack.Count != 0)//循环条件:P!=null或stack.count!=0直到当前节点p为NULL且栈空时,循环结束
{
outArr.Add(p.value);//访问p(先,中,后的区别)
if (p.left != null)//如果左子树不为空
{
stack.Push(p);//将p入栈
p = p.left;//p的左子树赋值给p,p变成左子树
}
else//左子树为空
{
if (p.right != null)//如果右子树不为空
{
p = p.right;//p的右子树赋值给p,p变成右子树
}
if (stack.Count == 0)//如果栈已经被取空
{
p = null;//将p置为空
}
else//右子树为空
{
while (stack.Count > 0)
{
p = stack.Pop();//将stack中的值pop给p
if (p.right != null)//如果右子树不为空
{
p = p.right;//把右子树的值给p
break;//跳出循环
}
else
p = null;//p=null
}
}
}
}
}
递归方法:
public static void getValueF(TreeNode node, List<int> outArr)//list中存遍历后的节点,outArr存节点中的值
{
if (node == null)//递归出口,节点为空时跳出
{
return;
}
outArr.Add(node.value);//传入节点值给list///访问节点
if (node.left != null)//遍历左子树
{
getValueF(node.left, outArr);
}
if (node.right != null)//遍历右子树
{
getValueF(node.right, outArr);
}
}