《算法》第三章部分程序 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 }
原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9784759.html