二叉排序树的各种操作及平衡测试

  1. 过程概述
    • 创建一个二叉排序树
    • 插入24个随机数据
    • 输出前序遍历
    • 输出中序遍历
    • 输出后序遍历
    • 搜索一个给定的节点是否在树中
    • 计算二叉排序树的节点数
    • 计算所有叶子节点的深度的总和
    • 计算二叉排序树的叶子数
    • 计算所有叶子节点的平均深度
    • 计算二叉排序树的高度(最大的叶子节点的深度)
     
  2. 代码清单
    • BSTNode.java // 二叉排序树节点
       1 public class BSTNode {
       2 
       3     int item; // The data in this node.
       4     BSTNode left, right; // Pointer to subtree.
       5 
       6     public BSTNode(int el) {
       7         this(el, null, null);
       8     }
       9 
      10     public BSTNode(int el, BSTNode left, BSTNode rigth) {
      11         this.item = el; 
      12         this.left = left; 
      13         this.right = rigth;
      14     }
      15 
      16 }
       
    • BST.java // 二叉排序树
        1 public class BST {
        2 
        3     BSTNode root; // Pointer to the root node in the tree.
        4 
        5     void insert(int x) {
        6         root = insert(x, root);
        7     }
        8 
        9     private BSTNode insert(int x, BSTNode t) {
       10         if (t == null) // The tree is empty
       11             return new BSTNode(x);
       12         if (x < t.item)
       13             t.left = insert(x, t.left);
       14         else if (x >= t.item)
       15             t.right = insert(x, t.right);
       16         return t;
       17     }
       18 
       19     void visit(BSTNode p) {
       20         System.out.print(p.item + " ");
       21     }
       22 
       23     void preorder() {
       24         preorder(root);
       25     }
       26 
       27     void inorder() {
       28         inorder(root);
       29     }
       30 
       31     void postorder() {
       32         postorder(root);
       33     }
       34 
       35     private void preorder(BSTNode p) {
       36         if (p != null) {
       37             visit(p);
       38             preorder(p.left);
       39             preorder(p.right);
       40         }
       41     }
       42 
       43     private void inorder(BSTNode p) {
       44         if (p != null) {
       45             preorder(p.left);
       46             visit(p);
       47             preorder(p.right);
       48         }
       49     }
       50 
       51     private void postorder(BSTNode p) {
       52         if (p != null) {
       53             preorder(p.left);
       54             preorder(p.right);
       55             visit(p);
       56         }
       57     }
       58 
       59     /**
       60      * Count the nodes in the binary tree to which root points,
       61      * and return the answer. If root is null, the answer is zero.
       62      */
       63     static int countNodes(BSTNode root) {
       64         if (root == null)
       65             return 0; // The tree is empty. It contains no nodes.
       66         else
       67             return countNodes(root.left) + countNodes(root.right) + 1;
       68     }
       69 
       70     // Return the number of leaves in the tree to which node points.
       71     static int countLeaves(BSTNode node) {
       72         if (node == null)
       73             return 0; // An empty tree has no leaves.
       74         else if (node.left == null && node.right == null)
       75             return 1; // Node is a leaf.
       76         else
       77             return countLeaves(node.left) + countLeaves(node.right);
       78     }
       79 
       80     /**
       81      * Return true if item is one of the items in the binary sort tree
       82      * to which root points. Return false if not.
       83      */
       84     static boolean contains(BSTNode node, int item) {
       85         while (true) {
       86             if (node == null)
       87                 return false; // Tree is empty, it doesn't contain item.
       88             if (item == node.item)
       89                 return true; // found the item.
       90             if (item < node.item)
       91                 node = node.left; // advance the runner down one level to the left.
       92             else
       93                 node = node.right; // advance the runner down one level to the right.
       94         }
       95     }
       96 
       97     static int sumDeps(BSTNode node, int dep) {
       98         if (node == null)
       99             return 0; // The tree is empty, return 0.
      100         else if (node.left == null && node.right == null)
      101             return dep; // The node is a leaf, return the depth of this node.
      102         else
      103             return sumDeps(node.left, dep+1) + sumDeps(node.right, dep+1);
      104     }
      105 
      106     static int maxLeafDep(BSTNode node, int dep) {
      107         if (node == null)
      108             return 0; // The tree is empty, return 0.
      109         else if (node.left == null && node.right == null)
      110             return dep; // The node is a leaf, return the depth of this node.
      111         else
      112             return Math.max(maxLeafDep(node.left, dep+1), maxLeafDep(node.right, dep+1));
      113     }
      114 
      115 }
       
    • Main.java // 主程序
       1 //Makes the random tree and prints the statistics.
       2 
       3 import java.util.Random;
       4 
       5 public class Main {
       6     public static void main(String[] args) {
       7         BST t = new BST();
       8         Random random = new Random();
       9         int n = 24;
      10         for (int i = 0; i < n; i++)
      11             t.insert(random.nextInt(n) + 1);
      12         t.preorder();
      13         System.out.println(" preorder");
      14         t.inorder();
      15         System.out.println(" inorder");
      16         t.postorder();
      17         System.out.println(" postorder");
      18         System.out.println("contains(" + n + ")?:" + BST.contains(t.root, n));
      19         System.out.println("Nodes(root):" + BST.countNodes(t.root));
      20         int sum_dep = BST.sumDeps(t.root, 0),
      21             leaves = BST.countLeaves(t.root);
      22         System.out.println("sumDeps(root):" + sum_dep);
      23         System.out.println("leaves(root):" + leaves);
      24         System.out.println("avgDep(sumDeps/leaves):" + (double)sum_dep / leaves);
      25         System.out.println("maxDep(root):" + BST.maxLeafDep(t.root, 0));
      26     }
      27 }

       

  3. 输出结果

    9 2 2 4 2 7 4 6 8 10 9 20 10 17 16 10 15 10 15 19 20 24 20 21 preorder
    2 2 4 2 7 4 6 8 9 10 9 20 10 17 16 10 15 10 15 19 20 24 20 21 inorder
    2 2 4 2 7 4 6 8 10 9 20 10 17 16 10 15 10 15 19 20 24 20 21 9 postorder
    contains(24)?:true
    Nodes(root):24
    sumDeps(root):44
    leaves(root):8
    avgDep(sumDeps/leaves):5.5
    maxDep(root):8

  4. 分析报告

上面为了方便演示遍历,n只设到了24,为了测试裸二叉排序树在随机数据下的平衡情况,24太小肯定不够,我把n设到1024再把程序跑N次,发现树的叶子节点的平均深度约为12,高于完全二叉树的9,高出1/3,最大深度约为20。二叉排序树在平均情况下运行时间为O(logN),在最坏的情况下(递增或递减的数据)会退化为一条链表,运行时间为O(N)。可以在插入数据时调整节点位置让二叉排序树保持平衡(比如AVL树……),保证平均和最坏情况下运行时间为O(logN)。

posted @ 2012-12-26 20:47  LYLtim  阅读(697)  评论(0编辑  收藏  举报