posts - 2,  comments - 7,  trackbacks - 0
/* BPlusTree.java
 * Support class for Pyramid Technique
 * Capable of doing insertion, search, but not deletion
 * Modified from jwang01 's work as found @ 
http://en.wikibooks.org/wiki/Transwiki:B+_Tree_Java_Implementation
 * Fay Pan 2007
 * Computer Science, University of Otago
 
*/


public class BPlusTree{
    
private Node root;
    
private int h = 0// height of the tree
    private final int order;
    
private final int max_inner_keys;
    
private final int min_inner_keys;
    
private final int max_inner_pointers;
    
private final int min_inner_pointers;
    
private final int max_leaf_keys;
    
private final int min_leaf_keys;
    
private final int max_leaf_points;
    
private final int min_leaf_points;
    
private final int dim;
    
private int counter =0;//count how many nodes in the tree and link
    private int seek_time;
    
private static int total=0;

    
/*constructor*/
    
// t is the order of the tree
    public BPlusTree(int t, int d){
    dim 
=d;
    h 
= 0;
    order 
= t;
    min_inner_keys 
= min_leaf_keys = min_leaf_points = t;
    max_inner_keys 
= max_leaf_keys = max_leaf_points = 2*t;
    min_inner_pointers 
= t+1;
    max_inner_pointers 
= 2*+1;
    
/*
        min_keys = t;
    min_points = 2*t;
    max_keys = 2*t;
    max_points = 2*t + 1;
*/
    root 
= new LNode();
    }
    
    
public BPlusTree(int l, int i, int d){
    dim 
= d;
    h
=0;
    order 
= i;
    min_inner_keys 
= i;
    max_inner_keys 
= 2*i;
    min_inner_pointers 
= i+1;
    max_inner_pointers 
= 2*+1;
    min_leaf_points 
= min_leaf_keys = l;
    max_leaf_points 
= max_leaf_keys = 2*l;
    root 
= new LNode();
    }

    
public void print(){

    Node node 
= root;
        
int d=h, idx=0;
        
while( d-- != 0 ) {//need to traverse down to the leaf
        INode inner = (INode) node;
            
            node 
= inner.children[idx];
        }
         System.out.println(d);
        
//We are @ leaf after while loop
        LNode leaf=  (LNode) node;
        
//for(int i =0; i< max_points; i++){
    while(leaf!=null){
        System.out.println(leaf.num);
        
for(int j = 0; j < leaf.num; j++){//print the keys and points in one leaf node
        System.out.println("key = " + leaf.keys[j]);
        
for(int k = 0; k < dim; k++){
            
            System.out.print(leaf.points[j][k]
+ " ");
        }
    
        }
        
if(leaf.next!=null) {
        leaf
=leaf.next;
        
//System.out.println("link to a new leaf");
        }else break;
        
//System.out.println(leaf.num);
    }
    }
     

    
public void insert(double key, double[] point){
    
    
//System.out.println("insert key=" + key);
    InsertResult result = new InsertResult();
    
boolean split;
    
if(h==0){// The root is a leaf node
        split= insertLeaf((LNode)root, key, point, result);
    } 
else {// The root is an inner node
        split= insertInner((INode)root, h, key, point, result);
    }
    
if(split) {
        
// The old root was splitted in two parts.
        
// We have to create a new root pointing to them
        total = total +2;
        h
++;
        root
= new INode();
        INode _root 
= (INode) root;
        _root.num 
= 1;
        _root.keys[
0= result.key;
        _root.children[
0= result.left;
        _root.children[
1= result.right;
    }
    
//id++;
    }
    
    
public static int getTotal(){
    
return total;
    }

     
/* 
      * Looks for the given key. If it is not found, it returns false,
      * if it is found, it returns true and copies the associated value
      * unless the pointer is null.
      
*/
    
public boolean find(double key, double[] point) {
    seek_time 
= 0;
    
double[][] result=new double[100][dim];
        Node node 
= root;
        
int d=h, idx, n=0;
        
while( d-- != 0 ) {//need to traverse down to the leaf
        INode inner = (INode) node;
            idx 
= getInnerLoc(key, inner.keys, inner.num);
            node 
= inner.children[idx];
        seek_time
++;
        }
        
        
//We are @ leaf after while loop
        LNode leaf=  (LNode) node;
        idx 
= getLeafLoc(key, leaf.keys, leaf.num);
        
if(idx<leaf.num && leaf.keys[idx] == key) {
        
while(leaf.keys[idx] == key){
        result[n] 
= leaf.points[idx];
        n
++;
        
if(idx<=leaf.num) idx++;
        
else{
            leaf 
= leaf.next;
            seek_time
++;
            idx
=0;
        }
        }
        
//search for point in result array
        int valid = 0;
        
for(int i = 0; i < result.length; i++){
        
for(int j =0; j < dim; j++){
            
if(result[i][j] == point[j]) valid ++;
        }
        
if (valid==3return true;
        valid
=0;
        }
        }
else{
        
return false;
        }
    
return false;
    }

    
public int getTime(){
    
return seek_time;
    }

     
/* 
      * Looks for the given key. If it is not found, it returns false,
      * if it is found, it returns true and copies the associated value
      * unless the pointer is null.
      
*/
    
public ResultList findRange(double key, double high) {
    seek_time
=0;
    ResultNode no;
    ResultList r 
= new ResultList();
    ResultNode pos 
= new ResultNode();
    
//double[][] result=new double[1300][dim];
        Node node = root;
        
int d=h, idx, n=0;
        
while( d-- != 0 ) {//need to traverse down to the leaf
        INode inner = (INode) node;
            idx 
= getInnerLoc(key, inner.keys, inner.num);
            node 
= inner.children[idx];
        seek_time
++;
        }
        
        
//We are @ leaf after while loop
        LNode leaf=  (LNode) node;
        idx 
= getLeafLoc(key, leaf.keys, leaf.num);
        
if(idx<leaf.num && leaf.keys[idx] >= key) {//start from the low key
        int flag =0;
        
while(leaf.keys[idx] <= high){//end with high key
        if(idx<leaf.num-1 && flag==0){//if it is in the middle of a bucket
            no = new ResultNode(leaf.keys[idx], leaf.points[idx]);
            
if(r.header.k==0) {
            
//System.out.println("Start");
            r = new ResultList(no);
            r.inc();
            pos 
= r.header;
            } 
else {
            r.inc();
            pos.next 
= no;
            pos 
= pos.next;
            }
           
            n
++;
            idx
++;
        }
        
else if(idx==leaf.num-1 && flag ==0){// if it reaches the end of a bucket
            
//System.out.println("last");
            no = new ResultNode(leaf.keys[idx], leaf.points[idx]);
            
if(r.header.p==null) {
            r 
= new ResultList(no);
            r.inc();
            pos 
= r.header;
            } 
else {
            r.inc();
            pos.next 
= no;
            pos 
= pos.next;
            }
           
            n
++;
            flag 
= 1;
        } 
else {//go to the next bucket
            if(leaf.next!=null){
            
//System.out.println("Jump");
            leaf = leaf.next;
            seek_time
++;
            idx
=0;
            flag 
= 0;
            } 
else {
            
break;
            }
        }
        }
        
return r;
        }
else{
        
return null;
        }
    }

    
//return the position where the 'key' should be inserted in a leaf node
    private static int getLeafLoc(double key, double[] keys, int num){
    
//linear search
    int i = 0;
    
while((i < num) && (keys[i] < key)){
        i
++;
    }
    
return i;
    }
   
    
//return the position where the 'key' should be inserted in an inner node
    private static int getInnerLoc(double key, double[] keys, int num){
    
int i = 0;
    
while((i < num) && (keys[i] <= key)){
        i
++;
    }
    
return i;
    }

    
protected boolean insertLeaf(LNode node, double key, double[] point, InsertResult result){
    
boolean split = false;
    
//linear search
    int idx = getLeafLoc(key, node.keys, node.num);
    
if(node.num == max_leaf_keys){//the node was full, we must split it
        LNode sibling = new LNode();
        sibling.num 
= node.num - min_leaf_keys;
        
int sNum = sibling.num;
        
for(int j = 0; j < sNum; j++){
        
int mj = min_leaf_keys + j;
        sibling.keys[j] 
= node.keys[mj];
        
for(int k = 0; k < dim; k++)
            sibling.points[j][k] 
= node.points[mj][k];
        }
        node.num 
= min_leaf_keys;
        
if(idx < min_leaf_keys){
        
//inserted element goes to left sibling
        insertLeafNonfull(node, key, point, idx);
        } 
else {
        
//inserted element goes to right sibling
        insertLeafNonfull(sibling, key, point, idx - min_leaf_keys);
        }
        
//nitofy the parent about the split
        split = true;
        result.key 
= sibling.keys[0];
        
//System.out.println(result.key);
        result.left = node;
        result.right 
= sibling;
        sibling.next 
= node.next;
        node.next 
= sibling;
        
//System.out.println(node.next.num+ " " +sibling.num); 
        
//verified the linked list works fine
        total ++//increment total number of nodes by 1
    } else {// the node is not full
        insertLeafNonfull(node, key, point, idx);
    }
    
return split;
    }

    
private void insertLeafNonfull(LNode node, double key, double[] point, int idx){
    
for(int i = node.num; i > idx; i--){
        node.keys[i] 
= node.keys[i-1];
        
for(int k = 0; k < dim; k++)
        node.points[i][k] 
= node.points[i-1][k];
    }
    node.keys[idx] 
= key;
    
for(int k = 0; k < dim; k++) node.points[idx][k] = point[k];
    node.num
++;
    }

    
protected boolean insertInner(INode node, int height, double key, double[] point, InsertResult result){
    
//early split if node is full
    boolean split = false;
    
if(node.num == max_inner_keys){//split
        INode sibling = new INode();
        
int sNum = sibling.num = node.num - min_inner_keys;
        
for(int i = 0; i < sNum; i++){
        sibling.keys[i] 
= node.keys[min_inner_keys + i];
        sibling.children[i] 
= node.children[min_inner_keys + i];
        }
        sibling.children[sNum] 
= node.children[node.num];
        node.num 
= min_inner_keys - 1//inner node's key doesn't repeat itself

        split 
= true;
        result.key 
= node.keys[min_inner_keys - 1];
        result.left 
= node;
        result.right 
= sibling;

        
//insert into the appropriate sibling
        if(key < result.key){
        insertInnerNonfull(node, height, key, point);
        } 
else {
        insertInnerNonfull(sibling, height, key, point);
        }
        total 
++//increment total number of nodes by 1
    } else { //no split
        insertInnerNonfull(node, height, key, point);
    }
    
return split;
    }

    
private void insertInnerNonfull(INode node, int height, double key, double[] point){
    
//linear search
    int idx = getInnerLoc(key, node.keys, node.num);
    InsertResult result 
= new InsertResult();
    
boolean split;
    
if(height -1 == 0){ //the children are leaf
        split = insertLeaf((LNode)node.children[idx], key, point, result);
    } 
else { //the children are inner
        INode child = (INode) node.children[idx];
        split 
= insertInner(child, height-1, key, point, result);
    }
    
if(split){
        
if(idx == node.num){
        
//insertion at the rightmost key
        node.keys[idx] = result.key;
        node.children[idx] 
= result.left;
        node.children[idx
+1= result.right;
        node.num
++;
        } 
else {
        
//insertion not at the rightmost key
        node.children[node.num+1= node.children[node.num];
        
for(int i = node.num; i>idx; i--){
            node.children[i] 
= node.children[i-1];
            node.keys[i] 
= node.keys[i-1];
        }
        node.children[idx] 
= result.left;
        node.children[idx
+1= result.right;
        node.keys[idx] 
= result.key;
        node.num
++;
        }
    }
    }

        
    
class LNode extends Node{
    
double[][] points= null;
        LNode next;
    
public LNode(){
        type 
= LEAF;
        keys 
= new double[max_leaf_keys];
        points 
= new double[max_leaf_points][dim];
        next 
= null;
    } 
    }

    
class INode extends Node{
    Node[] children 
= null;
    
public INode(){
        type 
= INNER;
        keys 
= new double[max_inner_keys];
        children 
= new Node[max_inner_pointers];
    }
    };
    
    
class InsertResult{
    
double key;
    Node left;
    Node right;
    
public InsertResult(){
    }
    
public InsertResult(double k, Node l, Node r){
        key 
= k;
        left 
= l;
        right 
= r;
    }
    }

}
posted on 2007-10-17 15:20 Fay 阅读(1526) 评论(5)  编辑  收藏


FeedBack:
# re: BPlusTree.java
2007-11-06 08:53 | zbhuang
你能把这个类的其他方法一起都贴出来吗?
Node/ResultNode/ResultList。。。  回复  更多评论
  
# re: BPlusTree.java
2008-04-26 16:06 | fgnhfgn
什么啊,全是错误,  回复  更多评论
  
# re: BPlusTree.java
2008-11-06 19:24 | lol
maybe

public class ResultNode {
public double k;
public ResultNode next;
public double[] p;

public ResultNode(double key, double[] point) {
this.k = key;
this.p = point;
}

public ResultNode() {

}
}

public class ResultList {
public ResultNode header;

public ResultList(ResultNode header) {
this.header = header;
}

public ResultList() {
}

public void inc() {
}
}

public class Node {

protected int type;
protected int num;
protected double[] keys;
}  回复  更多评论
  
# sampadi_83@yahoo.com
2013-01-24 02:36 | sepna
what is dim ? :s  回复  更多评论
  
# sampadi_83@yahoo.com
2013-01-24 02:36 | sepna
what is dim ?:s  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
<2013年1月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

常用链接

留言簿(2)

随笔档案

文章档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