package wind.wdb;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;
public final class MultipleSearchTree<K> {
private static final class BTreeNode<K> {
K[] key;
BTreeNode<K> parent;
BTreeNode<K>[] ptr;
int ptrSize;
BTreeNode(int order) {
this.key = (K[])new Object[order];
this.parent = null;
this.ptr = new BTreeNode[order + 1];
this.ptrSize = 1;
}
}
private static final int FIELD_LIMIT_ORDER_MINIMUM = 3;
private static final int FIELD_LIMIT_ORDER_MAXIMUM = 65535;
private static final int FIELD_DEFAULT_ORDER = 4;
private final Comparator<? super K> comparator;
private final int order;
private BTreeNode<K> root;
private int keySize;
public MultipleSearchTree(Comparator<? super K> comparator) {
checkComparator(comparator);
this.comparator = comparator;
this.order = FIELD_DEFAULT_ORDER;
}
public MultipleSearchTree(int order, Comparator<? super K> comparator) {
checkComparator(comparator);
checkOrder(order);
this.comparator = comparator;
this.order = order;
}
private static void checkOrder(int order) {
if (order < FIELD_LIMIT_ORDER_MINIMUM) {
System.out.println("阶数的取值过小,最小的阶数取值不能小于" + FIELD_LIMIT_ORDER_MINIMUM + "!");
} else if (order > FIELD_LIMIT_ORDER_MAXIMUM) {
System.out.println("阶数的取值过大,最小的阶数取值不能大于" + FIELD_LIMIT_ORDER_MAXIMUM + "!");
}
}
private static <K> void checkComparator(Comparator<? super K> comparator) {
if (comparator == null) {
throw new NullPointerException("关键码比较器不能为空!");
}
}
public boolean remove(K key) {
if (key == null || this.root == null) {
return false;
}
final Comparator<? super K> comparator = this.comparator;
BTreeNode<K> delItr = this.root;
int delPos = 0;
do {
delPos = Arrays.binarySearch(delItr.key, 0, delItr.ptrSize - 1, key, comparator);
if (delPos < 0) {
delItr = delItr.ptr[~delPos];
} else {
break;
}
} while (delItr != null);
if (delItr == null) return false;
if (delItr.ptr[delPos + 1] != null) {
BTreeNode<K> original = delItr;
delItr = delItr.ptr[delPos + 1];
while (delItr.ptr[0] != null) {
delItr = delItr.ptr[0];
}
original.key[delPos] = delItr.key[0];
delPos = 0;
}
System.arraycopy(delItr.key, delPos + 1, delItr.key, delPos, (delItr.ptrSize - 1) - (delPos + 1));
delItr.ptrSize--;
if (delItr.ptrSize < Math.ceil(this.order / 2)) {
fixUnderflow(delItr);
}
this.keySize--;
return true;
}
private void fixUnderflow(BTreeNode<K> fixItr) {
final Comparator<? super K> comparator = this.comparator;
while (fixItr.ptrSize < Math.ceil(this.order / 2)) {
BTreeNode<K> parent = fixItr.parent;
if (parent == null) {
if (fixItr.ptrSize < 2 && fixItr.ptr[0] != null) {
this.root = fixItr.ptr[0];
this.root.parent = null;
}
return;
}
int fixItrPos = 0;
while (parent.ptr[fixItrPos] != fixItr) {
++fixItrPos;
}
if (0 < fixItrPos) {
BTreeNode<K> leftSibling = parent.ptr[fixItrPos - 1];
if (leftSibling.ptrSize - 1 >= Math.ceil(this.order / 2)) {
System.arraycopy(fixItr.key, 0, fixItr.key, 1, fixItr.ptrSize - 1);
fixItr.key[0] = parent.key[fixItrPos - 1];
parent.key[fixItrPos - 1] = leftSibling.key[(leftSibling.ptrSize - 1) - 1];
System.arraycopy(fixItr.ptr, 0, fixItr.ptr, 1, fixItr.ptrSize);
fixItr.ptr[0] = leftSibling.ptr[leftSibling.ptrSize - 1];
if (fixItr.ptr[0] != null) {
fixItr.ptr[0].parent = fixItr;
}
fixItr.ptrSize++;
leftSibling.ptrSize--;
return;
}
}
if (fixItrPos < parent.ptrSize - 1) {
BTreeNode<K> rightSibling = parent.ptr[fixItrPos + 1];
if (rightSibling.ptrSize - 1 >= Math.ceil(this.order / 2)) {
fixItr.key[fixItr.ptrSize - 1] = parent.key[fixItrPos];
parent.key[fixItrPos] = rightSibling.key[0];
System.arraycopy(rightSibling.key, 1, rightSibling.key, 0, (rightSibling.ptrSize - 1) - 1);
fixItr.ptr[fixItr.ptrSize] = rightSibling.ptr[0];
System.arraycopy(rightSibling.ptr, 1, rightSibling.ptr, 0, rightSibling.ptrSize - 1);
if (fixItr.ptr[fixItr.ptrSize] != null) {
fixItr.ptr[fixItr.ptrSize].parent = fixItr;
}
fixItr.ptrSize++;
rightSibling.ptrSize--;
return;
}
}
if (0 < fixItrPos) {
BTreeNode<K> leftSibling = parent.ptr[fixItrPos - 1];
leftSibling.key[leftSibling.ptrSize - 1] = parent.key[fixItrPos - 1];
System.arraycopy(parent.key, fixItrPos, parent.key, fixItrPos - 1, (parent.ptrSize - 1) - fixItrPos);
System.arraycopy(parent.ptr, fixItrPos + 1, parent.ptr, fixItrPos, parent.ptrSize - (fixItrPos + 1));
parent.ptrSize--;
System.arraycopy(fixItr.key, 0, leftSibling.key, leftSibling.ptrSize, fixItr.ptrSize - 1);
if (fixItr.ptr[0] != null) {
System.arraycopy(fixItr.ptr, 0, leftSibling.ptr, leftSibling.ptrSize, fixItr.ptrSize);
for (int i = 0; i < fixItr.ptrSize; ++i) {
fixItr.ptr[i].parent = leftSibling;
}
}
leftSibling.ptrSize += fixItr.ptrSize;
} else {
BTreeNode<K> rightSibling = parent.ptr[fixItrPos + 1];
fixItr.key[fixItr.ptrSize - 1] = parent.key[fixItrPos];
System.arraycopy(parent.key, fixItrPos + 1, parent.key, fixItrPos, (parent.ptrSize - 1) - (fixItrPos + 1));
System.arraycopy(parent.ptr, fixItrPos + 2, parent.ptr, fixItrPos + 1, parent.ptrSize - (fixItrPos + 2));
parent.ptrSize--;
System.arraycopy(rightSibling.key, 0, fixItr.key, fixItr.ptrSize, rightSibling.ptrSize - 1);
if (rightSibling.ptr[0] != null) {
System.arraycopy(rightSibling.ptr, 0, fixItr.ptr, fixItr.ptrSize, rightSibling.ptrSize);
for (int i = 0; i < rightSibling.ptrSize; ++i) {
rightSibling.ptr[i].parent = fixItr;
}
}
fixItr.ptrSize += rightSibling.ptrSize;
}
fixItr = parent;
}
}
public boolean add(K key) {
if (key == null) {
return false;
} else if (this.root != null) {
final Comparator<? super K> comparator = this.comparator;
BTreeNode<K> iterator = this.root;
BTreeNode<K> insert = null;
int insPos = 0;
do {
insPos = Arrays.binarySearch(iterator.key, 0, iterator.ptrSize - 1, key, comparator);
if (insPos < 0) {
insert = iterator;
iterator = iterator.ptr[~insPos];
} else {
return false;
}
} while (iterator != null);
insPos = ~insPos;
System.arraycopy(insert.key, insPos, insert.key, insPos + 1, (insert.ptrSize - 1) - insPos);
insert.key[insPos] = key;
insert.ptrSize++;
if (insert.ptrSize > this.order) {
fixOverflow(insert);
}
} else {
this.root = new BTreeNode<>(this.order);
this.root.key[0] = key;
this.root.ptrSize = 2;
}
this.keySize++;
return true;
}
private final void fixOverflow(BTreeNode<K> fixItr) {
final Comparator<? super K> comparator = this.comparator;
while (fixItr.ptrSize > this.order) {
BTreeNode<K> parent = fixItr.parent;
BTreeNode<K> right = new BTreeNode<>(this.order);
int midKeyIndex = (fixItr.ptrSize - 1) >> 1;
System.arraycopy(fixItr.key, midKeyIndex + 1, right.key, 0, (fixItr.ptrSize - 1) - (midKeyIndex + 1));
if (fixItr.ptr[0] != null) {
System.arraycopy(fixItr.ptr, midKeyIndex + 1, right.ptr, 0, fixItr.ptrSize - (midKeyIndex + 1));
for (int i = midKeyIndex + 1; i < fixItr.ptrSize; ++i) {
fixItr.ptr[i].parent = right;
}
}
right.ptrSize = fixItr.ptrSize - (midKeyIndex + 1);
fixItr.ptrSize -= right.ptrSize;
if (parent == null) {
this.root = new BTreeNode<>(this.order);
this.root.key[0] = fixItr.key[midKeyIndex];
this.root.ptr[0] = fixItr;
this.root.ptr[1] = right;
fixItr.parent = this.root;
right.parent = this.root;
this.root.ptrSize = 2;
return;
}
int risePos = ~Arrays.binarySearch(parent.key, 0, parent.ptrSize - 1, fixItr.key[midKeyIndex], comparator);
System.arraycopy(parent.key, risePos, parent.key, risePos + 1, (parent.ptrSize - 1) - risePos);
parent.key[risePos] = fixItr.key[midKeyIndex];
System.arraycopy(parent.ptr, risePos + 1, parent.ptr, risePos + 2, parent.ptrSize - (risePos + 1));
parent.ptr[risePos + 1] = right;
right.parent = parent;
parent.ptrSize++;
fixItr = parent;
}
}
}
final class Run {
public static void main(String[] args) {
MultipleSearchTree<Double> bTree = new MultipleSearchTree<>(4, Double::compareTo);
Random random = new Random();
Double[] key = new Double[100000];
for (int j = 0; j < 100; ++j) {
for (int i = 0; i < key.length; ++i) {
key[i] = random.nextDouble();
}
for (int i = 0; i < key.length; ++i) {
System.out.print("第" + (i + 1) + "轮:");
System.out.println(bTree.add(key[i]) ? "插入成功" : "插入失败");
}
for (int i = 0; i < key.length; ++i) {
System.out.print("第" + (i + 1) + "轮:");
System.out.println(bTree.remove(key[i]) ? "删除成功" : "删除失败");
}
}
}
}