vlambda博客
学习文章列表

多级树 深度优先搜索算法和广度优先搜索算法

标签(空格分隔):深度优先搜索算法 广度优先搜索算法


我们知道,遍历有递归,非递归两种方式。在工程项目上,一般是禁用递归方式的,因为递归非常容易使得系统爆栈。同时,JVM也限制了最大递归数量,在你的树结构非常深的时候很容易出现StackOverflowError异常,所以最好采用非递归的方式。

节点模型

 
   
   
 
  1. public class Node {

  2. //值

  3. public int value;

  4. //所有的子节点

  5. public ArrayList<Node> nexts;


  6. public Node(int value) {

  7. this.value = value;

  8. }

  9. }

深度优先遍历

深度优先搜索英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。多级树可以看做一个特殊的图结构,总的来说遍历的方法还是不变的,都是利用栈和Set来进行操作。

主要步骤:

  1. 准备一个栈结构和一个Set结构的集合,栈用来记录还有孩子没有被遍历到的节点,Set用来记录遍历的历史记录

  2. 将首节点加入到栈和set中

  3. 弹栈拿到首节点

  4. 从首节点开始深度遍历,下面示例代码配合注解近进行理解

 
   
   
 
  1. public static void dfs(Node node) {

  2. if (node == null) {

  3. return;

  4. }

  5. Stack<Node> stack = new Stack<>();

  6. HashSet<Node> set = new HashSet<>();

  7. stack.add(node);

  8. set.add(node);

  9. System.out.println(node.value);


  10. while (!stack.isEmpty()) {

  11. //弹栈获得一个节点

  12. Node cur = stack.pop();

  13. //查看这个节点的所有孩子

  14. for (Node next : cur.nexts) {

  15. //如果有孩子是之前没有遍历到的,说明这个节点没有深度遍历完

  16. if (!set.contains(next)) {

  17. //此节点与其孩子加入栈与Set中

  18. stack.push(cur);

  19. stack.push(next);

  20. set.add(next);

  21. System.out.println(next.value);

  22. break;

  23. }

  24. }

  25. }

  26. }

广度优先遍历

宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。对于多级数来说,就是先遍历该节点的所有孩子,然后在遍历孩子节点的所有孩子,先遍历一层再遍历下一次层。

 
   
   
 
  1. public static void bfs(Node node) {

  2. if (node == null) {

  3. return;

  4. }

  5. Queue<Node> queue = new LinkedList<>();

  6. //用来注册已加入队列的节点——>防止重复添加节点

  7. HashSet<Node> set = new HashSet<>();

  8. queue.add(node);

  9. set.add(node);

  10. while (!queue.isEmpty()) {

  11. Node cur = queue.poll();

  12. System.out.println(cur.value);

  13. //将节点的所有下游节点加入到队列

  14. for (Node next : cur.nexts) {

  15. if (!set.contains(next)) {

  16. set.add(next);

  17. queue.add(next);

  18. }

  19. }

  20. }

  21. }