/**
  * Reads the given number of entries from the input stream, returning the corresponding tree.
  *
  * @param s the input stream.
  * @param n the (positive) number of entries to read.
  * @param pred the entry containing the key that preceeds the first key in the tree.
  * @param succ the entry containing the key that follows the last key in the tree.
  */
 @SuppressWarnings("unchecked")
 private Entry<K> readTree(
     final java.io.ObjectInputStream s, final int n, final Entry<K> pred, final Entry<K> succ)
     throws java.io.IOException, ClassNotFoundException {
   if (n == 1) {
     final Entry<K> top = new Entry<K>((K) s.readObject());
     top.pred(pred);
     top.succ(succ);
     top.black(true);
     return top;
   }
   if (n == 2) {
     /* We handle separately this case so that recursion will
      *always* be on nonempty subtrees. */
     final Entry<K> top = new Entry<K>((K) s.readObject());
     top.black(true);
     top.right(new Entry<K>((K) s.readObject()));
     top.right.pred(top);
     top.pred(pred);
     top.right.succ(succ);
     return top;
   }
   // The right subtree is the largest one.
   final int rightN = n / 2, leftN = n - rightN - 1;
   final Entry<K> top = new Entry<K>();
   top.left(readTree(s, leftN, pred, top));
   top.key = (K) s.readObject();
   top.black(true);
   top.right(readTree(s, rightN, top, succ));
   if (n + 2 == ((n + 2) & -(n + 2)))
     top.right.black(false); // Quick test for determining whether n + 2 is a power of 2.
   return top;
 }
  /**
   * Finds the parent of an entry.
   *
   * @param e a node of the tree.
   * @return the parent of the given node, or <code>null</code> for the root.
   */
  private Entry parent(final Entry e) {
    if (e == tree) return null;

    Entry x, y, p;
    x = y = e;

    while (true) {
      if (y.succ()) {
        p = y.right;
        if (p == null || p.left != e) {
          while (!x.pred()) x = x.left;
          p = x.left;
        }
        return p;
      } else if (x.pred()) {
        p = x.left;
        if (p == null || p.right != e) {
          while (!y.succ()) y = y.right;
          p = y.right;
        }
        return p;
      }

      x = x.left;
      y = y.right;
    }
  }
 /**
  * Returns a deep copy of this tree set.
  *
  * <p>This method performs a deep copy of this tree set; the data stored in the set, however, is
  * not cloned. Note that this makes a difference only for object keys.
  *
  * @return a deep copy of this tree set.
  */
 @SuppressWarnings("unchecked")
 public Object clone() {
   ObjectRBTreeSet<K> c;
   try {
     c = (ObjectRBTreeSet<K>) super.clone();
   } catch (CloneNotSupportedException cantHappen) {
     throw new InternalError();
   }
   c.allocatePaths();
   if (count != 0) {
     // Also this apparently unfathomable code is derived from GNU libavl.
     Entry<K> e, p, q, rp = new Entry<K>(), rq = new Entry<K>();
     p = rp;
     rp.left(tree);
     q = rq;
     rq.pred(null);
     while (true) {
       if (!p.pred()) {
         e = p.left.clone();
         e.pred(q.left);
         e.succ(q);
         q.left(e);
         p = p.left;
         q = q.left;
       } else {
         while (p.succ()) {
           p = p.right;
           if (p == null) {
             q.right = null;
             c.tree = rq.left;
             c.firstEntry = c.tree;
             while (c.firstEntry.left != null) c.firstEntry = c.firstEntry.left;
             c.lastEntry = c.tree;
             while (c.lastEntry.right != null) c.lastEntry = c.lastEntry.right;
             return c;
           }
           q = q.right;
         }
         p = p.right;
         q = q.right;
       }
       if (!p.succ()) {
         e = p.right.clone();
         e.succ(q.right);
         e.pred(q);
         q.right(e);
       }
     }
   }
   return c;
 }
  @SuppressWarnings("unchecked")
  public boolean remove(final Object k) {
    if (tree == null) return false;

    Entry<K> p = tree;
    int cmp;
    int i = 0;
    final K kk = (K) k;

    while (true) {
      if ((cmp = compare(kk, p.key)) == 0) break;

      dirPath[i] = cmp > 0;
      nodePath[i] = p;

      if (dirPath[i++]) {
        if ((p = p.right()) == null) {
          // We clean up the node path, or we could have stale references later.
          while (i-- != 0) nodePath[i] = null;
          return false;
        }
      } else {
        if ((p = p.left()) == null) {
          // We clean up the node path, or we could have stale references later.
          while (i-- != 0) nodePath[i] = null;
          return false;
        }
      }
    }

    if (p.left == null) firstEntry = p.next();
    if (p.right == null) lastEntry = p.prev();

    if (p.succ()) {
      if (p.pred()) {
        if (i == 0) tree = p.left;
        else {
          if (dirPath[i - 1]) nodePath[i - 1].succ(p.right);
          else nodePath[i - 1].pred(p.left);
        }
      } else {
        p.prev().right = p.right;

        if (i == 0) tree = p.left;
        else {
          if (dirPath[i - 1]) nodePath[i - 1].right = p.left;
          else nodePath[i - 1].left = p.left;
        }
      }
    } else {
      boolean color;
      Entry<K> r = p.right;

      if (r.pred()) {
        r.left = p.left;
        r.pred(p.pred());
        if (!r.pred()) r.prev().right = r;
        if (i == 0) tree = r;
        else {
          if (dirPath[i - 1]) nodePath[i - 1].right = r;
          else nodePath[i - 1].left = r;
        }

        color = r.black();
        r.black(p.black());
        p.black(color);
        dirPath[i] = true;
        nodePath[i++] = r;
      } else {
        Entry<K> s;
        int j = i++;

        while (true) {
          dirPath[i] = false;
          nodePath[i++] = r;
          s = r.left;
          if (s.pred()) break;
          r = s;
        }

        dirPath[j] = true;
        nodePath[j] = s;

        if (s.succ()) r.pred(s);
        else r.left = s.right;

        s.left = p.left;

        if (!p.pred()) {
          p.prev().right = s;
          s.pred(false);
        }

        s.right(p.right);

        color = s.black();
        s.black(p.black());
        p.black(color);

        if (j == 0) tree = s;
        else {
          if (dirPath[j - 1]) nodePath[j - 1].right = s;
          else nodePath[j - 1].left = s;
        }
      }
    }

    int maxDepth = i;

    if (p.black()) {
      for (; i > 0; i--) {
        if (dirPath[i - 1] && !nodePath[i - 1].succ()
            || !dirPath[i - 1] && !nodePath[i - 1].pred()) {
          Entry<K> x = dirPath[i - 1] ? nodePath[i - 1].right : nodePath[i - 1].left;

          if (!x.black()) {
            x.black(true);
            break;
          }
        }

        if (!dirPath[i - 1]) {
          Entry<K> w = nodePath[i - 1].right;

          if (!w.black()) {
            w.black(true);
            nodePath[i - 1].black(false);

            nodePath[i - 1].right = w.left;
            w.left = nodePath[i - 1];

            if (i < 2) tree = w;
            else {
              if (dirPath[i - 2]) nodePath[i - 2].right = w;
              else nodePath[i - 2].left = w;
            }

            nodePath[i] = nodePath[i - 1];
            dirPath[i] = false;
            nodePath[i - 1] = w;
            if (maxDepth == i++) maxDepth++;

            w = nodePath[i - 1].right;
          }

          if ((w.pred() || w.left.black()) && (w.succ() || w.right.black())) {
            w.black(false);
          } else {
            if (w.succ() || w.right.black()) {
              Entry<K> y = w.left;

              y.black(true);
              w.black(false);
              w.left = y.right;
              y.right = w;
              w = nodePath[i - 1].right = y;

              if (w.succ()) {
                w.succ(false);
                w.right.pred(w);
              }
            }

            w.black(nodePath[i - 1].black());
            nodePath[i - 1].black(true);
            w.right.black(true);

            nodePath[i - 1].right = w.left;
            w.left = nodePath[i - 1];

            if (i < 2) tree = w;
            else {
              if (dirPath[i - 2]) nodePath[i - 2].right = w;
              else nodePath[i - 2].left = w;
            }

            if (w.pred()) {
              w.pred(false);
              nodePath[i - 1].succ(w);
            }
            break;
          }
        } else {
          Entry<K> w = nodePath[i - 1].left;

          if (!w.black()) {
            w.black(true);
            nodePath[i - 1].black(false);

            nodePath[i - 1].left = w.right;
            w.right = nodePath[i - 1];

            if (i < 2) tree = w;
            else {
              if (dirPath[i - 2]) nodePath[i - 2].right = w;
              else nodePath[i - 2].left = w;
            }

            nodePath[i] = nodePath[i - 1];
            dirPath[i] = true;
            nodePath[i - 1] = w;
            if (maxDepth == i++) maxDepth++;

            w = nodePath[i - 1].left;
          }

          if ((w.pred() || w.left.black()) && (w.succ() || w.right.black())) {
            w.black(false);
          } else {
            if (w.pred() || w.left.black()) {
              Entry<K> y = w.right;

              y.black(true);
              w.black(false);
              w.right = y.left;
              y.left = w;
              w = nodePath[i - 1].left = y;

              if (w.pred()) {
                w.pred(false);
                w.left.succ(w);
              }
            }

            w.black(nodePath[i - 1].black());
            nodePath[i - 1].black(true);
            w.left.black(true);

            nodePath[i - 1].left = w.right;
            w.right = nodePath[i - 1];

            if (i < 2) tree = w;
            else {
              if (dirPath[i - 2]) nodePath[i - 2].right = w;
              else nodePath[i - 2].left = w;
            }

            if (w.succ()) {
              w.succ(false);
              nodePath[i - 1].pred(w);
            }
            break;
          }
        }
      }

      if (tree != null) tree.black(true);
    }

    count--;
    // We clean up the node path, or we could have stale references later.
    while (maxDepth-- != 0) nodePath[maxDepth] = null;
    if (ASSERTS) {
      checkNodePath();
      checkTree(tree, 0, -1);
    }
    return true;
  }
  public boolean add(final K k) {
    int maxDepth = 0;

    if (tree == null) { // The case of the empty tree is treated separately.
      count++;
      tree = lastEntry = firstEntry = new Entry<K>(k);
    } else {
      Entry<K> p = tree, e;
      int cmp, i = 0;

      while (true) {
        if ((cmp = compare(k, p.key)) == 0) {
          // We clean up the node path, or we could have stale references later.
          while (i-- != 0) nodePath[i] = null;
          return false;
        }

        nodePath[i] = p;

        if (dirPath[i++] = cmp > 0) {
          if (p.succ()) {
            count++;
            e = new Entry<K>(k);

            if (p.right == null) lastEntry = e;

            e.left = p;
            e.right = p.right;

            p.right(e);

            break;
          }

          p = p.right;
        } else {
          if (p.pred()) {
            count++;
            e = new Entry<K>(k);

            if (p.left == null) firstEntry = e;

            e.right = p;
            e.left = p.left;

            p.left(e);

            break;
          }

          p = p.left;
        }
      }

      maxDepth = i--;

      while (i > 0 && !nodePath[i].black()) {
        if (!dirPath[i - 1]) {
          Entry<K> y = nodePath[i - 1].right;

          if (!nodePath[i - 1].succ() && !y.black()) {
            nodePath[i].black(true);
            y.black(true);
            nodePath[i - 1].black(false);
            i -= 2;
          } else {
            Entry<K> x;

            if (!dirPath[i]) y = nodePath[i];
            else {
              x = nodePath[i];
              y = x.right;
              x.right = y.left;
              y.left = x;
              nodePath[i - 1].left = y;

              if (y.pred()) {
                y.pred(false);
                x.succ(y);
              }
            }

            x = nodePath[i - 1];
            x.black(false);
            y.black(true);

            x.left = y.right;
            y.right = x;
            if (i < 2) tree = y;
            else {
              if (dirPath[i - 2]) nodePath[i - 2].right = y;
              else nodePath[i - 2].left = y;
            }

            if (y.succ()) {
              y.succ(false);
              x.pred(y);
            }
            break;
          }
        } else {
          Entry<K> y = nodePath[i - 1].left;

          if (!nodePath[i - 1].pred() && !y.black()) {
            nodePath[i].black(true);
            y.black(true);
            nodePath[i - 1].black(false);
            i -= 2;
          } else {
            Entry<K> x;

            if (dirPath[i]) y = nodePath[i];
            else {
              x = nodePath[i];
              y = x.left;
              x.left = y.right;
              y.right = x;
              nodePath[i - 1].right = y;

              if (y.succ()) {
                y.succ(false);
                x.pred(y);
              }
            }

            x = nodePath[i - 1];
            x.black(false);
            y.black(true);

            x.right = y.left;
            y.left = x;
            if (i < 2) tree = y;
            else {
              if (dirPath[i - 2]) nodePath[i - 2].right = y;
              else nodePath[i - 2].left = y;
            }

            if (y.pred()) {
              y.pred(false);
              x.succ(y);
            }

            break;
          }
        }
      }
    }
    tree.black(true);
    // We clean up the node path, or we could have stale references later.
    while (maxDepth-- != 0) nodePath[maxDepth] = null;
    if (ASSERTS) {
      checkNodePath();
      checkTree(tree, 0, -1);
    }
    return true;
  }
  @SuppressWarnings("unchecked")
  public boolean remove(final long k) {
    if (tree == null) return false;

    int cmp;
    Entry p = tree, q = null;
    boolean dir = false;
    final long kk = k;

    while (true) {
      if ((cmp = compare(kk, p.key)) == 0) break;
      else if (dir = cmp > 0) {
        q = p;
        if ((p = p.right()) == null) return false;
      } else {
        q = p;
        if ((p = p.left()) == null) return false;
      }
    }

    if (p.left == null) firstEntry = p.next();
    if (p.right == null) lastEntry = p.prev();

    if (p.succ()) {
      if (p.pred()) {
        if (q != null) {
          if (dir) q.succ(p.right);
          else q.pred(p.left);
        } else tree = dir ? p.right : p.left;
      } else {
        p.prev().right = p.right;

        if (q != null) {
          if (dir) q.right = p.left;
          else q.left = p.left;
        } else tree = p.left;
      }
    } else {
      Entry r = p.right;

      if (r.pred()) {
        r.left = p.left;
        r.pred(p.pred());
        if (!r.pred()) r.prev().right = r;
        if (q != null) {
          if (dir) q.right = r;
          else q.left = r;
        } else tree = r;

        r.balance(p.balance());
        q = r;
        dir = true;

      } else {
        Entry s;

        while (true) {
          s = r.left;
          if (s.pred()) break;
          r = s;
        }

        if (s.succ()) r.pred(s);
        else r.left = s.right;

        s.left = p.left;

        if (!p.pred()) {
          p.prev().right = s;
          s.pred(false);
        }

        s.right = p.right;
        s.succ(false);

        if (q != null) {
          if (dir) q.right = s;
          else q.left = s;
        } else tree = s;

        s.balance(p.balance());
        q = r;
        dir = false;
      }
    }

    Entry y;

    while (q != null) {
      y = q;
      q = parent(y);

      if (!dir) {
        dir = q != null && q.left != y;
        y.incBalance();

        if (y.balance() == 1) break;
        else if (y.balance() == 2) {

          Entry x = y.right;
          if (ASSERTS) assert x != null;

          if (x.balance() == -1) {
            Entry w;

            if (ASSERTS) assert x.balance() == -1;

            w = x.left;
            x.left = w.right;
            w.right = x;
            y.right = w.left;
            w.left = y;

            if (w.balance() == 1) {
              x.balance(0);
              y.balance(-1);
            } else if (w.balance() == 0) {
              x.balance(0);
              y.balance(0);
            } else {
              if (ASSERTS) assert w.balance() == -1;

              x.balance(1);
              y.balance(0);
            }

            w.balance(0);

            if (w.pred()) {
              y.succ(w);
              w.pred(false);
            }
            if (w.succ()) {
              x.pred(w);
              w.succ(false);
            }

            if (q != null) {
              if (dir) q.right = w;
              else q.left = w;
            } else tree = w;
          } else {
            if (q != null) {
              if (dir) q.right = x;
              else q.left = x;
            } else tree = x;

            if (x.balance() == 0) {
              y.right = x.left;
              x.left = y;
              x.balance(-1);
              y.balance(+1);
              break;
            }

            if (ASSERTS) assert x.balance() == 1;

            if (x.pred()) {
              y.succ(true);
              x.pred(false);
            } else y.right = x.left;

            x.left = y;
            y.balance(0);
            x.balance(0);
          }
        }
      } else {
        dir = q != null && q.left != y;
        y.decBalance();

        if (y.balance() == -1) break;
        else if (y.balance() == -2) {

          Entry x = y.left;
          if (ASSERTS) assert x != null;

          if (x.balance() == 1) {
            Entry w;

            if (ASSERTS) assert x.balance() == 1;

            w = x.right;
            x.right = w.left;
            w.left = x;
            y.left = w.right;
            w.right = y;

            if (w.balance() == -1) {
              x.balance(0);
              y.balance(1);
            } else if (w.balance() == 0) {
              x.balance(0);
              y.balance(0);
            } else {
              if (ASSERTS) assert w.balance() == 1;

              x.balance(-1);
              y.balance(0);
            }

            w.balance(0);

            if (w.pred()) {
              x.succ(w);
              w.pred(false);
            }
            if (w.succ()) {
              y.pred(w);
              w.succ(false);
            }

            if (q != null) {
              if (dir) q.right = w;
              else q.left = w;
            } else tree = w;
          } else {
            if (q != null) {
              if (dir) q.right = x;
              else q.left = x;
            } else tree = x;

            if (x.balance() == 0) {
              y.left = x.right;
              x.right = y;
              x.balance(+1);
              y.balance(-1);
              break;
            }

            if (ASSERTS) assert x.balance() == -1;

            if (x.succ()) {
              y.pred(true);
              x.succ(false);
            } else y.left = x.right;

            x.right = y;
            y.balance(0);
            x.balance(0);
          }
        }
      }
    }

    count--;
    if (ASSERTS) checkTree(tree);
    return true;
  }
  public boolean add(final long k) {

    if (tree == null) { // The case of the empty tree is treated separately.
      count++;
      tree = lastEntry = firstEntry = new Entry(k);
    } else {
      Entry p = tree, q = null, y = tree, z = null, e = null, w = null;
      int cmp, i = 0;

      while (true) {
        if ((cmp = compare(k, p.key)) == 0) return false;

        if (p.balance() != 0) {
          i = 0;
          z = q;
          y = p;
        }

        if (dirPath[i++] = cmp > 0) {
          if (p.succ()) {
            count++;
            e = new Entry(k);

            if (p.right == null) lastEntry = e;

            e.left = p;
            e.right = p.right;

            p.right(e);

            break;
          }

          q = p;
          p = p.right;
        } else {
          if (p.pred()) {
            count++;
            e = new Entry(k);

            if (p.left == null) firstEntry = e;

            e.right = p;
            e.left = p.left;

            p.left(e);

            break;
          }

          q = p;
          p = p.left;
        }
      }

      p = y;
      i = 0;

      while (p != e) {
        if (dirPath[i]) p.incBalance();
        else p.decBalance();

        p = dirPath[i++] ? p.right : p.left;
      }

      if (y.balance() == -2) {
        Entry x = y.left;

        if (x.balance() == -1) {
          w = x;
          if (x.succ()) {
            x.succ(false);
            y.pred(x);
          } else y.left = x.right;

          x.right = y;
          x.balance(0);
          y.balance(0);
        } else {
          if (ASSERTS) assert x.balance() == 1;

          w = x.right;
          x.right = w.left;
          w.left = x;
          y.left = w.right;
          w.right = y;
          if (w.balance() == -1) {
            x.balance(0);
            y.balance(1);
          } else if (w.balance() == 0) {
            x.balance(0);
            y.balance(0);
          } else {
            x.balance(-1);
            y.balance(0);
          }
          w.balance(0);

          if (w.pred()) {
            x.succ(w);
            w.pred(false);
          }
          if (w.succ()) {
            y.pred(w);
            w.succ(false);
          }
        }
      } else if (y.balance() == +2) {
        Entry x = y.right;

        if (x.balance() == 1) {
          w = x;
          if (x.pred()) {
            x.pred(false);
            y.succ(x);
          } else y.right = x.left;

          x.left = y;
          x.balance(0);
          y.balance(0);
        } else {
          if (ASSERTS) assert x.balance() == -1;

          w = x.left;
          x.left = w.right;
          w.right = x;
          y.right = w.left;
          w.left = y;
          if (w.balance() == 1) {
            x.balance(0);
            y.balance(-1);
          } else if (w.balance() == 0) {
            x.balance(0);
            y.balance(0);
          } else {
            x.balance(1);
            y.balance(0);
          }
          w.balance(0);

          if (w.pred()) {
            y.succ(w);
            w.pred(false);
          }
          if (w.succ()) {
            x.pred(w);
            w.succ(false);
          }
        }
      } else return true;

      if (z == null) tree = w;
      else {
        if (z.left == y) z.left = w;
        else z.right = w;
      }
    }

    if (ASSERTS) checkTree(tree);
    return true;
  }