树--05---二叉树--02---二叉搜索树(BST)遍历

Posted 高高for 循环

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树--05---二叉树--02---二叉搜索树(BST)遍历相关的知识,希望对你有一定的参考价值。


二叉树(BST)基础遍历----深度优先

很多情况下,我们可能需要像遍历数组数组一样,遍历树,从而拿出树中存储的每一个元素,由于树状结构和线性结构不一样,它没有办法从头开始依次向后遍历,所以存在如何遍历,也就是按照什么样的搜索路径进行遍历的问题。

我们把树简单的画作上图中的样子,由一个根节点、一个左子树、一个右子树组成,那么按照根节点什么时候被访问,我们可以把二叉树的遍历分为以下三种方式:

  1. 前序遍历;
    先访问根结点,然后再访问左子树,最后访问右子树
  2. 中序遍历;
    先访问左子树,中间访问根节点,最后访问右子树
  3. 后序遍历;
    先访问左子树,再访问右子树,最后访问根节点

如果我们分别对下面的树使用三种遍历方式进行遍历,得到的结果如下:

1. 前序遍历

前序遍历的API

实现步骤:

  1. 把当前结点的key放入到队列中;
  2. 找到当前结点的左子树,如果不为空,递归遍历左子树
  3. 找到当前结点的右子树,如果不为空,递归遍历右子树

用的jDK自带的队列 LinkedBlockingDeque

代码:

 //获取整个树中所有的键
    public Queue<Key> preErgodic(){
        Queue<Key> keys= new LinkedBlockingDeque<>();
        preErgodic(root, keys);
        return keys;
    }

    //获取指定树x的所有键,并放到keys队列中
    private void preErgodic(Node x,Queue<Key> keys){
        if (x==null){
            return;
        }

        //把x结点的key放入到keys中
        keys.add(x.key);

        //递归遍历x结点的左子树
        if (x.left!=null){
            preErgodic(x.left,keys);
        }

        //递归遍历x结点的右子树
        if (x.right!=null){
            preErgodic(x.right,keys);
        }

    }

测试

 @Test
    public void test01(){
    //创建树对象
        BinaryTree<String, String> tree = new BinaryTree<>();
        //往树中添加数据
        tree.put("E", "5");
        tree.put("B", "2");
        tree.put("G", "7");
        tree.put("A", "1");
        tree.put("D", "4");
        tree.put("F", "6");
        tree.put("H", "8");
        tree.put("C", "3");

        //遍历
        Queue<String> keys = tree.preErgodic();
        for (String key : keys) {
            String value = tree.get(key);
            System.out.println(key+"----"+value);
        }
    }


2.中序遍历

中序遍历是按照Key从小到大遍历,最为重要

中序遍历的API:

实现步骤:

  1. 找到当前结点的左子树,如果不为空,递归遍历左子树
  2. 把当前结点的key放入到队列中;
  3. 找到当前结点的右子树,如果不为空,递归遍历右子树

代码:

   //使用中序遍历获取树中所有的键
    public Queue<Key> midErgodic(){
        Queue<Key> keys = new LinkedBlockingDeque<>();
        midErgodic(root,keys);
        return keys;
    }

    //使用中序遍历,获取指定树x中所有的键,并存放到key中
    private void midErgodic(Node x,Queue<Key> keys){
        if (x==null){
            return;
        }
        //先递归,把左子树中的键放到keys中
        if (x.left!=null){
            midErgodic(x.left,keys);
        }
        //把当前结点x的键放到keys中
        keys.add(x.key);
        //在递归,把右子树中的键放到keys中
        if(x.right!=null){
            midErgodic(x.right,keys);
        }

    }

测试:

 @Test
    public void test02(){
    //创建树对象
        BinaryTree<String, String> tree = new BinaryTree<>();
        //往树中添加数据
        tree.put("E", "5");
        tree.put("B", "2");
        tree.put("G", "7");
        tree.put("A", "1");
        tree.put("D", "4");
        tree.put("F", "6");
        tree.put("H", "8");
        tree.put("C", "3");

        //遍历
        Queue<String> keys = tree.midErgodic();
        for (String key : keys) {
            String value = tree.get(key);
            System.out.println(key+"----"+value);
        }
    }


3. 后序遍历

遍历的API:

