递归遍历
前序遍历就是把输出放前面,中序后序以此类推。
public void print(Node node){
if (node!=null){
print(node.lift);
print(node.right);
System.out.println(node.data);
}
}
非递归前序、中序遍历
代码的基本结构都一样,使用两个while,或是一个while嵌套一个if-else。
要使用栈,从根节点开始压栈,一直压到最左边,然后转到右节点。
值得注意的是,叶子节点转到右节点时,因为右边是空结点,所以直接进入下一轮循环,即遍历叶子节点的父节点的右节点。
入栈时输出为前序遍历,出栈时输出为中续遍历。
//非递归前序遍历
public void preOrd(Node root){
Stack<Node> stack=new Stack<Node>();
Node current=root;
if (root==null){
return;
}
while (current!=null||!stack.isEmpty()){
while (current!=null){ // 这种while和下面那种if-else都可以
System.out.println(current.data);
stack.push(current);
current=current.lift;
}
current=stack.pop();
current=current.right;
}
}
//非递归中序遍历
public void midOrd(Node root){
if (root==null){
return;
}
Stack<Node> stack=new Stack<Node>();
Node current=root;
while (current!=null||!stack.isEmpty()){
if (current!=null){
stack.push(current);
current=current.lift;
}else {
current=stack.pop();
System.out.println(current.data);
current=current.right;
}
}
}
非递归后序遍历
stack2用来标记哪边访问完了。
如果访问完了左子树,那继续访问右子树。 而如果访问完了右子树,那就要输出根节点。
这个算法的关键问题在于,只有当没有右子树时才会进行输出;
所以,要先访问左子树,再判断是否要输出,再访问右子树。
public void postOrd(Node root){
if (root==null){
return;
}
Node current=root;
Stack<Node> stack1=new Stack<Node>();
Stack<String> stack2=new Stack<String>();
while (current!=null||!stack1.isEmpty()){
//首先遍历左子树和沿途根节点,入栈
while (current!=null){
stack1.push(current);
stack2.push("left");
current=current.lift;
}
//判断是否需要输出
while (!stack1.isEmpty()&&stack2.peek()=="right"){
current=stack1.pop();
stack2.pop();
System.out.println(current.data);
//要手动跳出,这个方法不能自动跳出
if (stack1.isEmpty()){
return;
}
}
//转到右边进行遍历
if (!stack1.isEmpty()){
current=stack1.peek().right;
stack2.pop();
stack2.push("right");
}
}
}