Example #1
0
    boolean insert(Object x, int parentIndex) {
      if (isFull()) { // If full, you must split and promote splitNode before inserting
        Object splitNode = entries[nrElements / 2].element;
        BTreeNode rightSibling = split();

        if (isRoot()) { // Grow a level
          splitRoot(splitNode, this, rightSibling);
          // Determine where to insert
          if (BTreeSet.this.compare(x, BTreeSet.this.root.entries[0].element) < 0) insert(x, 0);
          else rightSibling.insert(x, 1);
        } else { // Promote splitNode
          parent.insertSplitNode(splitNode, this, rightSibling, parentIndex);
          if (BTreeSet.this.compare(x, parent.entries[parentIndex].element) < 0) {
            return insert(x, parentIndex);
          }
          return rightSibling.insert(x, parentIndex + 1);
        }
      } else if (isLeaf()) { // If leaf, simply insert the non-duplicate element
        int insertAt = childToInsertAt(x, true);
        // Determine if the element already exists
        if (insertAt == -1) {
          return false;
        }
        insertNewElement(x, insertAt);
        BTreeSet.this.size++;
        return true;
      } else { // If not full and not leaf recursively find correct node to insert at
        int insertAt = childToInsertAt(x, true);
        return (insertAt == -1 ? false : entries[insertAt].child.insert(x, insertAt));
      }
      return false;
    }
Example #2
0
 /*
  * Creates a new BTreeSet.root which contains only the splitNode and pointers
  * to it's left and right child.
  */
 private void splitRoot(Object splitNode, BTreeNode left, BTreeNode right) {
   BTreeNode newRoot = new BTreeNode(null);
   newRoot.entries[0].element = splitNode;
   newRoot.entries[0].child = left;
   newRoot.entries[1] = new Entry();
   newRoot.entries[1].child = right;
   newRoot.nrElements = 1;
   left.parent = right.parent = newRoot;
   BTreeSet.this.root = newRoot;
 }
Example #3
0
    boolean delete(Object x, int parentIndex) {
      int i = childToInsertAt(x, true);
      int priorParentIndex = parentIndex;
      BTreeNode temp = this;
      if (i != -1) {
        do {
          if (temp.entries[i] == null || temp.entries[i].child == null) return false;
          temp = temp.entries[i].child;
          priorParentIndex = parentIndex;
          parentIndex = i;
          i = temp.childToInsertAt(x, true);
        } while (i != -1);
      } // Now temp contains element to delete and temp's parentIndex is parentIndex

      if (temp.isLeaf()) { // If leaf and have more than MIN elements, simply delete
        if (temp.nrElements > MIN) {
          temp.deleteElement(x);
          BTreeSet.this.size--;
          return true;
        }

        // else - If leaf and have less than MIN elements, than prepare the BTreeSet for deletion
        temp.prepareForDeletion(parentIndex);
        temp.deleteElement(x);
        BTreeSet.this.size--;
        temp.fixAfterDeletion(priorParentIndex);
        return true;
      }

      // else - Only delete at leaf so first switch with successor than delete
      temp.switchWithSuccessor(x);
      parentIndex = temp.childToInsertAt(x, false) + 1;
      return temp.entries[parentIndex].child.delete(x, parentIndex);
    }
Example #4
0
    private void fixAfterDeletion(int parentIndex) {
      if (isRoot() || parent.isRoot()) return; // No fixing needed

      if (parent.nrElements < MIN) { // If parent lost it's n/2 element repair it
        BTreeNode temp = parent;
        temp.prepareForDeletion(parentIndex);
        if (temp.parent == null) return; // Root changed
        if (!temp.parent.isRoot() && temp.parent.nrElements < MIN) { // If need be recurse
          BTreeNode x = temp.parent.parent;
          int i = 0;
          // Find parent's parentIndex
          for (; i < entries.length; i++) if (x.entries[i].child == temp.parent) break;
          temp.parent.fixAfterDeletion(i);
        }
      }
    }
