zoukankan      html  css  js  c++  java
  • 二叉查找树的java实现

      1 package 查找;
      2 
      3 import java.util.ArrayList;
      4 import java.util.List;
      5 
      6 public class BST<Key extends Comparable<Key>, Value> {
      7     private class Node {
      8         private Key key; //
      9         private Value value;//
     10         private Node left, right; // 指向子树的链接
     11         private int n; // 以该节点为根的子树中的节点总数
     12 
     13         public Node(Key key, Value val, int n) {
     14             this.key = key;
     15             this.value = val;
     16             this.n = n;
     17         }
     18     }
     19 
     20     private Node root;
     21 
     22     public int size() {
     23         return size(root);
     24     }
     25 
     26     private int size(Node x) {
     27         if (x == null)
     28             return 0;
     29         else
     30             return x.n;
     31     }
     32 
     33     /**
     34      * 如果树是空的,则查找未命中 如果被查找的键小于根节点,则在左子树中继续查找 如果被查找的键大于根节点,则在右子树中继续查找
     35      * 如果被查找的键和根节点的键相等,查找命中
     36      * 
     37      * @param key
     38      * @return
     39      */
     40     public Value get(Key key) {
     41         return get(root, key);
     42     }
     43 
     44     private Value get(Node x, Key key) {
     45         if (x == null)
     46             return null;
     47         int cmp = key.compareTo(x.key);
     48         if (cmp < 0)
     49             return get(x.left, key);
     50         else if (cmp > 0)
     51             return get(x.right, key);
     52         else
     53             return x.value;
     54     }
     55 
     56     /**
     57      * 二叉查找树的一个很重要的特性就是插入的实现难度和查找差不多。 
     58      * 当查找到一个不存在与树中的节点(null)时,new 新节点,并将上一路径指向该节点
     59      * 
     60      * @param key
     61      * @param val
     62      */
     63     public void put(Key key, Value val) {
     64         root = put(root, key, val);
     65     }
     66 
     67     private Node put(Node x, Key key, Value val) {
     68         if (x == null)
     69             return new Node(key, val, 1);
     70         int cmp = key.compareTo(x.key);
     71         if (cmp < 0)
     72             x.left = put(x.left, key, val);
     73         else if (cmp > 0)
     74             x.right = put(x.right, key, val);
     75         else
     76             x.value = val;
     77         x.n = 1 + size(x.left) + size(x.right); // 要及时更新节点的子树数量
     78         return x;
     79     }
     80 
     81     public Key min() {
     82         return min(root).key;
     83     }
     84 
     85     private Node min(Node x) {
     86         if (x.left == null)
     87             return x;
     88         return min(x.left);
     89     }
     90 
     91     public Key max() {
     92         return max(root).key;
     93     }
     94 
     95     private Node max(Node x) {
     96         if (x.right == null)
     97             return x;
     98         return max(x.right);
     99     }
    100 
    101     /**
    102      * 向下取整:找出小于等于该键的最大键
    103      * 
    104      * @param key
    105      * @return
    106      */
    107     public Key floor(Key key) {
    108         Node x = floor(root, key);
    109         if (x == null)
    110             return null;
    111         else
    112             return x.key;
    113     }
    114 
    115     /**
    116      * 如果给定的键key小于二叉查找树的根节点的键,那么小于等于key的最大键一定出现在根节点的左子树中
    117      * 如果给定的键key大于二叉查找树的根节点,那么只有当根节点右子树中存在大于等于key的节点时,
    118      * 小于等于key的最大键才会出现在右子树中,否则根节点就是小于等于key的最大键
    119      * 
    120      * @param x
    121      * @param key
    122      * @return
    123      */
    124     private Node floor(Node x, Key key) {
    125         if (x == null)
    126             return null;
    127         int cmp = key.compareTo(x.key);
    128         if (cmp == 0)
    129             return x;
    130         else if (cmp < 0)
    131             return floor(x.left, key);
    132         else {
    133             Node t = floor(x.right, key);
    134             if (t == null)
    135                 return x;
    136             else
    137                 return t;
    138         }
    139     }
    140 
    141     /**
    142      * 向上取整:找出大于等于该键的最小键
    143      * 
    144      * @param key
    145      * @return
    146      */
    147     public Key ceiling(Key key) {
    148         Node x = ceiling(root, key);
    149         if (x == null)
    150             return null;
    151         else
    152             return x.key;
    153     }
    154 
    155     /**
    156      * 如果给定的键key大于二叉查找树的根节点的键,那么大于等于key的最小键一定出现在根节点的右子树中
    157      * 如果给定的键key小于二叉查找树的根节点,那么只有当根节点左子树中存在大于等于key的节点时,
    158      * 大于等于key的最小键才会出现在左子树中,否则根节点就是大于等于key的最小键
    159      * 
    160      * @param x
    161      * @param key
    162      * @return
    163      */
    164     private Node ceiling(Node x, Key key) {
    165         if (x == null)
    166             return null;
    167         int cmp = key.compareTo(x.key);
    168         if (cmp == 0)
    169             return x;
    170         else if (cmp > 0) {
    171             return ceiling(x.right, key);
    172         } else {
    173             Node t = floor(x.left, key);
    174             if (t == null)
    175                 return x;
    176             else
    177                 return t;
    178         }
    179     }
    180 
    181     /**
    182      * 选择排名为k的节点
    183      * 
    184      * @param k
    185      * @return
    186      */
    187     public Key select(int k) {
    188         return select(root, k).key;
    189     }
    190 
    191     private Node select(Node x, int k) {
    192         if (x == null)
    193             return null;
    194         int t = size(x.left);
    195         if (t > k)
    196             return select(x.left, k);
    197         else if (t < k)
    198             return select(x.right, k - t - 1);// 根节点也要排除掉
    199         else
    200             return x;
    201     }
    202 
    203     /**
    204      * 查找给定键值的排名
    205      * 
    206      * @param key
    207      * @return
    208      */
    209     public int rank(Key key) {
    210         return rank(key, root);
    211     }
    212 
    213     private int rank(Key key, Node x) {
    214         if (x == null)
    215             return 0;
    216         int cmp = key.compareTo(x.key);
    217         if (cmp < 0)
    218             return rank(key, x.left);
    219         else if (cmp > 0)
    220             return 1 + size(x.left) + rank(key, x.right);
    221         else
    222             return size(x.left);
    223     }
    224     /**
    225      * 删除最小键值对
    226      */
    227     public void deleteMin(){
    228         root = deleteMin(root);
    229     }
    230     /**
    231      * 不断深入根节点的左子树直到遇见一个空链接,然后将指向该节点的链接指向该结点的右子树
    232      * 此时已经没有任何链接指向要被删除的结点,因此它会被垃圾收集器清理掉
    233      * @param x
    234      * @return
    235      */
    236     private Node deleteMin(Node x){
    237         if(x.left == null) return x.right;
    238         x.left = deleteMin(x.left);
    239         x.n = 1 + size(x.left)+size(x.right);
    240         return x;
    241     }
    242     
    243     public void deleteMax(){
    244         root = deleteMax(root);
    245     }
    246     private Node deleteMax(Node x){
    247         if(x.right == null ) return x.left;
    248         x.right = deleteMax(x.right);
    249         x.n = size(x.left)+size(x.right) + 1;
    250         return x;
    251     }
    252     
    253     public void delete(Key key){
    254         root = delete(root,key);
    255     }
    256     private Node delete(Node x, Key key){
    257         if(x == null) return null;
    258         int cmp = key.compareTo(x.key);
    259         if(cmp < 0) x.left = delete(x.left,key);
    260         else if(cmp > 0) x.right = delete(x.right,key);
    261         else{
    262             if(x.right == null) return x.left;
    263             if(x.left == null ) return x.right;
    264             /**
    265              * 如果被删除节点有两个子树,将被删除节点暂记为t
    266              * 从t的右子树中选取最小的节点x,将这个节点x的左子树设为t的左子树
    267              * 这个节点x的右子树设为t的右子树中删除了最小节点的子树,这样就成功替换了t的位置
    268              */
    269             Node t = x;
    270             x = min(t.right);
    271             x.right = deleteMin(t.right);
    272             x.left = t.left;
    273         }
    274         x.n = size(x.left) + size(x.right) +1;
    275         return x;
    276     }
    277     
    278     public String toString(){
    279         StringBuilder sb = new StringBuilder();
    280         toString(root,sb);
    281         sb.deleteCharAt(sb.length()-1);
    282         return sb.toString();
    283     }
    284     private void toString(Node x, StringBuilder sb){
    285         if(x == null ) return;
    286         toString(x.left,sb);
    287         sb.append("<"+x.key+","+x.value+">,");
    288         toString(x.right,sb);
    289     }
    290     
    291     public List<Key> keys(){
    292         return keys(min(),max());
    293     }
    294     public List<Key> keys(Key lo, Key hi){
    295         List<Key> list = new ArrayList<Key>();
    296         keys(root, list, lo, hi);
    297         return list;
    298     }
    299     private void keys(Node x, List<Key> list, Key lo, Key hi){
    300         if(x == null) return;
    301         int cmplo = lo.compareTo(x.key);
    302         int cmphi = hi.compareTo(x.key);
    303         if(cmplo < 0 ) keys(x.left,list,lo,hi);
    304         if(cmplo <= 0 && cmphi >= 0) list.add(x.key);
    305         if(cmphi > 0 ) keys(x.right,list,lo,hi);
    306     }
    307     public static void main(String[] args){
    308         BST<Integer,String> bst = new BST<Integer,String>();
    309         bst.put(5, "e");
    310         bst.put(1, "a");
    311         bst.put(4, "d");
    312         bst.put(9, "i");
    313         bst.put(10, "j");
    314         bst.put(2, "b");
    315         bst.put(7, "g");
    316         bst.put(3, "c");
    317         bst.put(8, "h");
    318         bst.put(6, "f");        
    319         List<Integer> keys = bst.keys();
    320         for(int key : keys){
    321             System.out.print("<"+key+","+bst.get(key)+">,");
    322         }
    323         System.out.println();
    324         bst.deleteMin();
    325         System.out.println(bst.toString());
    326         bst.deleteMax();
    327         System.out.println(bst.toString());
    328         bst.delete(7);
    329         System.out.println(bst.toString());
    330     }
    331 }

    树还是应该做成可视化的方便查看和调试,后续我将更新一个可视化的生成图的版本出来,恩,一定要记得这件事

  • 相关阅读:
    chapter01 Bob'store
    echo拼接
    《PHP和MySql Web》书,<input>属性
    http协议
    asc18_hpl,hpc,hpcg
    考研北邮总结[转发共享]
    考研经验总结【转发共享】
    ISBN号码 201312-2
    出现次数最多的数 201312-1
    相反数 201403-1
  • 原文地址:https://www.cnblogs.com/evasean/p/7327278.html
Copyright © 2011-2022 走看看