Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

438
LINES

< > BotCompany Repo | #1024412 // LogNArray v2 [based on TreeMap, dev.]

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (482L/4K).

1  
// see: https://en.wikipedia.org/wiki/Order_statistic_tree
2  
sclass LogNArray<A> extends RandomAccessAbstractList<A> {
3  
4  
  private transient Entry<A> root;
5  
6  
  /**
7  
   * The number of entries in the tree
8  
   */
9  
  //private transient int size = 0;
10  
11  
  /**
12  
   * The number of structural modifications to the tree.
13  
   */
14  
  private transient int modCount = 0;
15  
16  
  // Query Operations
17  
18  
  public int size() {
19  
    ret root == null ? 0 : root.size;
20  
  }
21  
22  
  public bool contains(Object value) {
23  
    for (Entry<A> e = getFirstEntry(); e != null; e = successor(e))
24  
      if (eq(value, e.value))
25  
        true;
26  
    false;
27  
  }
28  
29  
  public A get(int idx) {
30  
    Entry<A> p = getEntry(idx);
31  
    return p == null ? null : p.value;
32  
  }
33  
34  
  int subTreeSize(Entry<A> e) { ret e == null ? 0 : e.size; }
35  
36  
  final Entry<A> getEntry(int idx) {
37  
    if (idx < 0 || idx >= size())
38  
      throw new IndexOutOfBoundsException(idx + " / " + size());
39  
    Entry<A> p = root;
40  
    while true {
41  
      int sizeLeft = subTreeSize(p.left);
42  
      if (idx < sizeLeft)
43  
        continue with p = p.left;
44  
      idx -= sizeLeft;
45  
      if (idx == 0) ret p;
46  
      idx--;
47  
      p = p.right;
48  
    }
49  
  }
50  
51  
  /*public A put(Int key, A value) {
52  
      Entry<A> t = root;
53  
      if (t == null) {
54  
          compare(key, key); // type (and possibly null) check
55  
56  
          root = new Entry<>(key, value, null);
57  
          //size = 1;
58  
          modCount++;
59  
          return null;
60  
      }
61  
      int cmp;
62  
      Entry<A> parent;
63  
      // split comparator and comparable paths
64  
      Comparator<? super Int> cpr = comparator;
65  
      if (cpr != null) {
66  
          do {
67  
              parent = t;
68  
              cmp = cpr.compare(key, t.key);
69  
              if (cmp < 0)
70  
                  t = t.left;
71  
              else if (cmp > 0)
72  
                  t = t.right;
73  
              else
74  
                  return t.setValue(value);
75  
          } while (t != null);
76  
      }
77  
      else {
78  
          if (key == null)
79  
              throw new NullPointerException();
80  
          @SuppressWarnings("unchecked")
81  
              Comparable<? super Int> k = (Comparable<? super Int>) key;
82  
          do {
83  
              parent = t;
84  
              cmp = k.compareTo(t.key);
85  
              if (cmp < 0)
86  
                  t = t.left;
87  
              else if (cmp > 0)
88  
                  t = t.right;
89  
              else
90  
                  return t.setValue(value);
91  
          } while (t != null);
92  
      }
93  
      Entry<A> e = new Entry<>(key, value, parent);
94  
      if (cmp < 0)
95  
          parent.left = e;
96  
      else
97  
          parent.right = e;
98  
      fixAfterInsertion(e);
99  
      //size++;
100  
      modCount++;
101  
      return null;
102  
  }*/
103  
104  
  /*public A remove(int idx) {
105  
    Entry<A> p = getEntry(key);
106  
    if (p == null)
107  
        return null;
108  
109  
    A oldValue = p.value;
110  
    deleteEntry(p);
111  
    return oldValue;
112  
  }*/
113  
114  
  public void clear() {
115  
      modCount++;
116  
      //size = 0;
117  
      root = null;
118  
  }
119  
120  
  // Red-black mechanics
121  
122  
  private static final boolean RED   = false;
123  
  private static final boolean BLACK = true;
124  
125  
  /**
126  
   * Node in the Tree.  Doubles as a means to pass key-value pairs back to
127  
   * user (see Map.Entry).
128  
   */
129  
130  
  static final class Entry<A> {
131  
      int size = 1; // entry count of subtree
132  
      //Int key;
133  
      A value;
134  
      Entry<A> left;
135  
      Entry<A> right;
136  
      Entry<A> parent;
137  
      boolean color = BLACK;
138  
139  
      /**
140  
       * Make a new cell with given value and parent, and with
141  
       * {@code null} child links, size 1, and BLACK color.
142  
       */
143  
      Entry(A value, Entry<A> parent) {
144  
          this.value = value;
145  
          this.parent = parent;
146  
      }
147  
  }
148  
149  
  final Entry<A> getFirstEntry() {
150  
      Entry<A> p = root;
151  
      if (p != null)
152  
          while (p.left != null)
153  
              p = p.left;
154  
      return p;
155  
  }
156  
157  
  final Entry<A> getLastEntry() {
158  
      Entry<A> p = root;
159  
      if (p != null)
160  
          while (p.right != null)
161  
              p = p.right;
162  
      return p;
163  
  }
164  
165  
  static <Int,A> LogNArray.Entry<A> successor(Entry<A> t) {
166  
      if (t == null)
167  
          return null;
168  
      else if (t.right != null) {
169  
          Entry<A> p = t.right;
170  
          while (p.left != null)
171  
              p = p.left;
172  
          return p;
173  
      } else {
174  
          Entry<A> p = t.parent;
175  
          Entry<A> ch = t;
176  
          while (p != null && ch == p.right) {
177  
              ch = p;
178  
              p = p.parent;
179  
          }
180  
          return p;
181  
      }
182  
  }
183  
184  
  static <Int,A> Entry<A> predecessor(Entry<A> t) {
185  
      if (t == null)
186  
          return null;
187  
      else if (t.left != null) {
188  
          Entry<A> p = t.left;
189  
          while (p.right != null)
190  
              p = p.right;
191  
          return p;
192  
      } else {
193  
          Entry<A> p = t.parent;
194  
          Entry<A> ch = t;
195  
          while (p != null && ch == p.left) {
196  
              ch = p;
197  
              p = p.parent;
198  
          }
199  
          return p;
200  
      }
201  
  }
202  
203  
  /**
204  
   * Balancing operations.
205  
   *
206  
   * Implementations of rebalancings during insertion and deletion are
207  
   * slightly different than the CLR version.  Rather than using dummy
208  
   * nilnodes, we use a set of accessors that deal properly with null.  They
209  
   * are used to avoid messiness surrounding nullness checks in the main
210  
   * algorithms.
211  
   */
212  
213  
  private static <Int,A> boolean colorOf(Entry<A> p) {
214  
      return (p == null ? BLACK : p.color);
215  
  }
216  
217  
  private static <Int,A> Entry<A> parentOf(Entry<A> p) {
218  
      return (p == null ? null: p.parent);
219  
  }
220  
221  
  private static <Int,A> void setColor(Entry<A> p, boolean c) {
222  
      if (p != null)
223  
          p.color = c;
224  
  }
225  
226  
  private static <Int,A> Entry<A> leftOf(Entry<A> p) {
227  
      return (p == null) ? null: p.left;
228  
  }
229  
230  
  private static <Int,A> Entry<A> rightOf(Entry<A> p) {
231  
      return (p == null) ? null: p.right;
232  
  }
233  
234  
  /** From CLR */
235  
  private void rotateLeft(Entry<A> p) {
236  
      if (p != null) {
237  
          Entry<A> r = p.right;
238  
          p.right = r.left;
239  
          if (r.left != null)
240  
              r.left.parent = p;
241  
          r.parent = p.parent;
242  
          if (p.parent == null)
243  
              root = r;
244  
          else if (p.parent.left == p)
245  
              p.parent.left = r;
246  
          else
247  
              p.parent.right = r;
248  
          r.left = p;
249  
          p.parent = r;
250  
      }
251  
  }
252  
253  
  /** From CLR */
254  
  private void rotateRight(Entry<A> p) {
255  
      if (p != null) {
256  
          Entry<A> l = p.left;
257  
          p.left = l.right;
258  
          if (l.right != null) l.right.parent = p;
259  
          l.parent = p.parent;
260  
          if (p.parent == null)
261  
              root = l;
262  
          else if (p.parent.right == p)
263  
              p.parent.right = l;
264  
          else p.parent.left = l;
265  
          l.right = p;
266  
          p.parent = l;
267  
      }
268  
  }
269  
270  
  /** From CLR */
271  
  private void fixAfterInsertion(Entry<A> x) {
272  
      x.color = RED;
273  
274  
      while (x != null && x != root && x.parent.color == RED) {
275  
          if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
276  
              Entry<A> y = rightOf(parentOf(parentOf(x)));
277  
              if (colorOf(y) == RED) {
278  
                  setColor(parentOf(x), BLACK);
279  
                  setColor(y, BLACK);
280  
                  setColor(parentOf(parentOf(x)), RED);
281  
                  x = parentOf(parentOf(x));
282  
              } else {
283  
                  if (x == rightOf(parentOf(x))) {
284  
                      x = parentOf(x);
285  
                      rotateLeft(x);
286  
                  }
287  
                  setColor(parentOf(x), BLACK);
288  
                  setColor(parentOf(parentOf(x)), RED);
289  
                  rotateRight(parentOf(parentOf(x)));
290  
              }
291  
          } else {
292  
              Entry<A> y = leftOf(parentOf(parentOf(x)));
293  
              if (colorOf(y) == RED) {
294  
                  setColor(parentOf(x), BLACK);
295  
                  setColor(y, BLACK);
296  
                  setColor(parentOf(parentOf(x)), RED);
297  
                  x = parentOf(parentOf(x));
298  
              } else {
299  
                  if (x == leftOf(parentOf(x))) {
300  
                      x = parentOf(x);
301  
                      rotateRight(x);
302  
                  }
303  
                  setColor(parentOf(x), BLACK);
304  
                  setColor(parentOf(parentOf(x)), RED);
305  
                  rotateLeft(parentOf(parentOf(x)));
306  
              }
307  
          }
308  
      }
309  
      root.color = BLACK;
310  
  }