Example #5
0
    private Object nextElement() {
      if (currentNode.isLeaf()) {
        if (index < currentNode.nrElements) return currentNode.entries[index++].element;
        else if (!parentIndex
            .empty()) { // All elements have been returned, return successor of lastReturned if it
          // exists
          currentNode = currentNode.parent;
          index = ((Integer) parentIndex.pop()).intValue();

          while (index == currentNode.nrElements) {
            if (parentIndex.empty()) break;
            currentNode = currentNode.parent;
            index = ((Integer) parentIndex.pop()).intValue();
          }

          if (index == currentNode.nrElements)
            return null; // Reached root and he has no more children
          return currentNode.entries[index++].element;
        } else { // Your a leaf and the root
          if (index == currentNode.nrElements) return null;
          return currentNode.entries[index++].element;
        }
      }

      // else - You're not a leaf so simply find and return the successor of lastReturned
      currentNode = currentNode.entries[index].child;
      parentIndex.push(Integer.valueOf(index));

      while (currentNode.entries[0].child != null) {
        currentNode = currentNode.entries[0].child;
        parentIndex.push(Integer.valueOf(0));
      }

      index = 1;
      return currentNode.entries[0].element;
    }
Example #6
0
 public boolean remove(Object x) {
   if (x == null) return false;
   return root.delete(x, -1);
 }
Example #7
0
 public boolean contains(Object x) {
   return root.includes(x);
 }
Example #8
0
 /*
  * Public Methods
  */
 public boolean add(Object x) throws IllegalArgumentException {
   if (x == null) throw new IllegalArgumentException();
   return root.insert(x, -1);
 }
Example #9
0
    /*
     * This method is called only when stealLeft, stealRight, and mergeLeft could not be called,
     * the BTreeNode has the minimum number of elements, has a rightSibling, and the
     * rightSibling has more than the minimum number of elements.  If after completion
     * parent has fewer than the minimum number of elements than the parents entries[0]
     * slot is left empty in anticipation of a recursive call to stealLeft, stealRight,
     * mergeLeft, or mergeRight to fix the parent. All of the before-mentioned methods
     * expect the parent to be in such a condition.
     */
    private void mergeRight(int parentIndex) {
      BTreeNode p = parent;
      BTreeNode rs = p.entries[parentIndex + 1].child;

      if (isLeaf()) { // Don't worry about children
        entries[nrElements] = new Entry();
        entries[nrElements].element = p.entries[parentIndex].element;
        nrElements++;
        for (int i = 0, nr = nrElements; i < rs.nrElements; i++, nr++) {
          entries[nr] = rs.entries[i];
          nrElements++;
        }
        p.entries[parentIndex].element = p.entries[parentIndex + 1].element;
        if (p.nrElements == MIN && p != BTreeSet.this.root) {
          for (int x = parentIndex + 1, y = parentIndex; y >= 0; x--, y--)
            p.entries[x] = p.entries[y];
          p.entries[0] = new Entry();
          p.entries[0].child =
              rs; // So it doesn't think it's a leaf, this child will be deleted in the next
          // recursive call
        } else {
          for (int x = parentIndex + 1, y = parentIndex + 2; y <= p.nrElements; x++, y++)
            p.entries[x] = p.entries[y];
          p.entries[p.nrElements] = null;
        }

        p.nrElements--;
        if (p.isRoot() && p.nrElements == 0) { // It's the root and it's empty
          BTreeSet.this.root = this;
          parent = null;
        }
      } else { // It's not a leaf

        entries[nrElements].element = p.entries[parentIndex].element;
        nrElements++;

        for (int x = nrElements + 1, y = 0; y <= rs.nrElements; x++, y++) {
          entries[x] = rs.entries[y];
          rs.entries[y].child.parent = this;
          nrElements++;
        }
        nrElements--;

        p.entries[++parentIndex].child = this;

        if (p.nrElements == MIN && p != BTreeSet.this.root) {
          for (int x = parentIndex - 1, y = parentIndex - 2; y >= 0; x--, y--)
            p.entries[x] = p.entries[y];
          p.entries[0] = new Entry();
        } else {
          for (int x = parentIndex - 1, y = parentIndex; y <= p.nrElements; x++, y++)
            p.entries[x] = p.entries[y];
          p.entries[p.nrElements] = null;
        }

        p.nrElements--;

        if (p.isRoot() && p.nrElements == 0) { // It's the root and it's empty
          BTreeSet.this.root = this;
          parent = null;
        }
      }
    }
