Java中二叉树的广度优先搜索(BFS)和深度优先搜索(DFS)

时间:2020-02-23 14:33:57  来源:igfitidea点击:

广度优先搜索和深度优先搜索是遍历图形和树的两种技术。
在本教程中,我们将主要关注树中的BFS和DFS遍历。

什么是深度优先搜索(DFS)?

该算法从根节点开始,然后在回溯之前探索每个分支。
它是使用堆栈实现的。
通常在编写代码时,我们使用递归堆栈进行回溯。
通过使用递归,我们可以利用左右子树也是树并且共享相同属性的事实。

对于二叉树,有三种类型的DFS遍历。

  • In-Order
  • Pre-Order
  • Post-Order

什么是广度优先搜索(BFS)?

该算法也从根节点开始,然后逐级访问所有节点。
这意味着在根之后,它将遍历根的所有直接子代。
遍历了根的所有直接子代后,它移到了他们的子代,依此类推。
为了实现BFS,我们使用队列。

对于二叉树,我们遵循BFS的级别顺序遍历。

Java中BFS和DFS的实现

让正在考虑的树为:

TreeNode类的结构如下:

static class TreeNode {
      int data;
      TreeNode left, right;

      public TreeNode(int key) {
          data = key;
          left = right = null;
      }
  }

1.预定遍历

在二叉树的预遍历中,我们先遍历根,然后遍历左子树,最后遍历右子树。
我们递归地执行此操作,以从左右子树也是树的事实中受益。

预遍历的算法如下:

  • 遍历根。

  • 在左侧子树上调用preorder()。

  • 在右侧子树上调用preorder()。

上面树的预遍历为:

0 1 3 4 2 

Java代码如下:

static void preorder(TreeNode TreeNode) {
      if (TreeNode == null)
          return;

      //Traverse root
      System.out.print(TreeNode.item + "->");
      //Traverse left
      preorder(TreeNode.left);
      //Traverse right
      preorder(TreeNode.right);
  }

2.有序遍历

按顺序遍历二叉树首先遍历左子树,然后遍历根,最后遍历右子树。

有序遍历的算法如下:

  • 在左侧子树上调用inorder()。

  • 遍历根。

  • 在右侧子树上调用inorder()。

上面的树的有序遍历为:

3 1 4 0 2 

Java代码如下:

static void inorder(TreeNode TreeNode) {
      if (TreeNode == null)
          return;

      //Traverse left
      inorder(TreeNode.left);
      //Traverse root
      System.out.print(TreeNode.item + "->");
      //Traverse right
      inorder(TreeNode.right);
  }

3.订单遍历

二叉树的后序遍历首先遍历左子树,然后遍历右子树,最后遍历根。

后遍历的算法如下:

  • 在左侧子树上调用postorder()。

  • 在右侧子树上调用postorder()。

  • 遍历根。

上面树的后遍历为:

3 4 1 2 0 

Java代码如下:

static void postorder(TreeNode TreeNode) {
      if (TreeNode == null)
          return;

      //Traverse left
      postorder(TreeNode.left);
      //Traverse right
      postorder(TreeNode.right);
      //Traverse root
      System.out.print(TreeNode.item + "->");
  }

4.级别顺序遍历

级别顺序遍历使用队列来跟踪要访问的节点。
访问节点后,其子节点将进入队列。
为了遍历一个新节点,我们从队列中取出元素。

算法如下:

  • 初始化一个空队列

  • 首先将temp设置为root

  • 运行循环,直到队列不为空从临时打印数据。

  • 按从左到右的顺序排列temp的子级。

  • 从队列中取出一个节点,并将其值分配给temp。

上面树的级别顺序遍历为:

0 1 2 3 4

Java代码如下:

static void printLevelOrder(TreeNode root) {
     Queue<TreeNode> queue = new LinkedList<TreeNode>();
     queue.add(root);
     while (!queue.isEmpty()) {
         TreeNode temp = queue.poll();
         System.out.print(temp.data + " ");

         /*add left child to the queue */
         if (temp.left != null) {
             queue.add(temp.left);
         }

         /*add right right child to the queue */
         if (temp.right != null) {
             queue.add(temp.right);
         }
     }
 }

Java中BFS和DFS的完整代码实现

完整的Java代码如下:

package com.theitroad;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
  static class TreeNode {
      int data;
      TreeNode left, right;

      public TreeNode(int key) {
          data = key;
          left = right = null;
      }
  }

  static void preorder(TreeNode TreeNode) {
      if (TreeNode == null)
          return;

      //Traverse root
      System.out.print(TreeNode.data + " ");
      //Traverse left
      preorder(TreeNode.left);
      //Traverse right
      preorder(TreeNode.right);
  }

  static void inorder(TreeNode TreeNode) {
      if (TreeNode == null)
          return;

      //Traverse left
      inorder(TreeNode.left);
      //Traverse root
      System.out.print(TreeNode.data + " ");
      //Traverse right
      inorder(TreeNode.right);
  }

  static void postorder(TreeNode TreeNode) {
      if (TreeNode == null)
          return;

      //Traverse left
      postorder(TreeNode.left);
      //Traverse right
      postorder(TreeNode.right);
      //Traverse root
      System.out.print(TreeNode.data + " ");
  }
 static void printLevelOrder(TreeNode root) {
     Queue<TreeNode> queue = new LinkedList<TreeNode>();
     queue.add(root);
     while (!queue.isEmpty()) {
         TreeNode tempNode = queue.poll();
         System.out.print(tempNode.data + " ");

         /*add left child to the queue */
         if (tempNode.left != null) {
             queue.add(tempNode.left);
         }

         /*add right right child to the queue */
         if (tempNode.right != null) {
             queue.add(tempNode.right);
         }
     }
 }

  public static void main(String args[])
          
  {
      TreeNode root = new TreeNode(0);
      root.left = new TreeNode(1);
      root.right = new TreeNode(2);
      root.left.left = new TreeNode(3);
      root.left.right = new TreeNode(4);
      System.out.println("Inorder traversal");
      inorder(root);

      System.out.println("\nPreorder traversal ");
      preorder(root);

      System.out.println("\nPostorder traversal");
     postorder(root);

      System.out.println("\nLevelorder traversal");
      printLevelOrder(root);

  }

} 

Output : 

Inorder traversal
3 1 4 0 2 
Preorder traversal 
0 1 3 4 2 
Postorder traversal
3 4 1 2 0 
Levelorder traversal
0 1 2 3 4