java基础学习

二叉树遍历

2020-02-26  本文已影响0人  迷糊银儿
循环遍历(只有层次遍历用到了队,其他都是栈)
//非递归前序遍历二叉树
    public static void printTree1(Node root){
        SequenceStack<Node> stack=new SequenceStack<Node>();
        List<Node> list=new ArrayList<Node>();
        //首先先把根节点压栈
        stack.push(root);
        //当栈不为空的时候循环遍历
        while(!stack.isEmpty()){
            //弹出栈顶元素
            Node node=stack.pop();
            //遍历栈顶元素
            list.add(node);
            //如果栈顶元素的右孩子不为空,则进栈
            if(node.right!=null){
                stack.push(node.right);
            }
            //如果栈顶元素的左孩子不为空,则进栈
            if(node.left!=null){
                stack.push(node.left);
            }       
        }
        System.out.println(list);
}
//采用非递归中序遍历二叉树
    public static void printTree(Node root){
        SequenceStack<Node> stack=new SequenceStack<Node>();
        List<Node> list=new ArrayList<Node>();
        Node node=root;
        //刚开始先把根节点压入栈,往后每次判断节点不为空则压栈
        do {
            while(node!=null){
                stack.push(node);
                node=node.left;
            }
            node=stack.pop();
            list.add(node);
            //如果出栈的结点存在右节点,则指向该节点
            if(node.right!=null){
                node=node.right;
            }else{//否则设置为空,下次循环继续出栈
                node=null;
            }//当栈不为空,或者当前节点引用不为空时循环
        } while (!stack.isEmpty()||node!=null);
        System.out.println(list);
    }
//非递归实现后序遍历
    public static void printTree2(Node root){
        SequenceStack<Node> stack=new SequenceStack<Node>();
        List<Node> list=new ArrayList<Node>();
        //定义两个节点变量node和pre(这里需要注意pre节点的作用,下方的注释有详细地介绍)
        Node node=root;
        Node pre=null;
        do {
            //将左结点一次压入栈
            while(node!=null){
                stack.push(node);
                node=node.left;
            }
            //获取栈顶节点
            node = stack.get();
            //如果栈顶节点的右孩子不为空,说明还得把右子树压入栈中,这里需要注意
            //node.right!=pre这个条件,因为我们在遍历的过程中,对于(子树)根节点的判断会存在两次
            //第一次是弹出左孩子节点后,对根节点进行是否有右孩子的判断,如果有,则将右孩子压栈
            //第二次是弹出右孩子节点后,这时候因为循环的原因(代码的原因),我们再次对根节点进行了右孩子判断,
            //所以这里就必须得判断该右孩子节点是否在之前的循环中已经判断过了,如果判断过了,则弹出根节点,否则压入右孩子节点。
            //总的来说,pre节点的作用是用来防止重复遍历右孩子节点的。
            if(node.right!=null&&node.right!=pre){
                //node指向右孩子节点
                node=node.right;
            }else{//只要有一个条件不满足则执行
                //弹出栈顶元素
                node=stack.pop();
                //遍历栈顶元素
                list.add(node);
                //将pre指向当前弹出的元素,用来做下次对根节点的再次判断时,右孩子不重复遍历的一个条件
                pre=node;
                //将node设置为null,防止根节点重复压入左孩子节点。
                node=null;
            }
            
        } while (node!=null||!stack.isEmpty());
        System.out.println(list);
    }
public class PrintFromTopToBottom {
    public static class TreeNode{
        int val;
        TreeNode left=null;
        TreeNode right=null;
        public TreeNode(int val) {
            this.val = val;
        }
    }

    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> list=new ArrayList<Integer>();  //存放结果
        Queue<TreeNode> queue= new LinkedList<TreeNode>();   //辅助队列
        if (root!=null){
            //根节点入队
            queue.offer(root);
        }
        //队列不为空,执行循环
        while (!queue.isEmpty()){
            TreeNode node=queue.poll();
            list.add(node.val);     //将队列元素输出

            //如果有左节点,就把左节点加入
            if (node.left!=null){
                queue.offer(node.left);
            }
            //如果有右节点,就把右节点加入
            if(node.right!=null){
                queue.offer(node.right);
            }
        }
        return list;
    }
}
递归遍历
public class TreeNode {
    public char value;
    public TreeNode left;
    public TreeNode right;
 
    TreeNode(char value) {
        this.value = value;
    }
 
    TreeNode(char value, TreeNode left, TreeNode right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }
}
public class Order {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TreeNode root = init();
 
        System.out.println("先序");
        ProOrder(root);
 
        System.out.println("中序");
        InOrder(root);
 
        System.out.println("后序");
        PostOrder(root);
 
    }
 
    /** 构造树 */
    public static TreeNode init() {
        TreeNode a = new TreeNode('A');
        TreeNode b = new TreeNode('B', null, a);
        TreeNode c = new TreeNode('C');
        TreeNode d = new TreeNode('D', b, c);
        TreeNode e = new TreeNode('E');
        TreeNode f = new TreeNode('F', e, null);
        TreeNode g = new TreeNode('G', null, f);
        TreeNode h = new TreeNode('H', d, g);
        return h;// root
    }
 
    /**
     * 递归前序遍历
     * 
     * @param tree
     */
    public static void ProOrder(TreeNode tree) {
        System.out.println(tree.value);
        if (tree.left != null) {
            ProOrder(tree.left);
        }
        if (tree.right != null) {
            ProOrder(tree.right);
        }
    }
 
    /**
     * 递归中序遍历
     * 
     * @param tree
     */
    public static void InOrder(TreeNode tree) {
 
        if (tree.left != null) {
            InOrder(tree.left);
        }
        System.out.println(tree.value);
        if (tree.right != null) {
            InOrder(tree.right);
        }
    }
 
    /**
     * 递归后顺遍历
     * 
     * @param tree
     */
    public static void PostOrder(TreeNode tree) {
 
        if (tree.left != null) {
            PostOrder(tree.left);
        }
 
        if (tree.right != null) {
            PostOrder(tree.right);
        }
        System.out.println(tree.value);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读