Example #10
0
    /*
     * This method is called only when stealLeft and stealRight could not be called,
     * the BTreeNode has the minimum number of elements, has a leftSibling, and the
     * leftSibling has more than the minimum number of elements.  If after completion
     * parent has fewer than the minimum number of elements than the parents entries[0]
     * slot is left empty in anticipation of a recursive call to stealLeft, stealRight,
     * mergeLeft, or mergeRight to fix the parent. All of the before-mentioned methods
     * expect the parent to be in such a condition.
     */
    private void mergeLeft(int parentIndex) {
      BTreeNode p = parent;
      BTreeNode ls = p.entries[parentIndex - 1].child;

      if (isLeaf()) { // Don't worry about children
        int add = childToInsertAt(p.entries[parentIndex - 1].element, true);
        insertNewElement(
            p.entries[parentIndex - 1].element, add); // Could have been a successor switch
        p.entries[parentIndex - 1].element = null;

        for (int i = nrElements - 1, nr = ls.nrElements; i >= 0; i--) entries[i + nr] = entries[i];

        for (int i = ls.nrElements - 1; i >= 0; i--) {
          entries[i] = ls.entries[i];
          nrElements++;
        }

        if (p.nrElements == MIN && p != BTreeSet.this.root) {

          for (int x = parentIndex - 1, y = parentIndex - 2; y >= 0; x--, y--)
            p.entries[x] = p.entries[y];
          p.entries[0] = new Entry();
          p.entries[0].child =
              ls; // So p doesn't think it's a leaf this will be deleted in the next recursive call
        } else {

          for (int x = parentIndex - 1, y = parentIndex; y <= p.nrElements; x++, y++)
            p.entries[x] = p.entries[y];
          p.entries[p.nrElements] = null;
        }

        p.nrElements--;

        if (p.isRoot() && p.nrElements == 0) { // It's the root and it's empty
          BTreeSet.this.root = this;
          parent = null;
        }
      } else { // I'm not a leaf but fixing the tree structure
        entries[0].element = p.entries[parentIndex - 1].element;
        entries[0].child = ls.entries[ls.nrElements].child;
        nrElements++;

        for (int x = nrElements, nr = ls.nrElements; x >= 0; x--) entries[x + nr] = entries[x];

        for (int x = ls.nrElements - 1; x >= 0; x--) {
          entries[x] = ls.entries[x];
          entries[x].child.parent = this;
          nrElements++;
        }

        if (p.nrElements == MIN && p != BTreeSet.this.root) { // Push everything to the right
          for (int x = parentIndex - 1, y = parentIndex - 2; y >= 0; x++, y++) {
            System.out.println(x + " " + y);
            p.entries[x] = p.entries[y];
          }
          p.entries[0] = new Entry();
        } else { // Either p.nrElements > MIN or p == BTreeSet.this.root so push everything to the
          // left
          for (int x = parentIndex - 1, y = parentIndex; y <= p.nrElements; x++, y++)
            p.entries[x] = p.entries[y];
          p.entries[p.nrElements] = null;
        }

        p.nrElements--;

        if (p.isRoot() && p.nrElements == 0) { // p == BTreeSet.this.root and it's empty
          BTreeSet.this.root = this;
          parent = null;
        }
      }
    }