二叉树的遍历算法(一)

二叉树的遍历算法

复习一下 树的遍历算法
递归方法:前中后
非递归方法:前中后+层次

树的定义:

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x){
        val =x;
    }
}
public class Q1 {

    //递归函数写的时候就跟手算是一样的,只不过相应的读取变成一个存储或者输出的过程。
    //前序递归
    public static void RecurPreOrder(TreeNode root){
        if(root !=null){
            System.out.println(root.val);
            RecurPreOrder(root.left);
            RecurPreOrder(root.right);
        }
    }
    //中序递归
    public static void RecurInOrder(TreeNode root){
        if(root != null){
            RecurInOrder(root.left);
            System.out.println(root.val);
            RecurInOrder(root.right);
        }
    }
    //后序递归
    public static void RecurPostOrder(TreeNode root){
        if(root != null){
            RecurPostOrder(root.left);
            RecurPostOrder(root.right);
            System.out.println(root.val);

        }
    }



    //先序遍历的非递归算法使用的是栈,迭代核心的是“栈顶是根节点,访问,遍历先右后左,”
    //前序非递归
    public static List<Integer> NonRecurPreOrder(TreeNode root){
        List<Integer> list = new ArrayList<Integer>();
        if (root == null) return list;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);
        while( !stack.empty()){
            TreeNode p = stack.pop();
            list.add(Integer.valueOf(p.val));

            if(p.right != null){
                stack.push(p.right);
            }
            if(p.left  != null){
                stack.push(p.left);
            }
        }
        return list;

    }


    //中序遍历的非递归算法
    //还是利用栈:迭代的思想是,栈顶是左节点,访问发生在该节点无左子树的时候
    public static List<Integer> NonRecurInOrder(TreeNode root){
        List<Integer> list = new ArrayList<Integer>();
        if(root ==null) return list;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode tmp = root;
        while (! stack.empty()|| tmp != null){
            //1.遍历全部左子树
            if(tmp!= null){
                stack.push(tmp);
                tmp = tmp.left;
            }else{
             //2.左子树遍历完成以后,栈顶元素依次出栈访问,如果栈顶元素存在右子树,右子树入栈迭代成为新的栈顶
                tmp = stack.pop();
                list.add(Integer.valueOf(tmp.val));
                tmp  = tmp.right;
                //这三步实现了不用额外的判断即可完成对于右子树的回溯NB
            }
        }
        return list;
    }

    //后序遍历的非递归算法:这个版本太奇淫技巧了,学不来学不来
    //依旧是利用栈:参考中序遍历的左-根-右,后序遍历的是 左-右-根
    public static List<Integer> NonRecurPostOrder(TreeNode root){
        LinkedList<Integer> list = new LinkedList<>();
        if(root ==null ) return list;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode tmp = root;
        while ( ! stack.empty() || tmp != null){
            //1. 遍历全部右子树,结果容器用队列表示,
            if(tmp !=null){
                list.addFirst(tmp.val);
                stack.push(tmp);
                tmp = tmp.right;
            }else{
                //2.右子树遍历完成以后,栈顶元素依次出栈,如果存在的左子树,返回1。
                tmp = stack.pop();
                tmp = tmp.left;
            }
        }
        return list;
    }

    //参考另一个大佬的思路:
    //所谓的非递归算法就是使用栈来模仿递归,由栈的顺序可以知道,先入后出,所以:
    //前序遍历就是在访问访问左子树之前,对父节点进行访问。即左节点的出栈的时候
    //中序遍历就是在访问左子树之后,右子树之前,对父节点进行操作。
    //后序遍历就是在访问左右子树以后,对父节点进行操作。即左右子树都出栈以后

    public static List<Integer> NonRecurPreOrder2(TreeNode root) {
        if(root == null ) return Collections.emptyList();

        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();

        stack.push(root);

        while (! stack.empty()){
            //弹出节点用以判断节点是否已经访问,非空表示没有访问
            TreeNode t = stack.pop();

            if(t != null){
                if(t.right != null) stack.push(t.right);
                if(t.left != null) stack.push(t.left);
                stack.push(t);
                stack.push(null);
            }else{
                res.add(Integer.valueOf(stack.pop().val));
            }

        }
        return  res;


    }

    public static void main(String[] args) {
        String str = "[1,2,3,4,5,6]";
        TreeNode root = wrapper.stringToTreeNode(str);
        wrapper.prettyPrintTree(root);
        System.out.println(NonRecurPreOrder2(root));


    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值