1. 递归方法
递归方法比较简单,不过多赘述,直接看代码:
public class BinaryTreeTraversal {
//先序遍历
public void preOrder(TreeNode root){
if(root==null)return;
System.out.print(root.val+" ");
preOrder(root.left);
preOrder(root.right);
}
//中序遍历
public void midOrder(TreeNode root){
if(root==null)return;
midOrder(root.left);
System.out.print(root.val+" ");
midOrder(root.right);
}
//后序遍历
public void postorder(TreeNode root){
if(root==null)return;
postorder(root.left);
postorder(root.right);
System.out.print(root.val+" ");
}
}
2. 非递归方法
非递归的方法,我们要做到多次访问一个节点,需要使用栈来保存之前的信息。递归的方法其实是系统为我们提供的函数栈,非递归则是我们自己用栈来模拟。
1). 先序遍历
先序遍历的规律是:中左右,第一次访问到根节点的时候就打印。要实现这样的访问,我们先将根节点压栈,然后进入一个循环,循环条件是栈不空。然后从栈中弹出一个元素,打印它的值,然后先判断当前的元素是否有右节点,有就压栈;再判断是否有左节点,同样有就压栈。先压右节点再压左节点是为了先弹出左边的节点,再弹出右边的节点。代码如下:
public void preOrderNonrecursive(TreeNode root){
if(root==null)return;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode temp = stack.pop();
System.out.print(temp.val+" ");
if(temp.right!=null)stack.push(temp.right);
if(temp.left!=null)stack.push(temp.left);
}
System.out.println();
}
2). 中序遍历
中序遍历的规律:左中右,当第二次访问到该节点时才打印。要实现这样的访问,我们在压栈时,如果当前节点有左孩子,我们就把左孩子压栈,直到左孩子为空;然后从栈顶弹出一个元素打印,然后判断弹出的元素是否有右孩子,有就把右孩子压栈,然后弹出一个元素,判断是否有左孩子…重复这个循环。代码如下:
public void midOrderNonrecursive(TreeNode root){
if(root==null)return;
Stack<TreeNode> stack =new Stack<>();
TreeNode tempNode = root;
while(!stack.isEmpty()||tempNode!=null){
if(tempNode!=null){
stack.push(tempNode);
tempNode=tempNode.left;
}
else{
tempNode=stack.pop();
System.out.print(tempNode.val+" ");
tempNode= tempNode.right;
}
}
System.out.println();
}
3). 后序遍历
后序遍历的规律:左右中,当第三次访问到该节点时才打印。为了实现这个访问顺序,我们可以先实现 中右左 的访问,然后再把这个访问顺序反过来就是 左右中 的访问,因此,我们可以准备两个栈,其中一个栈用来实现 中右左的访问(参照先序遍历,这次只改为先压左孩子,再压有孩子),另外一个栈用来存储访问顺序,最后弹栈打印。代码如下:
public void postorderNonrecursive(TreeNode root){
if(root==null)return;
Stack<TreeNode> stack1 = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
stack1.push(root);
while(!stack1.isEmpty()){
TreeNode tempNode = stack1.pop();
stack2.push(tempNode);
if(tempNode.left!=null)stack1.push(tempNode.left);
if(tempNode.right!=null)stack1.push(tempNode.right);
}
while(!stack2.isEmpty()){
System.out.print(stack2.pop().val+" ");
}
System.out.println();
}
上面是用两个栈来实现的,还可以用一个栈来实现,代码如下:
public void postorderNonrecursiveOnlyOneStack(TreeNode root){
if(root==null)return;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
TreeNode tempNode = null;
while(!stack.isEmpty()){
tempNode = stack.peek();
if(tempNode.left!=null&&root!=tempNode.left&&root!=tempNode.right){//复用root来标记左孩子和右孩子是否被访问过
stack.push(tempNode.left);
}
else if(tempNode.right!=null&&root!=tempNode.right){
stack.push(tempNode.right);
}
else{
System.out.print(stack.pop().val+" ");
root=tempNode;//复用root来标记左孩子和右孩子是否被访问过
}
}
}
如有错误欢迎指正