Java实现B+树的完整代码
package javaDataStructure;
import java.util.LinkedList;
import java.util.Queue;
public class BPlusTree {
private final int MaxOrder=5;
private class BTreeNode{
int nodeTotal=0;
int[] values=new int[MaxOrder];
BTreeNode[] children=new BTreeNode[MaxOrder];
BTreeNode parent=null;
BTreeNode frontDataLeaf = null;
BTreeNode laterDataLeaf = null;
public BTreeNode(int data) {
this.values[0]=data;
this.nodeTotal++;
}
}
private BTreeNode ROOT=null;
private int SIZE=0;
public int size() {
return this.SIZE;
}
public void visitAllLeavesNode() {
if(this.ROOT==null) {
System.out.println("The tree is null by 'visitAllLeavesNode'!");
return;
}
int sum=0;
BTreeNode tempNode = this.ROOT;
while (tempNode.children[0]!=null) {
tempNode=tempNode.children[0];
}
while (tempNode!=null) {
System.out.print("(");
for(int i=0; i<tempNode.nodeTotal; i++) {
System.out.print(tempNode.values[i]+",");
sum++;
}
System.out.print(")");
tempNode=tempNode.laterDataLeaf;
}
System.out.println();
tempNode = this.ROOT;
while (tempNode.children[tempNode.nodeTotal-1]!=null) {
tempNode=tempNode.children[tempNode.nodeTotal-1];
}
while (tempNode!=null) {
System.out.print("(");
for(int i=tempNode.nodeTotal-1; i>-1; i--) {
System.out.print(tempNode.values[i]+",");
}
System.out.print(")");
tempNode=tempNode.frontDataLeaf;
}
System.out.println();
System.out.println("(visitAllLeavesNode): The data of leaves is "+sum);
}
public void visitAllNode() {
if(this.ROOT==null) {
System.out.println("The tree is null by 'visitAllNode'!");
return;
}
Queue<BTreeNode> aQueue=new LinkedList<BTreeNode>();
int thisFlower=0;
int nextFlower=0;
aQueue.add(this.ROOT);
thisFlower++;
BTreeNode temp;
while (!aQueue.isEmpty()) {
temp = aQueue.poll();
thisFlower--;
System.out.print("(");
for(int i=0; i<temp.nodeTotal; i++) {
if(temp.children[i]!=null) {
aQueue.add(temp.children[i]);
nextFlower++;
}
if(i<temp.nodeTotal-1) {
System.out.print(temp.values[i]+",");
}else {
System.out.print(temp.values[i]);
}
}
System.out.print(")");
if(thisFlower==0) {
thisFlower=nextFlower;
nextFlower=0;
System.out.println();
}
}
}
public boolean findData(int data) {
if(this.ROOT==null) return false;
if(findTheNodePositionForRemove(data,this.ROOT)!=null) {
return true;
}else {
return false;
}
}
public void add(int data) {
if(this.ROOT==null) {
this.ROOT = new BTreeNode(data);
this.SIZE = 1;
return;
}
BTreeNode goalNode = findTheNodePositionForAdd(data, this.ROOT);
if(goalNode == null) return;
insertTheAddDataToTheNode(data, goalNode);
this.SIZE++;
}
private void insertTheAddDataToTheNode(int data, BTreeNode goalNode) {
if(goalNode.nodeTotal<this.MaxOrder) {
dataInsertInSequence(goalNode, data);
if(data==goalNode.values[goalNode.nodeTotal]) {
updataParetFormationForAdd(goalNode.parent, goalNode.values[goalNode.nodeTotal-1] ,data);
}
goalNode.nodeTotal++;
return;
}
if(goalNode.nodeTotal==this.MaxOrder) {
BTreeNode newDivisiveNode = new BTreeNode(goalNode.values[this.MaxOrder/2]);
goalNode.values[this.MaxOrder/2]=0;
for(int i=this.MaxOrder/2+1, j=1; i<this.MaxOrder; i++) {
newDivisiveNode.values[j++]=goalNode.values[i];
goalNode.values[i]=0;
}
goalNode.nodeTotal=this.MaxOrder/2;
newDivisiveNode.nodeTotal=this.MaxOrder-this.MaxOrder/2;
if(data<newDivisiveNode.values[0]) {
dataInsertInSequence(goalNode,data);
goalNode.nodeTotal++;
}else {
dataInsertInSequence(newDivisiveNode,data);
newDivisiveNode.nodeTotal++;
}
if(goalNode.children[0]==null) {
BTreeNode tempNode=goalNode.laterDataLeaf;
goalNode.laterDataLeaf=newDivisiveNode;
newDivisiveNode.frontDataLeaf=goalNode;
if(tempNode!=null) {
tempNode.frontDataLeaf=newDivisiveNode;
newDivisiveNode.laterDataLeaf=tempNode;
}
}
nodeInsertInTree(goalNode, newDivisiveNode);
}
}
private void nodeInsertInTree(BTreeNode letfNode, BTreeNode rightNode) {
if(letfNode.parent==null) {
BTreeNode newParent=new BTreeNode(letfNode.values[letfNode.nodeTotal-1]);
newParent.children[0]=letfNode;
letfNode.parent=newParent;
newParent.values[1]=rightNode.values[rightNode.nodeTotal-1];
newParent.nodeTotal++;
newParent.children[1]=rightNode;
rightNode.parent=newParent;
this.ROOT=newParent;
return;
}
if(letfNode.parent.nodeTotal<this.MaxOrder) {
int iLR=0;
for(iLR=0; iLR < letfNode.parent.nodeTotal; iLR++) { if(letfNode.parent.children[iLR]==letfNode) break; }
boolean theAddDataIsMax=false;
if(letfNode.parent.values[iLR]!=rightNode.values[rightNode.nodeTotal-1])theAddDataIsMax=true;
letfNode.parent.values[iLR]=letfNode.values[letfNode.nodeTotal-1];
for(int i = this.MaxOrder-1; i>iLR; i--) {
letfNode.parent.values[i]=letfNode.parent.values[i-1];
letfNode.parent.children[i]=letfNode.parent.children[i-1];
}
letfNode.parent.values[iLR+1]=rightNode.values[rightNode.nodeTotal-1];
letfNode.parent.children[iLR+1]=rightNode;
rightNode.parent=letfNode.parent;
rightNode.parent.nodeTotal++;
if(theAddDataIsMax) {
if(rightNode.parent.parent!=null)
updataParetFormationForAdd(rightNode.parent.parent, rightNode.values[rightNode.nodeTotal-2] ,rightNode.values[rightNode.nodeTotal-1]);
}
return;
}
if (letfNode.parent.nodeTotal==this.MaxOrder) {
BTreeNode parentNodeLeft = letfNode.parent;
int iLR=0;
for(iLR=0; iLR < letfNode.parent.nodeTotal; iLR++) { if(letfNode.parent.children[iLR]==letfNode) break; }
letfNode.parent.values[iLR]=letfNode.values[letfNode.nodeTotal-1];
BTreeNode newDivisiveNode = new BTreeNode(parentNodeLeft.values[this.MaxOrder/2]);
newDivisiveNode.children[0]=parentNodeLeft.children[this.MaxOrder/2];
newDivisiveNode.children[0].parent=newDivisiveNode;
parentNodeLeft.values[this.MaxOrder/2]=0;
parentNodeLeft.children[this.MaxOrder/2]=null;
for(int i=this.MaxOrder/2+1, j=1; i<this.MaxOrder; i++) {
newDivisiveNode.values[j]=parentNodeLeft.values[i];
newDivisiveNode.children[j]=parentNodeLeft.children[i];
newDivisiveNode.children[j++].parent=newDivisiveNode;
parentNodeLeft.values[i]=0;
parentNodeLeft.children[i]=null;
}
parentNodeLeft.nodeTotal=this.MaxOrder/2;
newDivisiveNode.nodeTotal=this.MaxOrder-this.MaxOrder/2;
if(rightNode.values[rightNode.nodeTotal-1]<newDivisiveNode.values[0]) {
int pos = dataInsertInSequence(parentNodeLeft, rightNode.values[rightNode.nodeTotal-1]);
parentNodeLeft.children[pos]=rightNode;
rightNode.parent = parentNodeLeft;
parentNodeLeft.nodeTotal++;
}else {
int pos = dataInsertInSequence(newDivisiveNode, rightNode.values[rightNode.nodeTotal-1]);
newDivisiveNode.children[pos]=rightNode;
rightNode.parent = newDivisiveNode;
newDivisiveNode.nodeTotal++;
}
nodeInsertInTree(parentNodeLeft, newDivisiveNode);
}
}
private int dataInsertInSequence(BTreeNode goalNode, int data) {
int i=0;
for(i=0; i<goalNode.nodeTotal; i++) {
if(data<goalNode.values[i]){
break;
}
}
int tempValue;
BTreeNode tempNode,dataNode=null;
for(int j=i; j<goalNode.nodeTotal+1; j++) {
tempValue=goalNode.values[j];
tempNode=goalNode.children[j];
goalNode.values[j]=data;
goalNode.children[j]=dataNode;
data=tempValue;
dataNode=tempNode;
}
return i;
}
private void updataParetFormationForAdd(BTreeNode nodeIndex, int oldData, int newData) {
if(nodeIndex==null) {
return;
}else {
int i=0;
for(i=0; i<nodeIndex.nodeTotal; i++) {
if(nodeIndex.values[i] == oldData) break;
}
if(i==nodeIndex.nodeTotal) {
return;
}else {
nodeIndex.values[i]=newData;
updataParetFormationForAdd(nodeIndex.parent,oldData,newData);
}
}
}
private BTreeNode findTheNodePositionForAdd(int data, BTreeNode nodeIndex){
int i=0;
for(i=0; i<nodeIndex.nodeTotal; i++) {
if(data==nodeIndex.values[i]) {
return null;
}else if(data<nodeIndex.values[i]){
break;
}
}
if(i==nodeIndex.nodeTotal) {
BTreeNode tempNode=this.ROOT;
while (tempNode.children[tempNode.nodeTotal-1]!=null) {
tempNode=tempNode.children[tempNode.nodeTotal-1];
}
return tempNode;
}
if(nodeIndex.children[i]==null) {
return nodeIndex;
}else {
return findTheNodePositionForAdd(data, nodeIndex.children[i]);
}
}
public void remove(int data) {
if(this.ROOT==null)return;
BTreeNode targetNode=findTheNodePositionForRemove(data, this.ROOT);
if(targetNode==null) { return; }
int iIndex=0;
while (iIndex<targetNode.nodeTotal) {
if(data==targetNode.values[iIndex])break;
iIndex++;
}
for(int i=iIndex; i<targetNode.nodeTotal-1; i++) {
targetNode.values[i]=targetNode.values[i+1];
}
targetNode.nodeTotal--;
if(iIndex==targetNode.nodeTotal && targetNode.parent!=null) {
updataParetFormationForAdd( targetNode.parent, targetNode.values[targetNode.nodeTotal], targetNode.values[targetNode.nodeTotal-1]);
}
if(targetNode.nodeTotal < this.MaxOrder/2) removeUpwordParent(targetNode);
this.SIZE--;
}
private void removeUpwordParent(BTreeNode nodeIndex) {
if(nodeIndex.parent==null) {
if(nodeIndex.nodeTotal==1 && nodeIndex.children[0]!=null) {
this.ROOT=nodeIndex.children[0];
this.ROOT.parent=null;
}
if(nodeIndex.nodeTotal==0) this.ROOT = null;
return;
}
int iParentIndex=0;
while (iParentIndex < nodeIndex.parent.nodeTotal) {
if(nodeIndex == nodeIndex.parent.children[iParentIndex]) break;
iParentIndex++;
}
if(iParentIndex+1 < nodeIndex.parent.nodeTotal && nodeIndex.parent.children[iParentIndex+1].nodeTotal > this.MaxOrder/2) {
nodeIndex.values[nodeIndex.nodeTotal]=nodeIndex.parent.children[iParentIndex+1].values[0];
nodeIndex.children[nodeIndex.nodeTotal]=nodeIndex.parent.children[iParentIndex+1].children[0];
if(nodeIndex.children[nodeIndex.nodeTotal]!=null) nodeIndex.children[nodeIndex.nodeTotal].parent=nodeIndex;
nodeIndex.nodeTotal++;
updataParetFormationForAdd(nodeIndex.parent, nodeIndex.values[nodeIndex.nodeTotal-2],nodeIndex.values[nodeIndex.nodeTotal-1]);
for(int i=0; i < nodeIndex.parent.children[iParentIndex+1].nodeTotal-1; i++) {
nodeIndex.parent.children[iParentIndex+1].values[i] = nodeIndex.parent.children[iParentIndex+1].values[i+1];
nodeIndex.parent.children[iParentIndex+1].children[i] = nodeIndex.parent.children[iParentIndex+1].children[i+1];
}
nodeIndex.parent.children[iParentIndex+1].nodeTotal--;
return;
}
if(iParentIndex-1 > -1 && nodeIndex.parent.children[iParentIndex-1].nodeTotal > this.MaxOrder/2) {
for(int i=nodeIndex.nodeTotal; i>0; i--) {
nodeIndex.values[i]=nodeIndex.values[i-1];
nodeIndex.children[i]=nodeIndex.children[i-1];
}
nodeIndex.values[0]=nodeIndex.parent.children[iParentIndex-1].values[nodeIndex.parent.children[iParentIndex-1].nodeTotal-1];
nodeIndex.children[0]=nodeIndex.parent.children[iParentIndex-1].children[nodeIndex.parent.children[iParentIndex-1].nodeTotal-1];
if(nodeIndex.children[0]!=null) nodeIndex.children[0].parent=nodeIndex;
nodeIndex.nodeTotal++;
nodeIndex.parent.children[iParentIndex-1].nodeTotal--;
updataParetFormationForAdd(nodeIndex.parent,
nodeIndex.parent.children[iParentIndex-1].values[nodeIndex.parent.children[iParentIndex-1].nodeTotal],
nodeIndex.parent.children[iParentIndex-1].values[nodeIndex.parent.children[iParentIndex-1].nodeTotal-1]);
return;
}
if( nodeIndex.children[0]==null ) {
if(nodeIndex.frontDataLeaf!=null) nodeIndex.frontDataLeaf.laterDataLeaf=nodeIndex.laterDataLeaf;
if(nodeIndex.laterDataLeaf!=null) nodeIndex.laterDataLeaf.frontDataLeaf=nodeIndex.frontDataLeaf;
}
if(iParentIndex+1 < nodeIndex.parent.nodeTotal && nodeIndex.parent.children[iParentIndex+1].nodeTotal<=this.MaxOrder/2) {
for(int i = nodeIndex.parent.children[iParentIndex+1].nodeTotal + nodeIndex.nodeTotal-1; i > nodeIndex.nodeTotal-1; i--) {
if(nodeIndex.parent.children[iParentIndex+1].nodeTotal + nodeIndex.nodeTotal-1 == 5) {
System.out.println(nodeIndex.values[0]+","+nodeIndex.values[1]+","+nodeIndex.values[2]+","+nodeIndex.values[3]);
System.out.println("I am '5'."+nodeIndex.parent.children[iParentIndex+1].nodeTotal + "+" + nodeIndex.nodeTotal);
}
nodeIndex.parent.children[iParentIndex+1].values[i]=nodeIndex.parent.children[iParentIndex+1].values[i-nodeIndex.nodeTotal];
nodeIndex.parent.children[iParentIndex+1].children[i]=nodeIndex.parent.children[iParentIndex+1].children[i-nodeIndex.nodeTotal];
}
for(int i = nodeIndex.nodeTotal-1; i > -1; i--) {
nodeIndex.parent.children[iParentIndex+1].values[i]=nodeIndex.values[i];
nodeIndex.parent.children[iParentIndex+1].children[i]=nodeIndex.children[i];
if(nodeIndex.parent.children[iParentIndex+1].children[i]!=null)
nodeIndex.parent.children[iParentIndex+1].children[i].parent=nodeIndex.parent.children[iParentIndex+1];
}
nodeIndex.parent.children[iParentIndex+1].nodeTotal += nodeIndex.nodeTotal;
for(int i=iParentIndex; i<nodeIndex.parent.nodeTotal-1; i++) {
nodeIndex.parent.values[i]=nodeIndex.parent.values[i+1];
nodeIndex.parent.children[i]=nodeIndex.parent.children[i+1];
}
nodeIndex.parent.nodeTotal--;
if(nodeIndex.parent.nodeTotal<this.MaxOrder/2) {
removeUpwordParent(nodeIndex.parent);
}else {
return;
}
}
if(iParentIndex-1 > -1 && nodeIndex.parent.children[iParentIndex-1].nodeTotal <= this.MaxOrder/2) {
for(int i=0; i<nodeIndex.nodeTotal; i++) {
if(nodeIndex.parent.children[iParentIndex-1].nodeTotal + i==5)System.out.println("I am '5'"+nodeIndex.nodeTotal);
nodeIndex.parent.children[iParentIndex-1].values[nodeIndex.parent.children[iParentIndex-1].nodeTotal + i ]=nodeIndex.values[i];
nodeIndex.parent.children[iParentIndex-1].children[nodeIndex.parent.children[iParentIndex-1].nodeTotal + i ]=nodeIndex.children[i];
if(nodeIndex.parent.children[iParentIndex-1].children[nodeIndex.parent.children[iParentIndex-1].nodeTotal + i ] != null)
nodeIndex.parent.children[iParentIndex-1].children[nodeIndex.parent.children[iParentIndex-1].nodeTotal + i ].parent=
nodeIndex.parent.children[iParentIndex-1];
}
nodeIndex.parent.children[iParentIndex-1].nodeTotal += nodeIndex.nodeTotal;
updataParetFormationForAdd(nodeIndex.parent,
nodeIndex.parent.children[iParentIndex-1].values[nodeIndex.parent.children[iParentIndex-1].nodeTotal-nodeIndex.nodeTotal-1],
nodeIndex.parent.children[iParentIndex-1].values[nodeIndex.parent.children[iParentIndex-1].nodeTotal-1]);
for(int i=iParentIndex; i<nodeIndex.parent.nodeTotal-1; i++) {
nodeIndex.parent.values[i]=nodeIndex.parent.values[i+1];
nodeIndex.parent.children[i]=nodeIndex.parent.children[i+1];
}
nodeIndex.parent.nodeTotal--;
if(iParentIndex==nodeIndex.parent.nodeTotal)
updataParetFormationForAdd(nodeIndex.parent.parent,
nodeIndex.parent.values[nodeIndex.parent.nodeTotal], nodeIndex.parent.values[nodeIndex.parent.nodeTotal-1]);
if(nodeIndex.parent.nodeTotal<this.MaxOrder/2) {
removeUpwordParent(nodeIndex.parent);
}else {
return;
}
}
}
private BTreeNode findTheNodePositionForRemove(int data, BTreeNode nodeIndex){
int i=0;
for(i=0; i<nodeIndex.nodeTotal; i++) if(data <= nodeIndex.values[i]) break;
if(i==nodeIndex.nodeTotal)return null;
if(nodeIndex.children[i]==null) {
if(nodeIndex.values[i]!=data) {
return null;
} else {
return nodeIndex;
}
}else {
return findTheNodePositionForRemove(data, nodeIndex.children[i]);
}
}
}