1. 程式人生 > >java實現B-Tree

java實現B-Tree

package com.algorithm.tree;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class BTree<T extends Comparable<T>> {
	public int minDgree;
	public int keynum;
	public T[] key;
	public ArrayList<BTree<T>> child;
	public boolean isLeaf;
	
	public BTree(){
		
	}
	
	public BTree(T[] array,int minDegree){
		BTree<T> btree=new BTree<T>();
		btree.isLeaf=true;
		btree.minDgree=minDegree;
		btree.keynum=0;
		btree.key=(T[])Array.newInstance(array.getClass().getComponentType(), 2*minDegree-1);
		Arrays.fill(btree.key, 0); /*使用反射得到的陣列填充一下再使用,省略此處會產生NullPointerException*/
		btree.child=new ArrayList<BTree<T>>(2*minDegree);
		/*Collections.fill(btree.child, null);使用此方法不會改變size()大小,換句話說此方法填充的元素數量取決於size()而不是capacity()!!!!*/
		for(int i=0;i<2*minDegree;i++){
			btree.child.add(null);
		}
		int i=1;
		for(T ele:array){
			btree=insert(btree,ele);
			System.out.println("初始化第"+i+++"個節點");
			keynum=btree.keynum;
			isLeaf=btree.isLeaf;
			key=btree.key;
			child=btree.child;
			this.minDgree=minDegree;
		}
	}
	
	public static <T extends Comparable<T>> void split(BTree<T> parent,int i){
		BTree<T> first=parent.child.get(i);
		BTree<T> second=new BTree<>();
		second.minDgree=parent.minDgree;
		second.isLeaf=first.isLeaf;
		second.key=(T[])Array.newInstance(parent.key.getClass().getComponentType(), 2*parent.minDgree-1);
		second.child=new ArrayList<BTree<T>>(2*parent.minDgree);
		for(int k=0;k<2*parent.minDgree;k++){
			
			second.child.add(null);
		}
		
		int j=parent.minDgree;
		int m=0;
		while(j<first.keynum){
			second.key[m]=first.key[j];
			second.child.set(m++, first.child.get(j++));
		}
		second.child.set(m, first.child.get(j));
		first.keynum=second.keynum=parent.minDgree-1;
		
		j=parent.keynum-1;
		while(j>=i){
			parent.key[j+1]=parent.key[j];
			if(j!=i) parent.child.set(j+1, parent.child.get(j));
			j--;
		}
		parent.key[i]=first.key[parent.minDgree-1];
		parent.keynum++;
		parent.child.set(i+1, second);
		System.out.println("fenliehou keynum"+parent.keynum+"zhiwei"+parent.key[i]+"i wei"+i);
	}
	
	public static <T extends Comparable<T>> BTree<T> insert(BTree<T> root,T ele){
		if(root==null) return null;
		if(root.keynum==(2*root.minDgree-1)){
			BTree newRoot=new BTree();
			newRoot.minDgree=root.minDgree;
			newRoot.isLeaf=false;
			newRoot.key=(T[])Array.newInstance(root.key.getClass().getComponentType(), Array.getLength(root.key));
			Arrays.fill(newRoot.key, 0);
			newRoot.keynum=0;
			newRoot.child=new ArrayList<T>(Array.getLength(root.key)+1);
			for(int i=0;i<2*newRoot.minDgree;i++){
				newRoot.child.add(null);
			}
			
			newRoot.child.set(0, root);
			split(newRoot,0);
			insertNonfull(newRoot,ele);
			return newRoot;
		}else{
			insertNonfull(root,ele);
			return root;
		}
	}
	
	public static <T extends Comparable<T>> void insertNonfull(BTree<T> p,T ele){
		T[] newArray=(T[])Arrays.copyOf(p.key, p.keynum);
		int i=Arrays.binarySearch(newArray, ele);
		int insertionPoint=-(i+1);

		if(i<0 && !p.isLeaf){
			
			if(p.child.get(insertionPoint).keynum==(2*p.minDgree-1)){
				split(p,insertionPoint);
				insertionPoint=ele.compareTo(p.key[insertionPoint])>0 ? (insertionPoint+1):insertionPoint;
			}
			insertNonfull(p.child.get(insertionPoint),ele);
		}
		if(i<0 && p.isLeaf){
			int j=p.keynum-1;
			while(j>=insertionPoint){
				p.key[j+1]=p.key[j];
				j--;
			}
			p.key[insertionPoint]=ele;
			System.out.println("cha ru ele"+ele+"wei zhi"+insertionPoint+"jie dian"+p+"keynum"+p.keynum);
			p.keynum++;
		}
	}
	
	public boolean search(T k){
		T[] array=Arrays.copyOf(key, keynum);
		int i=Arrays.binarySearch(array, k);/*NullPointerException null不能參與比較大小 */
		if(i>=0) return true;
		if(isLeaf) return false;
		int insertionPoint=-(i+1);
		return child.get(insertionPoint).search(k);
	}
	
	public void traverse(){
		int i;
		for(i=0;i<keynum;i++){
			if(child.get(i)!=null) child.get(i).traverse();
			System.out.print(key[i]+",");
		}
		if(child.get(i)!=null) child.get(i).traverse();
	}
	
	public static void main(String[] args){
		BTree<Integer> btree=new BTree<Integer>(new Integer[]{1,2,3,4,5,6,7,8,9,10,11,12,13},3);
		btree.traverse();
		boolean b1=btree.search(12);
		boolean b2=btree.search(49);
		System.out.println("\nb1 : "+b1+"   b2 : "+b2);
	}
}

輸出結果:

cha ru ele1wei zhi0jie [email protected]
初始化第1個節點
cha ru ele2wei zhi1jie [email protected]
初始化第2個節點
cha ru ele3wei zhi2jie [email protected]
初始化第3個節點
cha ru ele4wei zhi3jie [email protected]
初始化第4個節點
cha ru ele5wei zhi4jie [email protected]
初始化第5個節點
fenliehou keynum1zhiwei3i wei0
cha ru ele6wei zhi2jie

[email protected]
初始化第6個節點
cha ru ele7wei zhi3jie [email protected]
初始化第7個節點
cha ru ele8wei zhi4jie [email protected]
初始化第8個節點
fenliehou keynum2zhiwei6i wei1
cha ru ele9wei zhi2jie [email protected]
初始化第9個節點
cha ru ele10wei zhi3jie [email protected]
初始化第10個節點
cha ru ele11wei zhi4jie
[email protected]

初始化第11個節點
fenliehou keynum3zhiwei9i wei2
cha ru ele12wei zhi2jie [email protected]
初始化第12個節點
cha ru ele13wei zhi3jie [email protected]
初始化第13個節點
1,2,3,4,5,6,7,8,9,10,11,12,13,
b1 : true   b2 : false