* 实现2-3-4树
* 2-3-4树的查找效率与红-黑树接近,都是O(logN);由于使用数组,存储空间浪费现象比较严重,大约有2/7;红-黑树是平衡树,几乎每个结点的子结点存储空间都被利用了,因此存储效率高。
* 测试用例在程序中的重要性
测试用例要尽可能的覆盖到if条件语句的所有情况;本例中,要测试到结点分裂时从不同位置插入到父结点时的情况;
用大量的random数据测试;100/1000;
从上至下插入结点时,边寻找下一跳结点,边判断当前结点是否为满结点
* 若发现当前结点为满结点,有两种情况:
1. 当前结点为根结点,执行split()分裂之后,因为根结点分裂会产生一个新的根结点,所以不能通过node=prev回到上层结点,所以需要node=root;
2. 当前结点不是根结点,执行split()分裂之后,node=prev,回到上一层结点;
若不回到上一层结点,会导致新插入的数据不能进入正确的位置;
* 对当前结点执行split()分裂操作,有两种情况:
1. 当前结点为根结点,新建两个结点;
2. 当前结点不是根结点,则新建一个结点,当前结点的右侧结点转移到新建的结点上,当前结点的中间结点转移到父结点;
插入到父结点时,会有5种情况:
1) 父结点插入前只有一个结点,插入位置在唯一结点的左侧;
2) 父结点插入前只有一个结点,插入位置在唯一结点的右侧;
3) 父结点插入前有两个结点,插入位置在左侧结点的左侧;
4) 父结点插入前有两个结点,插入位置在两个结点的中间;
5) 父结点插入前有两个结点,插入位置在右侧结点的右侧;
可以通过
for(int i=node.parent.current; i>ptr; i--) node.parent.nArr[i+1]=node.parent.nArr[i];
node.parent.nArr[ptr+1]=newNode;
实现
* 2-3-4树@java/DataStructure/unit10
class Tree234{
public Node root;
public Tree234(){
root=new Node();
}
public Tree234(Node root){
this.root=root;
}
public DataItem find(DataItem data){
Node node=root;
while(node!=null){
DataItem temp=node.findItem(data);
if(temp!=null) return temp;
else{
boolean flag=false;
for(int i=node.current-1; i>=0; i--){
if(data.key>node.dArr[i].key){
node=node.nArr[i+1];
flag=true;
break;
}
}
if(flag==false) node=node.nArr[0];
}
}
return null;
}
public void insert(DataItem data){
Node node=root;
Node prev=root;
while(node!=null){
if(node.current==3){
if(node==root){
split(node);
node=root;
}
else{
split(node);
node=node.parent;
}
}
else{
boolean flag=false;
prev=node;
for(int i=node.current-1; i>=0; i--){
if(data.key>=node.dArr[i].key){
node=node.nArr[i+1];
flag=true;
break;
}
}
if(flag==false) node=node.nArr[0];
}
}
prev.insertItem(data);
}
public void split(Node node){
if(node==root){
Node newNode=new Node();
Node newNode1=new Node();
newNode.insertItem(node.removeItem(node.dArr[1]));
newNode1.insertItem(node.removeItem(node.dArr[1]));
newNode.nArr[0]=node;
newNode.nArr[1]=newNode1;
if(node.nArr[2]!=null) node.nArr[2].parent=newNode1;
if(node.nArr[3]!=null) node.nArr[3].parent=newNode1;
newNode1.nArr[0]=node.nArr[2];
newNode1.nArr[1]=node.nArr[3];
node.nArr[2]=null;
node.nArr[3]=null;
newNode1.parent=newNode;
node.parent=newNode;
root=newNode;
}
else{
int ptr=0;
while(node.parent.nArr[ptr]!=node){
ptr++;
if(ptr==4){
node.parent.display();
node.display();
System.out.println("yes");
}
}
Node newNode=new Node();
for(int i=node.parent.current; i>ptr; i--) node.parent.nArr[i+1]=node.parent.nArr[i];
/* if(node.parent.current==1 && ptr==0) node.parent.nArr[2]=node.parent.nArr[1];
else if(node.parent.current==2 && ptr==0){
node.parent.nArr[3]=node.parent.nArr[2];
node.parent.nArr[2]=node.parent.nArr[1];
}
else if(node.parent.current==2 && ptr==1){
node.parent.nArr[3]=node.parent.nArr[2];
}*/
node.parent.insertItem(node.removeItem(node.dArr[1]));
newNode.insertItem(node.removeItem(node.dArr[1]));
node.parent.nArr[ptr+1]=newNode;
if(node.nArr[2]!=null) node.nArr[2].parent=newNode;
if(node.nArr[3]!=null) node.nArr[3].parent=newNode;
newNode.nArr[0]=node.nArr[2];
newNode.nArr[1]=node.nArr[3];
node.nArr[2]=null;
node.nArr[3]=null;
newNode.parent=node.parent;
}
}
public void display(){
displayNode(root);
}
private void displayNode(Node node){
if(node==null) return;
else{
node.display();
displayNode(node.nArr[0]);
displayNode(node.nArr[1]);
displayNode(node.nArr[2]);
displayNode(node.nArr[3]);
}
}
}
class DataItem{
public int key;
public DataItem(){
key=0;
}
public DataItem(int key){
this.key=key;
}
public void display(){
System.out.print("/"+key);
}
}
class Node{
public Node [] nArr;
public DataItem [] dArr;
public int current;
public Node parent;
public int counter;
public Node(){
nArr=new Node[4];
for(int i=0; i<nArr.length; i++) nArr[i]=null;
dArr=new DataItem[3];
for(int i=0; i<dArr.length; i++) dArr[i]=new DataItem();
current=0;
parent=null;
counter=0;
}
public DataItem findItem(DataItem data){
for(int i=0; i<current; i++){
if(dArr[i].key==data.key)
return dArr[i];
}
return null;
}
public void insertItem(DataItem data){
if(current==3){
System.out.println("Full Node!");
}
else{
int i;
for(i=current-1; i>=0 && dArr[i].key>data.key; i--) dArr[i+1]=dArr[i];
dArr[i+1]=data;
current++;
}
}
public DataItem removeItem(DataItem data){
if(current==0){
System.out.println("Empty Node!");
return null;
}
else{
int i=0;
for(; i<current; i++){
if(dArr[i].key==data.key)
break;
}
if(i==current){
System.out.println("Not Found!");
return null;
}
else{
DataItem temp=dArr[i];
for(; i<current-1; i++)
dArr[i]=dArr[i+1];
current--;
return temp;
}
}
}
public void display(){
for(int i=0; i<current; i++){
dArr[i].display();
// if(++counter==4){
// System.out.println();
// counter=0;
// }
}
System.out.println();
}
}