311  
312  
  /**
313  
   * Delete node p, and then rebalance the tree.
314  
   */
315  
  private void deleteEntry(Entry<A> p) {
316  
      modCount++;
317  
      //size--;
318  
319  
      // If strictly internal, copy successor's element to p and then make p
320  
      // point to successor.
321  
      if (p.left != null && p.right != null) {
322  
          Entry<A> s = successor(p);
323  
          p.value = s.value;
324  
          p = s;
325  
      } // p has 2 children
326  
327  
      // Start fixup at replacement node, if it exists.
328  
      Entry<A> replacement = (p.left != null ? p.left : p.right);
329  
330  
      if (replacement != null) {
331  
          // Link replacement to parent
332  
          replacement.parent = p.parent;
333  
          if (p.parent == null)
334  
              root = replacement;
335  
          else if (p == p.parent.left)
336  
              p.parent.left  = replacement;
337  
          else
338  
              p.parent.right = replacement;
339  
340  
          // Null out links so they are OK to use by fixAfterDeletion.
341  
          p.left = p.right = p.parent = null;
342  
343  
          // Fix replacement
344  
          if (p.color == BLACK)
345  
              fixAfterDeletion(replacement);
346  
      } else if (p.parent == null) { // return if we are the only node.
347  
          root = null;
348  
      } else { //  No children. Use self as phantom replacement and unlink.
349  
          if (p.color == BLACK)
350  
              fixAfterDeletion(p);
351  
352  
          if (p.parent != null) {
353  
              if (p == p.parent.left)
354  
                  p.parent.left = null;
355  
              else if (p == p.parent.right)
356  
                  p.parent.right = null;
357  
              p.parent = null;
358  
          }
359  
      }
360  
  }
