二叉树的遍历-先序中序后序层次(java实现)

二叉树的结构

public class TreeNode{
    int data;
    Treenode left;
    Treenode right;
    void Treenode(int data){
        this.data = data;
    }
}

遍历

即将树的所有结点访问且仅访问一次。按照根节点位置的不同分为前序遍历,中序遍历,后序遍历。
前序遍历:根节点->左子树->右子树
中序遍历:左子树->根节点->右子树
后序遍历:左子树->右子树->根节点

递归与非递归实现

非递归使用Stack
前序遍历

//递归
void traverse(TreeNode node){
        if(node != null){
            System.out.println("data:" + node.data);
            traverse(node.left);
            traverse(node.right);
        }
    }
//非递归
void preOrderTraverse(TreeNode root){
        Stack<TreeNode> stack = new Stack<>();
        TreeNode t = root;
        while(t != null || !stack.isEmpty()){
            while(t != null){
                stack.push(t);
                System.out.print(t.data + " ");
                t = t.left;
            }
            if(!stack.isEmpty()){
                t = stack.pop();
                t = t.right;
            }
        }
    }

中序遍历

//递归
void traverse(TreeNode node){
        if(node != null){
            traverse(node.left);
            System.out.println("data:" + node.data);
            traverse(node.right);
        }
    }
//非递归
void inOrderTraverse(TreeNode root){
        Stack<TreeNode> stack = new Stack<>();
        TreeNode t = root;
        while(t != null || !stack.isEmpty()){
            while(t != null){
                stack.push(t);
                t = t.left;
            }
            if(!stack.isEmpty()){
                t = stack.pop();
                System.out.print(t.data + " ");
                t = t.right;
            }
        }
    }

后序遍历

//递归
void traverse(TreeNode node){
        if(node != null){
            traverse(node.left);
            traverse(node.right);
            System.out.println("data:" + node.data);
        }
    }

非递归后序遍历要保证左孩子和右孩子都已被访问(且左孩子在右孩子前访问)才能访问根结点。
提供的思路:
思路:对于根结点,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,按照相同的规则处理右子树,当访问其右孩子后,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才访问它。
实现方式:
1.定义一种结构,信息包含TreeNode,以及右结点是否被访问rvisited
2.定义一种结构,信息包含TreeNode,以及出现在栈顶的次数,第一次为true,第二次为false;
实现代码有时间再写。

//非递归
void postOrderTraverse1(TreeNode node){
        Stack<TreeNode> stack = new Stack<>();

    }

第二种(个人偏好第二种):结点出栈的时候访问结点,当左右孩子都已经被访问时出栈,进栈时先进右孩子再进左孩子。算法:
1.若根结点不空,将根结点入栈;
2.若栈不空,若栈顶元素不存在左右孩子或者都已经被访问,则栈顶元素出栈并访问,否则若栈顶元素存在左右孩子,若存在右孩子,则右孩子进栈,若存在左孩子,则左孩子进栈;
3.重复2.

void postOrderTraverse2(TreeNode root){
    if(root == null)
        return;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    TreeNode cur = null;
    TreeNode pre = null;
    while(!stack.isEmpty()){
        cur = stack.peek();
        //如果当前结点没有孩子结点或者孩子节点都已被访问过
        if((cur.left == null && cur.right == null)|| (pre != null &&(pre == cur.left || pre == cur.right))){
            System.out.print("data:" + cur.data);
            stack.pop();
            pre = cur;
        }else{
            if(tmp.right != null){
                stack.push(tmp.right);
            }
            if(tmp.left != null){
                stack.push(tmp.left);
            }
        }
    }
}

思路:需要判断上次访问的节点是位于左子树,还是右子树。若是位于左子树,则需跳过根节点,先进入右子树,再回头访问根节点;若是位于右子树,则直接访问根节点。(和上一种差不多,只是实现不一样)

层次遍历,使用队列

import java.util.Queue;
import java.util.LinkedList;

public class Solution{
    private void traverseLevel(TreeNode node){
        if(node == null){
            return;
        }
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(node);
        while(!queue.isEmpty()){
            TreeNode tmp = queue.poll();
            System.out.println(tmp.data + "->");
            if(tmp.left != null){
                queue.add(tmp.left);
            }
            if(tmp.right != null){
                queue.add(tmp.right);           }
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值