`

【转】java实现二叉查找树

    博客分类:
  • java
 
阅读更多

    转自:http://blog.csdn.net/zyj8170/article/details/7045226

    1. /**   
    2.  * @author zyj8170  2011-2-13   
    3.  *    
    4.  * 此程序实现一个二叉查找树的功能,可以进行动态插入、删除关键字;   
    5.  * 查询给定关键字、最小关键字、最大关键字;转换为有序列表(用于排序)   
    6.  *    
    7.  *    
    8.  */   
    9.   
    10. import  java.util.ArrayList;  
    11. import  java.util.List;  
    12.   
    13. public   class  BinarySearchTree {  
    14.   
    15.     // 树的根结点   
    16.     private  TreeNode root =  null ;  
    17.   
    18.     // 遍历结点列表   
    19.     private  List<TreeNode> nodelist =  new  ArrayList<TreeNode>();  
    20.   
    21.     private   class  TreeNode {  
    22.   
    23.         private   int  key;  
    24.         private  TreeNode leftChild;  
    25.         private  TreeNode rightChild;  
    26.         private  TreeNode parent;  
    27.   
    28.         public  TreeNode( int  key, TreeNode leftChild, TreeNode rightChild,  
    29.                 TreeNode parent) {  
    30.             this .key = key;  
    31.             this .leftChild = leftChild;  
    32.             this .rightChild = rightChild;  
    33.             this .parent = parent;  
    34.         }  
    35.   
    36.         public   int  getKey() {  
    37.             return  key;  
    38.         }  
    39.   
    40.         public  String toString() {  
    41.             String leftkey = (leftChild == null  ?  ""  : String  
    42.                     .valueOf(leftChild.key));  
    43.             String rightkey = (rightChild == null  ?  ""  : String  
    44.                     .valueOf(rightChild.key));  
    45.             return   "("  + leftkey +  " , "  + key +  " , "  + rightkey +  ")" ;  
    46.         }  
    47.   
    48.     }  
    49.   
    50.     /**  
    51.      * isEmpty: 判断二叉查找树是否为空;若为空,返回 true ,否则返回 false .  
    52.      *   
    53.      */   
    54.     public   boolean  isEmpty() {  
    55.         if  (root ==  null ) {  
    56.             return   true ;  
    57.         } else  {  
    58.             return   false ;  
    59.         }  
    60.     }  
    61.   
    62.     /**  
    63.      * TreeEmpty: 对于某些二叉查找树操作(比如删除关键字)来说,若树为空,则抛出异常。  
    64.      */   
    65.     public   void  TreeEmpty()  throws  Exception {  
    66.         if  (isEmpty()) {  
    67.             throw   new  Exception( "树为空!" );  
    68.         }  
    69.     }  
    70.   
    71.     /**  
    72.      * search: 在二叉查找树中查询给定关键字  
    73.      *   
    74.      * @param key  
    75.      *            给定关键字  
    76.      * @return 匹配给定关键字的树结点  
    77.      */   
    78.     public  TreeNode search( int  key) {  
    79.         TreeNode pNode = root;  
    80.         while  (pNode !=  null  && pNode.key != key) {  
    81.             if  (key < pNode.key) {  
    82.                 pNode = pNode.leftChild;  
    83.             } else  {  
    84.                 pNode = pNode.rightChild;  
    85.             }  
    86.         }  
    87.         return  pNode;  
    88.     }  
    89.   
    90.     /**  
    91.      * minElemNode: 获取二叉查找树中的最小关键字结点  
    92.      *   
    93.      * @return 二叉查找树的最小关键字结点  
    94.      * @throws Exception  
    95.      *             若树为空,则抛出异常  
    96.      */   
    97.     public  TreeNode minElemNode(TreeNode node)  throws  Exception {  
    98.         if  (node ==  null ) {  
    99.             throw   new  Exception( "树为空!" );  
    100.         }  
    101.         TreeNode pNode = node;  
    102.         while  (pNode.leftChild !=  null ) {  
    103.             pNode = pNode.leftChild;  
    104.         }  
    105.         return  pNode;  
    106.     }  
    107.   
    108.     /**  
    109.      * maxElemNode: 获取二叉查找树中的最大关键字结点  
    110.      *   
    111.      * @return 二叉查找树的最大关键字结点  
    112.      * @throws Exception  
    113.      *             若树为空,则抛出异常  
    114.      */   
    115.     public  TreeNode maxElemNode(TreeNode node)  throws  Exception {  
    116.         if  (node ==  null ) {  
    117.             throw   new  Exception( "树为空!" );  
    118.         }  
    119.         TreeNode pNode = node;  
    120.         while  (pNode.rightChild !=  null ) {  
    121.             pNode = pNode.rightChild;  
    122.         }  
    123.         return  pNode;  
    124.     }  
    125.   
    126.     /**  
    127.      * successor: 获取给定结点在中序遍历顺序下的后继结点  
    128.      *   
    129.      * @param node  
    130.      *            给定树中的结点  
    131.      * @return 若该结点存在中序遍历顺序下的后继结点,则返回其后继结点;否则返回 null  
    132.      * @throws Exception  
    133.      */   
    134.     public  TreeNode successor(TreeNode node)  throws  Exception {  
    135.         if  (node ==  null ) {  
    136.             return   null ;  
    137.         }  
    138.   
    139.         // 若该结点的右子树不为空,则其后继结点就是右子树中的最小关键字结点   
    140.         if  (node.rightChild !=  null ) {  
    141.             return  minElemNode(node.rightChild);  
    142.         }  
    143.         // 若该结点右子树为空   
    144.         TreeNode parentNode = node.parent;  
    145.         while  (parentNode !=  null  && node == parentNode.rightChild) {  
    146.             node = parentNode;  
    147.             parentNode = parentNode.parent;  
    148.         }  
    149.         return  parentNode;  
    150.     }  
    151.   
    152.     /**  
    153.      * precessor: 获取给定结点在中序遍历顺序下的前趋结点  
    154.      *   
    155.      * @param node  
    156.      *            给定树中的结点  
    157.      * @return 若该结点存在中序遍历顺序下的前趋结点,则返回其前趋结点;否则返回 null  
    158.      * @throws Exception  
    159.      */   
    160.     public  TreeNode precessor(TreeNode node)  throws  Exception {  
    161.         if  (node ==  null ) {  
    162.             return   null ;  
    163.         }  
    164.   
    165.         // 若该结点的左子树不为空,则其前趋结点就是左子树中的最大关键字结点   
    166.         if  (node.leftChild !=  null ) {  
    167.             return  maxElemNode(node.leftChild);  
    168.         }  
    169.         // 若该结点左子树为空   
    170.         TreeNode parentNode = node.parent;  
    171.         while  (parentNode !=  null  && node == parentNode.leftChild) {  
    172.             node = parentNode;  
    173.             parentNode = parentNode.parent;  
    174.         }  
    175.         return  parentNode;  
    176.     }  
    177.   
    178.     /**  
    179.      * insert: 将给定关键字插入到二叉查找树中  
    180.      *   
    181.      * @param key  
    182.      *            给定关键字  
    183.      */   
    184.     public   void  insert( int  key) {  
    185.         TreeNode parentNode = null ;  
    186.         TreeNode newNode = new  TreeNode(key,  null null null );  
    187.         TreeNode pNode = root;  
    188.         if  (root ==  null ) {  
    189.             root = newNode;  
    190.             return ;  
    191.         }  
    192.         while  (pNode !=  null ) {  
    193.             parentNode = pNode;  
    194.             if  (key < pNode.key) {  
    195.                 pNode = pNode.leftChild;  
    196.             } else   if  (key > pNode.key) {  
    197.                 pNode = pNode.rightChild;  
    198.             } else  {  
    199.                 // 树中已存在匹配给定关键字的结点,则什么都不做直接返回   
    200.                 return ;  
    201.             }  
    202.         }  
    203.         if  (key < parentNode.key) {  
    204.             parentNode.leftChild = newNode;  
    205.             newNode.parent = parentNode;  
    206.         } else  {  
    207.             parentNode.rightChild = newNode;  
    208.             newNode.parent = parentNode;  
    209.         }  
    210.   
    211.     }  
    212.   
    213.     /**  
    214.      * insert: 从二叉查找树中删除匹配给定关键字相应的树结点  
    215.      *   
    216.      * @param key  
    217.      *            给定关键字  
    218.      */   
    219.     public   void  delete( int  key)  throws  Exception {  
    220.         TreeNode pNode = search(key);  
    221.         if  (pNode ==  null ) {  
    222.             throw   new  Exception( "树中不存在要删除的关键字!" );  
    223.         }  
    224.         delete(pNode);  
    225.     }  
    226.   
    227.     /**  
    228.      * delete: 从二叉查找树中删除给定的结点.  
    229.      *   
    230.      * @param pNode  
    231.      *            要删除的结点  
    232.      *   
    233.      *            前置条件: 给定结点在二叉查找树中已经存在  
    234.      * @throws Exception  
    235.      */   
    236.     private   void  delete(TreeNode pNode)  throws  Exception {  
    237.         if  (pNode ==  null ) {  
    238.             return ;  
    239.         }  
    240.         if  (pNode.leftChild ==  null  && pNode.rightChild ==  null ) {  // 该结点既无左孩子结点,也无右孩子结点   
    241.             TreeNode parentNode = pNode.parent;  
    242.             if  (pNode == parentNode.leftChild) {  
    243.                 parentNode.leftChild = null ;  
    244.             } else  {  
    245.                 parentNode.rightChild = null ;  
    246.             }  
    247.             return ;  
    248.         }  
    249.         if  (pNode.leftChild ==  null  && pNode.rightChild !=  null ) {  // 该结点左孩子结点为空,右孩子结点非空   
    250.             TreeNode parentNode = pNode.parent;  
    251.             if  (pNode == parentNode.leftChild) {  
    252.                 parentNode.leftChild = pNode.rightChild;  
    253.                 pNode.rightChild.parent = parentNode;  
    254.             } else  {  
    255.                 parentNode.rightChild = pNode.rightChild;  
    256.                 pNode.rightChild.parent = parentNode;  
    257.             }  
    258.             return ;  
    259.         }  
    260.         if  (pNode.leftChild !=  null  && pNode.rightChild ==  null ) {  // 该结点左孩子结点非空,右孩子结点为空   
    261.             TreeNode parentNode = pNode.parent;  
    262.             if  (pNode == parentNode.leftChild) {  
    263.                 parentNode.leftChild = pNode.leftChild;  
    264.                 pNode.rightChild.parent = parentNode;  
    265.             } else  {  
    266.                 parentNode.rightChild = pNode.leftChild;  
    267.                 pNode.rightChild.parent = parentNode;  
    268.             }  
    269.             return ;  
    270.         }  
    271.         // 该结点左右孩子结点均非空,则删除该结点的后继结点,并用该后继结点取代该结点   
    272.         TreeNode successorNode = successor(pNode);  
    273.         delete(successorNode);  
    274.         pNode.key = successorNode.key;  
    275.     }  
    276.   
    277.     /**  
    278.      * inOrderTraverseList: 获得二叉查找树的中序遍历结点列表  
    279.      *   
    280.      * @return 二叉查找树的中序遍历结点列表  
    281.      */   
    282.     public  List<TreeNode> inOrderTraverseList() {  
    283.         if  (nodelist !=  null ) {  
    284.             nodelist.clear();  
    285.         }  
    286.         inOrderTraverse(root);  
    287.         return  nodelist;  
    288.     }  
    289.   
    290.     /**  
    291.      * inOrderTraverse: 对给定二叉查找树进行中序遍历  
    292.      *   
    293.      * @param root  
    294.      *            给定二叉查找树的根结点  
    295.      */   
    296.     private   void  inOrderTraverse(TreeNode root) {  
    297.         if  (root !=  null ) {  
    298.             inOrderTraverse(root.leftChild);  
    299.             nodelist.add(root);  
    300.             inOrderTraverse(root.rightChild);  
    301.         }  
    302.     }  
    303.   
    304.     /**  
    305.      * toStringOfOrderList: 获取二叉查找树中关键字的有序列表  
    306.      *   
    307.      * @return 二叉查找树中关键字的有序列表  
    308.      */   
    309.     public  String toStringOfOrderList() {  
    310.         StringBuilder sbBuilder = new  StringBuilder( " [ " );  
    311.         for  (TreeNode p : inOrderTraverseList()) {  
    312.             sbBuilder.append(p.key);  
    313.             sbBuilder.append(" " );  
    314.         }  
    315.         sbBuilder.append("]" );  
    316.         return  sbBuilder.toString();  
    317.     }  
    318.   
    319.     /**  
    320.      * 获取该二叉查找树的字符串表示  
    321.      */   
    322.     public  String toString() {  
    323.         StringBuilder sbBuilder = new  StringBuilder( " [ " );  
    324.         for  (TreeNode p : inOrderTraverseList()) {  
    325.             sbBuilder.append(p);  
    326.             sbBuilder.append(" " );  
    327.         }  
    328.         sbBuilder.append("]" );  
    329.         return  sbBuilder.toString();  
    330.     }  
    331.   
    332.     public  TreeNode getRoot() {  
    333.         return  root;  
    334.     }  
    335.   
    336.     public   static   void  testNode(BinarySearchTree bst, TreeNode pNode)  
    337.             throws  Exception {  
    338.         System.out.println("本结点: "  + pNode);  
    339.         System.out.println("前趋结点: "  + bst.precessor(pNode));  
    340.         System.out.println("后继结点: "  + bst.successor(pNode));  
    341.     }  
    342.   
    343.     public   static   void  testTraverse(BinarySearchTree bst) {  
    344.         System.out.println("二叉树遍历:"  + bst);  
    345.         System.out.println("二叉查找树转换为有序列表: "  + bst.toStringOfOrderList());  
    346.     }  
    347.   
    348.     public   static   void  main(String[] args) {  
    349.         try  {  
    350.             BinarySearchTree bst = new  BinarySearchTree();  
    351.             System.out.println("查找树是否为空? "  + (bst.isEmpty() ?  "是"  :  "否" ));  
    352.             int [] keys =  new   int [] {  15 6 18 3 7 13 20 2 9 4  };  
    353.             for  ( int  key : keys) {  
    354.                 bst.insert(key);  
    355.             }  
    356.             System.out.println("查找树是否为空? "  + (bst.isEmpty() ?  "是"  :  "否" ));  
    357.             TreeNode minkeyNode = bst.minElemNode(bst.getRoot());  
    358.             System.out.println("最小关键字: "  + minkeyNode.getKey());  
    359.             testNode(bst, minkeyNode);  
    360.             TreeNode maxKeyNode = bst.maxElemNode(bst.getRoot());  
    361.             System.out.println("最大关键字: "  + maxKeyNode.getKey());  
    362.             testNode(bst, maxKeyNode);  
    363.             System.out.println("根结点关键字: "  + bst.getRoot().getKey());  
    364.             testNode(bst, bst.getRoot());  
    365.             testTraverse(bst);  
    366.             System.out.println("****************************** " );  
    367.             testTraverse(bst);  
    368.         } catch  (Exception e) {  
    369.             System.out.println(e.getMessage());  
    370.             e.printStackTrace();  
    371.         }  
    372.     }  
    373.   

    分享到:
    评论

    相关推荐

    Global site tag (gtag.js) - Google Analytics