二叉树--遍历

本文详细介绍树的遍历算法,包括先序、中序、后序及层次遍历的递归与非递归实现,并给出具体代码示例。

三种遍历方式

遍历分为非递归和递归两种形式,递归的遍历很简单,本文主要针对非递归算法进行说明,详细代码如下:


static void visit(TreeNode root) {
    System.out.println(root.key + "----------->" + root.value);
}
//先序遍历
static void preOrder(TreeNode root) {
        if (root != null) {
            visit(root);
            preOrder(root.left);
            preOrder(root.right);
        }
}

public static void preOrderImpl01(TreeNode node) {
        if (node == null)
            return;

        LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
        stack.push(node);

        while (!stack.isEmpty()) {
            TreeNode temp = stack.pop();
            visit(temp);
            if (temp.right != null)
                stack.push(temp.right);
            if (temp.left != null)
                stack.push(temp.left);
        }
}

非递归解释:采用栈,先压入根节点,接着出栈,压入右节点,左节点,下一次左节点出栈,压入左节点的左右节点,西安便利左子树,再遍历右子树,输出的顺序为先序遍历中–>左–>右

//中序遍历
static void inOrder(TreeNode root) {
        if (root != null) {
            midOrder(root.left);
            visit(root);
            midOrder(root.right);
        }
    }

static void inOrder(TreeNode root) {
        LinkedList<TreeNode> stack = new LinkedList<BinaryTree.TreeNode>();
        TreeNode node = root;
        while (node != null || !stack.isEmpty()) {
            while (node != null) {
                stack.push(node);
                node = node.left;
            }

            node = stack.pop();
            visit(node);
            node = node.right;
            if (node != null) {
                stack.push(node);
                node = node.left;
            }
        }

    }

非递归解释:采用栈,先压入根节点,接着依次压入左节点,下一次左节点出栈,如果该点有右子树,则右节点进栈,节点右节点的左节点,这样进行下一次循环时,就可以进行while的左子树压栈,保证左子树有限进栈;如果该点无右子树,则node赋值为空,可以保证不进入上面while的循环。先便利左子树,再遍历右子树,输出的顺序为先序遍历左–>中–>右

//后序遍历
static void postOrder(TreeNode root) {
        if (root != null) {
            postOrder(root.left);
            postOrder(root.right);
            visit(root);
        }
    }

public static void postOrder(TreeNode node) {
        if (node == null)
            return;

        LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
        stack.push(node);

        while (!stack.isEmpty()) {
            TreeNode curr = stack.peek();
            if (!curr.flag) {
                if (curr.right != null) {
                    stack.push(curr.right);
                }
                if (curr.left != null) {
                    System.out.println(curr.left.value);
                    stack.push(curr.left);
                }
                curr.flag = true;
            }

            TreeNode temp = stack.peek();
            if (temp.flag == true) {
                visit(stack.pop());
            }
        }

    }

//不使用标记flag的方法
public List<Integer> postorderTraversal(TreeNode root) {
    Deque<TreeNode> stack = new LinkedList<>();
    stack.push(root);
    List<Integer> ret = new ArrayList<>();
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        if (node != null) {
            ret.add(node.val);
            stack.push(node.left);
            stack.push(node.right);
        }
    }
    Collections.reverse(ret);
    return ret;
} 

非递归解释:这个里边增加了节点访问标记,采用栈,先压入根节点,接着压入右节点,左节点,然后取栈顶元素,看是否符合输出条件(不到左子树的最作边节点,就不符合输出条件),直到最左边的一个中–>右–>左结构压栈,下一次进行出栈,则是左,右,中,如果右节点上还有子树,进入上面的if,再进行先前的操作,这样左子树就遍历完成,接着会遍历右子树,最后返回根节点,输出的顺序为先序遍历左–>右–>中

树的结构如下:

public static class TreeNode {
        int key;
        Object value;
        boolean flag;
        TreeNode left;
        TreeNode right;

        TreeNode(int key, Object value) {
            this.value = value;
            this.key = key;
        }
    }

层次遍历

public List<List<Integer>> levelOrder(TreeNode root) {

        if (root == null)
            return list;
        List<List<Integer>> list = new LinkedList<>();
        List<TreeNode> nodeList = new ArrayList<>();
        TreeNode node = root;
        nodeList.add(node);
        while (!nodeList.isEmpty()) {
            List<Integer> valueList = new LinkedList<>();
            int count = 0;
            int len = nodeList.size();
            while (count < len) {
                TreeNode nodeTemp = nodeList.pop();
                valueList.add(nodeTemp.val);
                if (nodeTemp.left != null) {
                    nodeList.add(nodeTemp.left);
                }

                if (nodeTemp.right != null) {
                    nodeList.add(nodeTemp.right);
                }
                count++;
            }
            list.add(valueList);
        }

        return list;
    }

这个代码比较简单,博主自己实现的,所以代码看着比较乱一点,同时也可以采用队列的结构,来实现层次遍历。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值