📄 btreeset.java
字号:
rightSibling.entries[i].child.parent = rightSibling; entries[index] = null; nrElements--; rightSibling.nrElements++; } rightSibling.nrElements--; // Need to correct for copying the last Entry which has a null element and a child return rightSibling; } /* * 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; } private void insertSplitNode(Object splitNode, BTreeNode left, BTreeNode right, int insertAt) { for (int i = nrElements; i >= insertAt; i--) entries[i + 1] = entries[i]; entries[insertAt] = new Entry(); entries[insertAt].element = splitNode; entries[insertAt].child = left; entries[insertAt + 1].child = right; nrElements++; } private void insertNewElement(Object x, int insertAt) { for (int i = nrElements; i > insertAt; i--) entries[i] = entries[i - 1]; entries[insertAt] = new Entry(); entries[insertAt].element = x; nrElements++; } /* * Possibly a deceptive name for a pretty cool method. Uses binary search * to determine the postion in entries[] in which to traverse to find the correct * BTreeNode in which to insert a new element. If the element exists in the calling * BTreeNode than -1 is returned. When the parameter position is true and the element * is present in the calling BTreeNode -1 is returned, if position is false and the * element is contained in the calling BTreeNode than the position of the element * in entries[] is returned. */ private int childToInsertAt(Object x, boolean position) { int index = nrElements / 2; if (entries[index] == null || entries[index].element == null) return index; int lo = 0, hi = nrElements - 1; while (lo <= hi) { if (BTreeSet.this.compare(x, entries[index].element) > 0) { lo = index + 1; index = (hi + lo) / 2; } else { hi = index - 1; index = (hi + lo) / 2; } } hi++; if (entries[hi] == null || entries[hi].element == null) return hi; return (!position ? hi : BTreeSet.this.compare(x, entries[hi].element) == 0 ? -1 : hi); } private void deleteElement(Object x) { int index = childToInsertAt(x, false); for (; index < (nrElements - 1); index++) entries[index] = entries[index + 1]; if (nrElements == 1) entries[index] = new Entry(); // This is root and it is empty else entries[index] = null; nrElements--; } private void prepareForDeletion(int parentIndex) { if (isRoot()) return; // Don't attempt to steal or merge if your the root // If not root then try to steal left else if (parentIndex != 0 && parent.entries[parentIndex - 1].child.nrElements > MIN) { stealLeft(parentIndex); return; } // If not root and can't steal left try to steal right else if (parentIndex < entries.length && parent.entries[parentIndex + 1] != null && parent.entries[parentIndex + 1].child != null && parent.entries[parentIndex + 1].child.nrElements > MIN) { stealRight(parentIndex); return; } // If not root and can't steal left or right then try to merge left else if (parentIndex != 0) { mergeLeft(parentIndex); return; } // If not root and can't steal left or right and can't merge left you must be able to merge right else mergeRight(parentIndex); } 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); } } } private void switchWithSuccessor(Object x) { int index = childToInsertAt(x, false); BTreeNode temp = entries[index + 1].child; while (temp.entries[0] != null && temp.entries[0].child != null) temp = temp.entries[0].child; Object successor = temp.entries[0].element; temp.entries[0].element = entries[index].element; entries[index].element = successor; } /* * This method is called only when the BTreeNode has the minimum number of elements, * has a leftSibling, and the leftSibling has more than the minimum number of elements. */ private void stealLeft(int parentIndex) { BTreeNode p = parent; BTreeNode ls = parent.entries[parentIndex - 1].child; if (isLeaf()) { // When stealing from leaf to leaf don't worry about children int add = childToInsertAt(p.entries[parentIndex - 1].element, true); insertNewElement(p.entries[parentIndex - 1].element, add); p.entries[parentIndex - 1].element = ls.entries[ls.nrElements - 1].element; ls.entries[ls.nrElements - 1] = null; ls.nrElements--; } else { // Was called recursively to fix an undermanned parent entries[0].element = p.entries[parentIndex - 1].element; p.entries[parentIndex - 1].element = ls.entries[ls.nrElements - 1].element; entries[0].child = ls.entries[ls.nrElements].child; entries[0].child.parent = this; ls.entries[ls.nrElements] = null; ls.entries[ls.nrElements - 1].element = null; nrElements++; ls.nrElements--; } } /* * This method is called only when stealLeft can't be called, the BTreeNode * has the minimum number of elements, has a rightSibling, and the rightSibling * has more than the minimum number of elements. */ private void stealRight(int parentIndex) { BTreeNode p = parent; BTreeNode rs = p.entries[parentIndex + 1].child; if (isLeaf()) { // When stealing from leaf to leaf don't worry about children entries[nrElements] = new Entry(); entries[nrElements].element = p.entries[parentIndex].element; p.entries[parentIndex].element = rs.entries[0].element; for (int i = 0; i < rs.nrElements; i++) rs.entries[i] = rs.entries[i + 1]; rs.entries[rs.nrElements - 1] = null; nrElements++; rs.nrElements--; } else { // Was called recursively to fix an undermanned parent for (int i = 0; i <= nrElements; i++) entries[i] = entries[i + 1]; entries[nrElements].element = p.entries[parentIndex].element; p.entries[parentIndex].element = rs.entries[0].element; entries[nrElements + 1] = new Entry(); entries[nrElements + 1].child = rs.entries[0].child; entries[nrElements + 1].child.parent = this; for (int i = 0; i <= rs.nrElements; i++) rs.entries[i] = rs.entries[i + 1]; rs.entries[rs.nrElements] = null; nrElements++; rs.nrElements--; } } /* * 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; } } } /* * 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; } } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -