二叉树遍历扩展

在前面的一章中,我们知道了如何实现简单的二叉树,可以实现get查询,put插入,以及delete删除。

下面我们对二叉树的查询进行一定的扩展,查询二叉树中的最小值和最大值

查询二叉树中的最小键
在某些情况下,我们需要查找出树中存储的所有元素的键的最小值,比如我们树中存储的是学生的排名和姓名数据。那么我们需要查找出排名最低是多少名?这里我们设计以下两个方法来完成:

方法作用
public Key min()找出树中最小的键
private Node min(Node x)找出指定树X中,最小键所在的结点

好的,看完了需求之后我们最直接开始实现:

    public String min(){
        return min(root).value;
    }
    private Node min(Node tree){
        if (tree==null){
            return null;
        }
        while(tree.left!=null){
            return min(tree.left);
        }
        return tree;
    }

上面这段代码几句话就可以讲清楚,也是通过递归的思想,这种情况下的二叉树大量运用了递归的思想,就是不断的对二叉树的左子结点进行递归,直到最后左结点值为null为止!

查询二叉树中的最大键
在某些情况下,我们需要查找出树中存储的所有元素的键的最小值,比如我们树中存储的是学生的排名和姓名数据。那么我们需要查找出分数最高是多少名?这里我们设计以下两个方法来完成:

方法作用
public Key max()找出树中最小的键
private Node max(Node x)找出指定树X中,最小键所在的结点
    public String max(){
        return max(root).value;
    }
    private Node max(Node tree){
        if (tree==null){
            return null;
        }
        while(tree.right!=null){
            return max(tree.right);
        }
        return tree;
    }

思想与第一种情况类似,这里就不过度探究了!

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

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

首先我们先看下前序遍历的API:

方法作用
public Queue preErgodic()使用前序遍历,获取整个树中的所有键
private void preErgodic(Node x,Queue keys)使用前序遍历,把指定树x中的所有键放入到keys队列中

实现过程中,我们通过前序遍历,把每个结点的键取出,放入到队列中返回即可
实现步骤:

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

下面我们开始进行代码实现,我们方法中用到的Queue是我们前面自己定义的队列,你也可以使用自己写的,或者去我前面的博客直接用我的队列结构实现

首先写个给用户操作的接口:

    public Queue preErgodic(){
        Queue keys=new Queue();
        preErgodic(root,keys);
        return keys;
    }

由于是遍历操作,所以我们不传递参数进去,并且在方法里面写一个队列,然后将队列传递进我们的入口,最后将这个队列返回。

    private void preErgodic(Node tree,Queue keys){
        if (tree==null){
            return ;
        }
        //把当前结点的key放入到队列中
        keys.enqueue(tree.key+"");
        //找到当前结点的左子树,如果不为空,递归遍历左子树
        if(tree.left!=null){
            preErgodic(tree.left,keys);
        }
        //找到当前结点的右子树
        if(tree.right!=null){
            preErgodic(tree.right,keys);
        }
    }
  1. 判断树是否为空,如果树为空的话,直接结束循环不用返回任何值。
  2. 如果不为空的话才开始遍历,首先将根结点放入队列
  3. 遍历左子树
  4. 遍历右子树

以上就是前序遍历

而后序遍历实现方法与前序遍历基本相同,不过就是改变了位置,最后遍历根结点罢了。

顺序是:

  1. 遍历左子树
  2. 遍历右子树
  3. 遍历根结点
    //后序遍历开始
    public Queue afterErgodic(){
        Queue queue=new Queue();
        afterErgodic(root,queue);
        return queue;
    }
    private void afterErgodic(Node tree,Queue keys){
        if(tree!=null){
            return ;
        }
        if(tree.left!=null){
            midErgodic(tree.left,keys);
        }
        if(tree.right!=null){
            midErgodic(tree.right,keys);
        }
        keys.enqueue(tree.key+"");
    }
    //后序遍历结束

好了,前面的都是小儿科,接下来我们来研究我们二叉树遍历的重点:层序遍历

层序遍历,顾名思意就是将二叉树按层次一层层遍历出来,先遍历根结点,放入队列,然后将根结点弹出来,再将根结点的左右结点放入放入队列,再依次将那两个结点遍历弹出来,再将其左右4个结点放入队列中,依次类推。
这就是层序遍历的实现思想

思想听不懂没关系,我们代码看的懂就够了,先看实现步骤:

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

下面我们看代码实现:

    public Queue layerErgodic() {
        // 创建一个队列,存储每一层的节点
        Queue nodes = new Queue();
        // 创建一个队列,用于存储遍历的节点
        Queue keys = new Queue();
        // 将当前节点存储到nodes中
        nodes.enqueue(root.key + "");
        // 遍历queue
        while (!nodes.isEmpty()) {
            // 出列
            String key = nodes.dequeue();
            Node currentNode = getNode(root, Integer.parseInt(key));
            // 把节点的key存入到keys中
            keys.enqueue(currentNode.key + "");
            // 如果当前节点的左子节点不为空,则把左子节点放入到队列中
            if (currentNode.left != null) {
                nodes.enqueue(currentNode.left.key + "");
            }
            // 如果当前节点的右子节点不为空,把右子节点放到队列中
            if (currentNode.right != null) {
                nodes.enqueue(currentNode.right.key + "");
            }
        }
        return keys;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值