• 《算法》第三章部分程序 part 2


    ▶ 书中第三章部分程序,加上自己补充的代码,平衡二叉搜索树

    ● 平衡二叉搜索树

      1 package package01;
      2 
      3 import java.util.NoSuchElementException;
      4 import edu.princeton.cs.algs4.Queue;
      5 import edu.princeton.cs.algs4.StdIn;
      6 import edu.princeton.cs.algs4.StdOut;
      7 
      8 public class class01<Key extends Comparable<Key>, Value>
      9 {
     10     private class Node             // 二叉树节点
     11     {
     12         private Key key;
     13         private Value val;
     14         private Node left, right;
     15         private int size;          // 节点总数(包括根节点和子树)
     16 
     17         public Node(Key key, Value val, int size)
     18         {
     19             this.key = key;
     20             this.val = val;
     21             this.size = size;
     22         }
     23     }
     24 
     25     private Node root;             // 二叉树根节点
     26 
     27     public class01() {}
     28 
     29     public int size()
     30     {
     31         return size(root);
     32     }
     33 
     34     private int size(Node x)
     35     {
     36         if (x == null)
     37             return 0;
     38         return x.size;
     39     }
     40 
     41     public boolean isEmpty()
     42     {
     43         return size() == 0;
     44     }
     45 
     46     public Value get(Key key)                   // 查找
     47     {
     48         if (key == null)
     49             throw new IllegalArgumentException("
    <get> key == null.
    ");
     50         return getKernel(root, key);
     51     }
     52 
     53     private Value getKernel(Node x, Key key)    // 查找内核,递归地向下找
     54     {
     55         if (x == null)
     56             return null;
     57         int cmp = key.compareTo(x.key);
     58         if (cmp < 0)
     59             return getKernel(x.left, key);
     60         if (cmp > 0)
     61             return getKernel(x.right, key);
     62         return x.val;
     63     }
     64 
     65     public boolean contains(Key key)            // 判断 key 是否在树中
     66     {
     67         if (key == null)
     68             throw new IllegalArgumentException("
    <contains> key == null.
    ");
     69         return get(key) != null;
     70     }
     71 
     72     public void put(Key key, Value val)         // 插入
     73     {
     74         if (key == null)
     75             throw new IllegalArgumentException("
    <put> key == null.
    ");
     76         if (val == null)                        // 空值插入作删除处理
     77             delete(key);
     78         else
     79             root = putKernel(root, key, val);
     80         //assert check();                         // 对树作修改时需要检查
     81     }
     82 
     83     private Node putKernel(Node x, Key key, Value val)  // 插入内核,插到适当的位置上去
     84     {
     85         if (x == null)
     86             return new Node(key, val, 1);
     87         int cmp = key.compareTo(x.key);
     88         if (cmp < 0)
     89             x.left = putKernel(x.left, key, val);
     90         else if (cmp > 0)
     91             x.right = putKernel(x.right, key, val);
     92         else
     93             x.val = val;
     94         x.size = 1 + size(x.left) + size(x.right);
     95         return x;
     96     }
     97 
     98     public void deleteMin()                         // 删除最小节点(先根序首节点)
     99     {
    100         if (isEmpty())
    101             throw new NoSuchElementException("
    <deleteMin> underflow.
    ");
    102         root = deleteMinKernel(root);
    103         //assert check();
    104     }
    105 
    106     private Node deleteMinKernel(Node x)            // 删除最小节点内核
    107     {
    108         if (x.left == null)                         // 左子树为空,返回右子树(相当于删除根节点)
    109             return x.right;
    110         x.left = deleteMinKernel(x.left);           // 左子树不空,继续往下找
    111         x.size = size(x.left) + size(x.right) + 1;  // 重新计算输的大小
    112         return x;
    113     }
    114 
    115     public void deleteMax()                         // 删除最大节点(先根序末节点)
    116     {
    117         if (isEmpty())
    118             throw new NoSuchElementException("
    <deleteMax> underflow.
    ");
    119         root = deleteMaxKernel(root);
    120         //assert check();
    121     }
    122 
    123     private Node deleteMaxKernel(Node x)
    124     {
    125         if (x.right == null)                        // 右子树为空,返回左子树(相当于删除根节点)
    126             return x.left;
    127         x.right = deleteMaxKernel(x.right);         // 右子树不空,继续往下找
    128         x.size = size(x.left) + size(x.right) + 1;  // 重新计算输的大小
    129 
    130         return x;
    131     }
    132 
    133     public void delete(Key key)                      // 删除指定 key 的节点
    134     {
    135         if (key == null)
    136             throw new IllegalArgumentException("
    <delete> key == null.
    ");
    137         root = deleteKernel(root, key);
    138         //assert check();
    139     }
    140 
    141     private Node deleteKernel(Node x, Key key)       // 删除节点内核
    142     {
    143         if (x == null)
    144             return null;
    145         int cmp = key.compareTo(x.key);
    146         if (cmp < 0)
    147             x.left = deleteKernel(x.left, key);
    148         else if (cmp > 0)
    149             x.right = deleteKernel(x.right, key);
    150         else                                        // 找到了目标键
    151         {
    152             if (x.right == null)                    // 右子树为空就返回左子树,左子树为空就返回右子树
    153                 return x.left;
    154             if (x.left == null)
    155                 return x.right;
    156             Node t = x;                             // 左右子树都不空,设这里中根序遍历为 x -> a -> b
    157             x = min(t.right);                       // 找到 t 在中根序的下一个节点 a,赋给 x(结束后 x 的左子树一定为空)
    158             x.right = deleteMinKernel(t.right);     // 删除节点 a,删除函数返回 a 的下一个节点 b,赋给 x 的右子树
    159             x.left = t.left;                        // 原来的的左子树接到 x 的左子树
    160         }
    161         x.size = 1 + size(x.left) + size(x.right);
    162         return x;
    163     }
    164 
    165     public Key min()                                // 返回最小键
    166     {
    167         if (isEmpty())
    168             throw new NoSuchElementException("
    <delete> empty.
    ");
    169         return minKernel(root).key;
    170     }
    171 
    172     private Node minKernel(Node x)                  // 最小节点内核,需要递归
    173     {
    174         if (x.left == null)
    175             return x;
    176         return minKernel(x.left);
    177     }
    178 
    179     public Key max()                               // 返回最大键
    180     {
    181         if (isEmpty())
    182             throw new NoSuchElementException("
    <max> empty.
    ");
    183         return maxKernel(root).key;
    184     }
    185 
    186     private Node maxKernel(Node x)                 // 最大节点内核,需要递归
    187     {
    188         if (x.right == null)
    189             return x;
    190         return maxKernel(x.right);
    191     }
    192 
    193     public Key floor(Key key)                       // 返回不大于 key 的最大元素的键,不存在
    194     {
    195         if (key == null)
    196             throw new IllegalArgumentException("
    <floor> key == null.
    ");
    197         if (isEmpty())
    198             throw new NoSuchElementException("
    <floor> empty.
    ");
    199         Node x = floorKernel(root, key);
    200         return (x == null) ? null : x.key;
    201     }
    202 
    203     private Node floorKernel(Node x, Key key)       // floor 内核,需要递归
    204     {
    205         if (x == null)
    206             return null;
    207         int cmp = key.compareTo(x.key);
    208         if (cmp == 0)
    209             return x;
    210         if (cmp < 0)
    211             return floorKernel(x.left, key);
    212         Node t = floorKernel(x.right, key);         // 目标键较大时需要递归搜索 
    213         return (t == null) ? x : t;                 // 在母栈中保存了当前最好的结果 x,没有实现尾递归
    214     }
    215 
    216     public Key floor2(Key key)                      // floor 的尾递归实现
    217     {
    218         return floor2Kernel(root, key, null);
    219     }
    220 
    221     private Key floor2Kernel(Node x, Key key, Key best) // 调用时带上当前已经找到的最佳值
    222     {
    223         if (x == null)
    224             return best;
    225         int cmp = key.compareTo(x.key);
    226         if (cmp == 0)
    227             return x.key;
    228         if (cmp < 0)
    229             return floor2Kernel(x.left, key, best);
    230         return floor2Kernel(x.right, key, x.key);
    231     }
    232 
    233     public Key ceiling(Key key)                     // 返回不小于 key 的最大元素的键
    234     {
    235         if (key == null)
    236             throw new IllegalArgumentException("
    <ceiling> key == null.
    ");
    237         if (isEmpty())
    238             throw new NoSuchElementException("
    <ceiling> empty.
    ");
    239         Node x = ceilingKernel(root, key);
    240         return (x == null) ? null : x.key;
    241     }
    242 
    243     private Node ceilingKernel(Node x, Key key)     // ceiling 内核,需要递归
    244     {
    245         if (x == null)
    246             return null;
    247         int cmp = key.compareTo(x.key);
    248         if (cmp == 0)
    249             return x;
    250         if (cmp > 0)
    251             return ceilingKernel(x.right, key);
    252         Node t = ceilingKernel(x.left, key);
    253         return (t == null) ? x : t;
    254     }
    255 
    256     public Key ceiling2(Key key)                    // ceiling 的尾递归实现
    257     {
    258         return ceiling2Kernel(root, key, null);
    259     }
    260 
    261     private Key ceiling2Kernel(Node x, Key key, Key best)
    262     {
    263         if (x == null)
    264             return best;
    265         int cmp = key.compareTo(x.key);
    266         if (cmp == 0)
    267             return x.key;
    268         if (cmp < 0)
    269             return ceiling2Kernel(x.left, key, best);
    270         return ceiling2Kernel(x.right, key, x.key);
    271     }
    272 
    273     public Key select(int k)                        // 取出排第 k 的元素
    274     {
    275         if (k < 0 || k >= size())
    276             throw new IllegalArgumentException("
    <select> k < 0 || k >= size().
    ");
    277         return selectKernel(root, k).key;
    278     }
    279 
    280     private Node selectKernel(Node x, int k)        // 取元素内核,需要递归
    281     {
    282         if (x == null)
    283             return null;
    284         int t = size(x.left);                       // 树的元素数用于来计数
    285         if (k < t)
    286             return selectKernel(x.left, k);
    287         if (k > t)
    288             return selectKernel(x.right, k - t - 1);
    289         return x;
    290     }
    291 
    292     public int rank(Key key)                        // 计算键比 key 小的元素个数
    293     {
    294         if (key == null)
    295             throw new IllegalArgumentException("
    <rank> key == null.
    ");
    296         return rankKernel(key, root);
    297     }
    298 
    299     private int rankKernel(Key key, Node x)         // 计算函数内核,需要递归
    300     {
    301         if (x == null)
    302             return 0;
    303         int cmp = key.compareTo(x.key);
    304         if (cmp < 0)
    305             return rankKernel(key, x.left);
    306         if (cmp > 0)
    307             return 1 + size(x.left) + rankKernel(key, x.right);
    308         return size(x.left);
    309     }
    310 
    311     public Iterable<Key> keys()                     // 创建队列用于迭代器,中根序
    312     {
    313         if (isEmpty())
    314             return new Queue<Key>();
    315         Key lo = min(), hi = max();
    316         if (lo == null)
    317             throw new IllegalArgumentException("
    <iterable> lo == null.
    ");
    318         if (hi == null)
    319             throw new IllegalArgumentException("
    <iterable> hi == null.
    ");
    320         Queue<Key> queue = new Queue<Key>();
    321         keysKernel(root, queue, lo, hi);
    322         return queue;
    323     }
    324 
    325     private void keysKernel(Node x, Queue<Key> queue, Key lo, Key hi)   // 创建迭代器内核,需要递归
    326     {
    327         if (x == null)
    328             return;
    329         int cmplo = lo.compareTo(x.key);
    330         int cmphi = hi.compareTo(x.key);
    331         if (cmplo < 0)
    332             keysKernel(x.left, queue, lo, hi);
    333         if (cmplo <= 0 && cmphi >= 0)
    334             queue.enqueue(x.key);
    335         if (cmphi > 0)
    336             keysKernel(x.right, queue, lo, hi);
    337     }
    338     
    339     public Iterable<Key> levelOrder()           // 生成先根序队列
    340     {
    341         Queue<Key> keys = new Queue<Key>();
    342         Queue<Node> queue = new Queue<Node>();
    343         for (queue.enqueue(root); !queue.isEmpty();)
    344         {
    345             Node x = queue.dequeue();
    346             if (x == null)
    347                 continue;
    348             keys.enqueue(x.key);
    349             queue.enqueue(x.left);
    350             queue.enqueue(x.right);
    351         }
    352         return keys;
    353     }
    354 
    355     public int size(Key lo, Key hi)         // 计算键落在给定范围内的元素个数
    356     {
    357         if (lo == null)
    358             throw new IllegalArgumentException("
    <size> lo == null.
    ");
    359         if (hi == null)
    360             throw new IllegalArgumentException("
    <size> hi == null.
    ");
    361         if (lo.compareTo(hi) > 0)
    362             return 0;
    363         if (contains(hi))
    364             return rank(hi) - rank(lo) + 1;
    365         return rank(hi) - rank(lo);
    366     }
    367 
    368     public int height()                     // 计算树的高度
    369     {
    370         return heightKernel(root);
    371     }
    372 
    373     private int heightKernel(Node x)        // 计算树高度内核,需要递归,空树高度为 -1,根节点高度为 0
    374     {
    375         if (x == null)
    376             return -1;
    377         return 1 + Math.max(heightKernel(x.left), heightKernel(x.right));
    378     }
    379 
    380     private boolean check()                     // 检查函数,用于 debug
    381     {
    382         if (!isBinarySearchST())
    383             StdOut.println("
    <check> Not in symmetric order.
    ");
    384         if (!isSizeConsistent())
    385             StdOut.println("
    <check> Subtree counts not consistent.
    ");
    386         if (!isRankConsistent())
    387             StdOut.println("
    <check> Ranks not consistent.
    ");
    388         return isclass01() && isSizeConsistent() && isRankConsistent();
    389     }
    390 
    391     private boolean isBinarySearchST()                     // 检查输的保序性
    392     {
    393         return isBinarySearchSTKernel(root, null, null);
    394     }
    395 
    396     private boolean isBinarySearchSTKernel(Node x, Key min, Key max)
    397     {
    398         if (x == null)
    399             return true;
    400         if (min != null && x.key.compareTo(min) <= 0)
    401             return false;
    402         if (max != null && x.key.compareTo(max) >= 0)
    403             return false;
    404         return isBinarySearchSTKernel(x.left, min, x.key) && isBinarySearchSTKernel(x.right, x.key, max);
    405     }
    406 
    407     private boolean isSizeConsistent()          // 检查树的 size 是否正确
    408     {
    409         return isSizeConsistentKernel(root);
    410     }
    411 
    412     private boolean isSizeConsistentKernel(Node x)
    413     {
    414         if (x == null)
    415             return true;
    416         if (x.size != size(x.left) + size(x.right) + 1)
    417             return false;
    418         return isSizeConsistentKernel(x.left) && isSizeConsistentKernel(x.right);
    419     }
    420 
    421     private boolean isRankConsistent()          // 检查 rank 和 select
    422     {
    423         for (int i = 0; i < size(); i++)        // 检查 rank 是否正确
    424         {
    425             if (i != rank(select(i)))
    426                 return false;
    427         }
    428         for (Key key : keys())                  // 检查 select 是否正确
    429         {
    430             if (key.compareTo(select(rank(key))) != 0)
    431                 return false;
    432         }
    433         return true;
    434     }
    435 
    436     public static void main(String[] args)
    437     {
    438         class01<String, Integer> st = new class01<String, Integer>();
    439         for (int i = 0; !StdIn.isEmpty(); i++)                  // 放进树中
    440         {
    441             String key = StdIn.readString();
    442             st.put(key, i);
    443         }
    444 
    445         for (String s : st.levelOrder())                        // 迭代器先根序遍历树
    446             StdOut.println(s + " " + st.get(s));
    447 
    448         StdOut.println();
    449         for (String s : st.keys())                              // 按键遍历树
    450             StdOut.println(s + " " + st.get(s));
    451     }
    452 }
  • 相关阅读:
    Python中__new__()方法的使用和实例化
    python __str__ , __repr__区别
    python中%r和%s的区别
    面向对象进阶
    getattr(sys.modules[__name__], func_name)
    os.path.dirname(__file__)使用
    bound和unbound方法,类的绑定和非绑定是什么
    基于python中staticmethod和classmethod的区别(详解)
    python基础----特性(property)、静态方法(staticmethod)、类方法(classmethod)、__str__的用法
    python @classmethod 的使用场合
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9784759.html
Copyright © 2020-2023  润新知