实现步骤:

  1. 找到当前结点的左子树,如果不为空,递归遍历左子树
  2. 找到当前结点的右子树,如果不为空,递归遍历右子树
  3. 把当前结点的key放入到队列中;

代码:

 //使用后序遍历,把整个树中所有的键返回
    public Queue<Key> afterErgodic(){
        Queue<Key> keys = new LinkedBlockingDeque<>();
        afterErgodic(root,keys);
        return keys;
    }

    //使用后序遍历,把指定树x中所有的键放入到keys中
    private void afterErgodic(Node x,Queue<Key> keys){
        if (x==null){
            return ;
        }

        //通过递归把左子树中所有的键放入到keys中
        if (x.left!=null){
            afterErgodic(x.left,keys);
        }
        //通过递归把右子树中所有的键放入到keys中
        if (x.right!=null){
            afterErgodic(x.right,keys);
        }
        //把x结点的键放入到keys中
        keys.add(x.key);
    }

测试:

@Test
    public void test03(){
        //创建树对象
        BinaryTree<String, String> tree = new BinaryTree<>();
        //往树中添加数据
        tree.put("E", "5");
        tree.put("B", "2");
        tree.put("G", "7");
        tree.put("A", "1");
        tree.put("D", "4");
        tree.put("F", "6");
        tree.put("H", "8");
        tree.put("C", "3");

        //遍历
        Queue<String> keys = tree.afterErgodic();
        for (String key : keys) {
            String value = tree.get(key);
            System.out.println(key+"----"+value);
        }
    }


二叉树的层序遍历----广度优先

所谓的层序遍历,就是从根节点(第一层)开始,依次向下,获取每一层所有结点的值,有二叉树如下


那么层序遍历的结果是:EBGADFHC

层序遍历的API:

实现步骤:

  1. 创建队列,存储每一层的结点;
  2. 使用循环从队列中弹出一个结点:
  3. 获取当前结点的key;
  4. 如果当前结点的左子结点不为空,则把左子结点放入到队列中
  5. 如果当前结点的右子结点不为空,则把右子结点放入到队列中


代码实现:

    //使用层序遍历,获取整个树中所有的键
    public Queue<Key> layerErgodic(){
        //定义两个队列,分别存储树中的键和树中的结点
        Queue<Key> keys =new LinkedBlockingDeque<>();
        Queue<Node> nodes =new LinkedBlockingDeque<>();

        //默认,往队列中放入根结点
        nodes.add(root);

        while(!nodes.isEmpty()){
            //从队列中弹出一个结点,把key放入到keys中
            Node n = nodes.poll();
            keys.add(n.key);
            //判断当前结点还有没有左子结点,如果有,则放入到nodes中
            if (n.left!=null){
                nodes.add(n.left);
            }
            //判断当前结点还有没有右子结点,如果有,则放入到nodes中
            if (n.right!=null){
                nodes.add(n.right);
            }
        }
        return keys;
    }

测试:

 @Test
    public void test01(){
        //创建树对象
        BinaryTree<String, String> tree = new BinaryTree<>();
        //往树中添加数据
        tree.put("E", "5");
        tree.put("B", "2");
        tree.put("G", "7");
        tree.put("A", "1");
        tree.put("D", "4");
        tree.put("F", "6");
        tree.put("H", "8");
        tree.put("C", "3");

        //遍历
        Queue<String> keys = tree.layerErgodic();
        for (String key : keys) {
            String value = tree.get(key);
            System.out.println(key+"----"+value);
        }
    }


以上是关于树--05---二叉树--02---二叉搜索树(BST)遍历的主要内容,如果未能解决你的问题,请参考以下文章

史上最详细的二叉树B树,看不懂怨我

带你整理面试过程中关于 二叉树二叉搜索树平衡二叉树B 树和 B+树的相关知识

⭐算法入门⭐《二叉树 - 二叉搜索树》简单02 —— LeetCode 98. 验证二叉搜索树

⭐算法入门⭐《二叉树 - 二叉搜索树》中等05 —— LeetCode 450. 删除二叉搜索树中的节点

数据结构~基础2~树《二叉树二叉搜索树AVL树B树红黑树》的设计~红黑树

⭐算法入门⭐《二叉树 - 二叉搜索树》简单05 —— LeetCode 897. 递增顺序搜索树