361  
362  
  /** From CLR */
363  
  private void fixAfterDeletion(Entry<A> x) {
364  
      while (x != root && colorOf(x) == BLACK) {
365  
          if (x == leftOf(parentOf(x))) {
366  
              Entry<A> sib = rightOf(parentOf(x));
367  
368  
              if (colorOf(sib) == RED) {
369  
                  setColor(sib, BLACK);
370  
                  setColor(parentOf(x), RED);
371  
                  rotateLeft(parentOf(x));
372  
                  sib = rightOf(parentOf(x));
373  
              }
374  
375  
              if (colorOf(leftOf(sib))  == BLACK &&
376  
                  colorOf(rightOf(sib)) == BLACK) {
377  
                  setColor(sib, RED);
378  
                  x = parentOf(x);
379  
              } else {
380  
                  if (colorOf(rightOf(sib)) == BLACK) {
381  
                      setColor(leftOf(sib), BLACK);
382  
                      setColor(sib, RED);
383  
                      rotateRight(sib);
384  
                      sib = rightOf(parentOf(x));
385  
                  }
386  
                  setColor(sib, colorOf(parentOf(x)));
387  
                  setColor(parentOf(x), BLACK);
388  
                  setColor(rightOf(sib), BLACK);
389  
                  rotateLeft(parentOf(x));
390  
                  x = root;
391  
              }
392  
          } else { // symmetric
393  
              Entry<A> sib = leftOf(parentOf(x));
394  
395  
              if (colorOf(sib) == RED) {
396  
                  setColor(sib, BLACK);
397  
                  setColor(parentOf(x), RED);
398  
                  rotateRight(parentOf(x));
399  
                  sib = leftOf(parentOf(x));
400  
              }
401  
402  
              if (colorOf(rightOf(sib)) == BLACK &&
403  
                  colorOf(leftOf(sib)) == BLACK) {
404  
                  setColor(sib, RED);
405  
                  x = parentOf(x);
406  
              } else {
407  
                  if (colorOf(leftOf(sib)) == BLACK) {
408  
                      setColor(rightOf(sib), BLACK);
409  
                      setColor(sib, RED);
410  
                      rotateLeft(sib);
411  
                      sib = leftOf(parentOf(x));
412  
                  }
413  
                  setColor(sib, colorOf(parentOf(x)));
414  
                  setColor(parentOf(x), BLACK);
415  
                  setColor(leftOf(sib), BLACK);
416  
                  rotateRight(parentOf(x));
417  
                  x = root;
418  
              }
419  
          }
420  
      }
421  
422  
      setColor(x, BLACK);
423  
  }
424  
425  
  /**
426  
   * Finds the level down to which to assign all nodes BLACK.  This is the
427  
   * last `full' level of the complete binary tree produced by buildTree.
428  
   * The remaining nodes are colored RED. (This makes a `nice' set of
429  
   * color assignments wrt future insertions.) This level number is
430  
   * computed by finding the number of splits needed to reach the zeroeth
431  
   * node.
432  
   *
433  
   * @param size the (non-negative) number of keys in the tree to be built
434  
   */
435  
  private static int computeRedLevel(int size) {
436  
      return 31 - Integer.numberOfLeadingZeros(size + 1);
437  
  }
438  
}

Author comment

Began life as a copy of #1024411

download  show line numbers  debug dex  old transpilations   

Travelled to 6 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1024412
Snippet name: LogNArray v2 [based on TreeMap, dev.]
Eternal ID of this version: #1024412/12
Text MD5: e218fba96a516a2cc9c23442a664817e
Transpilation MD5: ba1ee5307ba902cc8076a7b714b727b9
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-08-11 11:38:26
Source code size: 12931 bytes / 438 lines
Pitched / IR pitched: No / No
Views / Downloads: 280 / 391
Version history: 11 change(s)
Referenced in: [show references]