6.1 树的BFS与DFS搜索

  在实际的开发工作中,我们会遇到很多树状结构,比如说文件系统、菜单树、商品分类。也就说目录结构是一种典型的树状结构。对于刚入行开发的新人来说,他们可能会使用递归的方式去遍历一棵树。
  BFS搜索叫宽度优先搜索,也叫广度优先搜索。是树的搜索方法中常见的方法,是一种按层搜索的方法。这个方法可以用递归实现,也可以用非递归方法实现。
在这里插入图片描述
  比如这个树,宽度优先搜索顺序就是4 2 7 1 3 6 9 5 10。
  那么具体要怎么实现呢?这个时候需要用到队列,为了方便理解,我建议大家想象一下,在树的根部,有一个大吸管,把树中的元素全部吸进去。
  首先初始化队列,把root,也就是4进入队列
  然后从左边取出队列元素,也就是4
  如果4 有子元素,那么依次从后面放入队列
  这时队列为
  2 7
  第二次循环,取出了2,但是2有子元素,从后面放入队列
  这时队列为
  7 1 3 6 9
  原理在于把子元素放在队列的后面,取的时候先取上一层元素。所以这就实现了宽度优先搜索。
  代码实现如下:

/**
 * 宽度搜索
 *
 * @param visitor
 */
public void bfs(Predicate<Node<T>> visitor) {

    final Deque<BinaryNode<T>> nodes = new ArrayDeque<>();
    nodes.add(root);
    while (!nodes.isEmpty()) {
        BinaryNode<T> node = nodes.pop();
        nodes.addAll(node.getChildren());
        if (!visitor.test(node)) {
            break;
        }
    }
}

  实际效果
  测试类代码

AVLTree<Integer> avlTree = new AVLTree<>();
for (int i = 0; i < 10; i++) {
    avlTree.add(i + 1);
}
System.out.println(avlTree.toTreeString());
avlTree.bfs(x->{
    System.out.print(x.getValue()+" ");
    return true;
});

在这里插入图片描述
  那么深度优先呢?
  还是上面那棵树
  我们把队列换成栈
  初始化栈为4
  取出4,这个时候放入4的子级,栈变成了
  2 7
  那么,因为是栈,这个时候取出的是7,然后再压入7的子元素,栈变成了
  2 7 6 9
  然后取出9,压入10,栈变成了
  1 7 6 10
  所以整个遍历顺序是4 7 9 10 6 5 2 3 1。
  深度搜索默认是最右边开始的,直接深入到最深的叶子。
  如果要改变深度搜索的左右顺序,把子元素压栈时,先翻转再压栈。这样能实现从左到右的遍历。
  代码实现

/**
 * 深度搜索
 *
 * @param visitor
 */
public void dfs(Predicate<Node<T>> visitor) {
    final Deque<BinaryNode<T>> nodes = new ArrayDeque<>();
    nodes.add(root);
    while (!nodes.isEmpty()) {
        BinaryNode<T> node = nodes.pop();
        List<BinaryNode<T>> children = node.getChildren();
        Collections.reverse(children);
        children.forEach(nodes::push);
        if (!visitor.test(node)) {
            break;
        }
    }
}

  实际效果:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醒过来摸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值