二叉树的深度优先与广度优先

来源:互联网 发布:python局域网嗅探 编辑:程序博客网 时间:2024/06/05 03:41

1、分析

        二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列。

        深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次。要特别注意的是,二叉树的深度优先遍历比较特殊,可以细分为先序遍历、中序遍历、后序遍历。具体说明如下:

  • 先序遍历:对任一子树,先访问根,然后遍历其左子树,最后遍历其右子树。
  • 中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树。
  • 后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。

        广度优先遍历:又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,直到没有结点可以访问为止。

2、举例说明

        对下图所示的二叉排序树进行遍历,要求使用先序遍历(递归、非递归)、中序遍历(递归、非递归)、后序遍历(递归、非递归)和广度优先遍历。


2.1、参考代码

[java] view plain copy
  1. package BinaryTreeTraverseTest;  
  2.   
  3. import java.util.LinkedList;  
  4. import java.util.Queue;  
  5.   
  6. /** 
  7.  * 二叉树的深度优先遍历和广度优先遍历 
  8.  * @author Fantasy 
  9.  * @version 1.0 2016/10/05 - 2016/10/07 
  10.  */  
  11. public class BinaryTreeTraverseTest {  
  12.     public static void main(String[] args) {  
  13.           
  14.     BinarySortTree<Integer> tree = new BinarySortTree<Integer>();  
  15.           
  16.         tree.insertNode(35);  
  17.         tree.insertNode(20);  
  18.         tree.insertNode(15);  
  19.         tree.insertNode(16);  
  20.         tree.insertNode(29);  
  21.         tree.insertNode(28);  
  22.         tree.insertNode(30);  
  23.         tree.insertNode(40);  
  24.         tree.insertNode(50);  
  25.         tree.insertNode(45);  
  26.         tree.insertNode(55);  
  27.           
  28.         System.out.print("先序遍历(递归):");  
  29.         tree.preOrderTraverse(tree.getRoot());  
  30.         System.out.println();  
  31.         System.out.print("中序遍历(递归):");  
  32.         tree.inOrderTraverse(tree.getRoot());  
  33.         System.out.println();  
  34.         System.out.print("后序遍历(递归):");  
  35.         tree.postOrderTraverse(tree.getRoot());  
  36.         System.out.println();  
  37.           
  38.         System.out.print("先序遍历(非递归):");  
  39.         tree.preOrderTraverseNoRecursion(tree.getRoot());  
  40.         System.out.println();  
  41.         System.out.print("中序遍历(非递归):");  
  42.         tree.inOrderTraverseNoRecursion(tree.getRoot());  
  43.         System.out.println();  
  44.         System.out.print("后序遍历(非递归):");  
  45.         tree.postOrderTraverseNoRecursion(tree.getRoot());  
  46.         System.out.println();  
  47.           
  48.         System.out.print("广度优先遍历:");  
  49.         tree.breadthFirstTraverse(tree.getRoot());  
  50.     }  
  51. }  
  52.   
  53. /** 
  54.  * 结点 
  55.  */  
  56. class Node<E extends Comparable<E>> {  
  57.       
  58.     E value;  
  59.     Node<E> left;  
  60.     Node<E> right;  
  61.       
  62.     Node(E value) {  
  63.         this.value = value;  
  64.         left = null;  
  65.         right = null;  
  66.     }  
  67.       
  68. }  
  69.   
  70. /** 
  71.  * 使用一个先序序列构建一棵二叉排序树(又称二叉查找树) 
  72.  */  
  73. class BinarySortTree<E extends Comparable<E>> {  
  74.       
  75.     private Node<E> root;  
  76.       
  77.     BinarySortTree() {  
  78.         root = null;  
  79.     }  
  80.       
  81.     public void insertNode(E value) {     
  82.         if (root == null) {  
  83.             root = new Node<E>(value);  
  84.             return;  
  85.         }      
  86.         Node<E> currentNode = root;  
  87.         while (true) {  
  88.             if (value.compareTo(currentNode.value) > 0) {  
  89.                 if (currentNode.right == null) {  
  90.                     currentNode.right = new Node<E>(value);  
  91.                     break;  
  92.                 }  
  93.                 currentNode = currentNode.right;  
  94.             } else {  
  95.                 if (currentNode.left == null) {  
  96.                     currentNode.left = new Node<E>(value);  
  97.                     break;  
  98.                 }  
  99.                 currentNode = currentNode.left;  
  100.             }  
  101.         }  
  102.     }  
  103.       
  104.     public Node<E> getRoot(){  
  105.         return root;  
  106.     }  
  107.   
  108.     /** 
  109.      * 先序遍历二叉树(递归) 
  110.      * @param node 
  111.      */  
  112.     public void preOrderTraverse(Node<E> node) {  
  113.         System.out.print(node.value + " ");  
  114.         if (node.left != null)  
  115.             preOrderTraverse(node.left);  
  116.         if (node.right != null)  
  117.             preOrderTraverse(node.right);  
  118.     }  
  119.       
  120.     /** 
  121.      * 中序遍历二叉树(递归) 
  122.      * @param node 
  123.      */  
  124.     public void inOrderTraverse(Node<E> node) {  
  125.         if (node.left != null)  
  126.             inOrderTraverse(node.left);  
  127.         System.out.print(node.value + " ");  
  128.         if (node.right != null)  
  129.             inOrderTraverse(node.right);  
  130.     }  
  131.       
  132.     /** 
  133.      * 后序遍历二叉树(递归) 
  134.      * @param node 
  135.      */  
  136.     public void postOrderTraverse(Node<E> node) {  
  137.         if (node.left != null)  
  138.             postOrderTraverse(node.left);  
  139.         if (node.right != null)  
  140.             postOrderTraverse(node.right);  
  141.         System.out.print(node.value + " ");  
  142.     }  
  143.       
  144.     /** 
  145.      * 先序遍历二叉树(非递归) 
  146.      * @param root 
  147.      */  
  148.     public void preOrderTraverseNoRecursion(Node<E> root) {  
  149.         LinkedList<Node<E>> stack = new LinkedList<Node<E>>();  
  150.         Node<E> currentNode = null;  
  151.         stack.push(root);  
  152.         while (!stack.isEmpty()) {  
  153.             currentNode = stack.pop();  
  154.             System.out.print(currentNode.value + " ");  
  155.             if (currentNode.right != null)  
  156.                 stack.push(currentNode.right);  
  157.             if (currentNode.left != null)  
  158.                 stack.push(currentNode.left);  
  159.         }  
  160.     }  
  161.       
  162.     /** 
  163.      * 中序遍历二叉树(非递归) 
  164.      * @param root 
  165.      */  
  166.     public void inOrderTraverseNoRecursion(Node<E> root) {  
  167.         LinkedList<Node<E>> stack = new LinkedList<Node<E>>();  
  168.         Node<E> currentNode = root;  
  169.         while (currentNode != null || !stack.isEmpty()) {  
  170.             // 一直循环到二叉排序树最左端的叶子结点(currentNode是null)  
  171.             while (currentNode != null) {  
  172.                 stack.push(currentNode);  
  173.                 currentNode = currentNode.left;  
  174.             }  
  175.             currentNode = stack.pop();  
  176.             System.out.print(currentNode.value + " ");  
  177.             currentNode = currentNode.right;  
  178.         }     
  179.     }  
  180.       
  181.     /** 
  182.      * 后序遍历二叉树(非递归) 
  183.      * @param root 
  184.      */  
  185.     public void postOrderTraverseNoRecursion(Node<E> root) {  
  186.         LinkedList<Node<E>> stack = new LinkedList<Node<E>>();  
  187.         Node<E> currentNode = root;  
  188.         Node<E> rightNode = null;  
  189.         while (currentNode != null || !stack.isEmpty()) {  
  190.             // 一直循环到二叉排序树最左端的叶子结点(currentNode是null)  
  191.             while (currentNode != null) {  
  192.                 stack.push(currentNode);  
  193.                 currentNode = currentNode.left;  
  194.             }  
  195.             currentNode = stack.pop();  
  196.             // 当前结点没有右结点或上一个结点(已经输出的结点)是当前结点的右结点,则输出当前结点  
  197.             while (currentNode.right == null || currentNode.right == rightNode) {  
  198.                 System.out.print(currentNode.value + " ");  
  199.                 rightNode = currentNode;  
  200.                 if (stack.isEmpty()) {  
  201.                     return//root以输出,则遍历结束  
  202.                 }  
  203.                 currentNode = stack.pop();  
  204.             }  
  205.             stack.push(currentNode); //还有右结点没有遍历  
  206.             currentNode = currentNode.right;  
  207.         }  
  208.     }  
  209.       
  210.     /** 
  211.      * 广度优先遍历二叉树,又称层次遍历二叉树 
  212.      * @param node 
  213.      */  
  214.     public void breadthFirstTraverse(Node<E> root) {  
  215.         Queue<Node<E>> queue = new LinkedList<Node<E>>();  
  216.         Node<E> currentNode = null;  
  217.         queue.offer(root);  
  218.         while (!queue.isEmpty()) {  
  219.             currentNode = queue.poll();  
  220.             System.out.print(currentNode.value + " ");  
  221.             if (currentNode.left != null)  
  222.                 queue.offer(currentNode.left);  
  223.             if (currentNode.right != null)  
  224.                 queue.offer(currentNode.right);  
  225.         }  
  226.     }  
  227.       
  228. }  

2.2、输出结果

先序遍历(递归):35 20 15 16 29 28 30 40 50 45 55 
中序遍历(递归):15 16 20 28 29 30 35 40 45 50 55 
后序遍历(递归):16 15 28 30 29 20 45 55 50 40 35 
先序遍历(非递归):35 20 15 16 29 28 30 40 50 45 55 
中序遍历(非递归):15 16 20 28 29 30 35 40 45 50 55 
后序遍历(非递归):16 15 28 30 29 20 45 55 50 40 35 
广度优先遍历:35 20 40 15 29 50 16 28 30 45 55 

0 0