1. 程式人生 > >B+樹的Java實現

B+樹的Java實現

下面的B+樹演算法是在我學習了別人的程式碼之後經過修改完成的,主要在葉子節點上使用了二分查詢,另外在更新節點上也減少了部分的遞迴操作,還對節點的結構做了細微的修改(每個節點得孩子指標比關鍵碼多1,原來是孩子指標和關鍵碼一樣多,這也與B+樹的原本定義一致),應該說整個程式的邏輯比原來清晰了一些。在此特別感謝wguoyong作者!大家可以參考原博主的程式碼點選開啟連結

在寫B+樹的過程中,其實查詢和插入操作都不算很難,最難的是刪除操作,在做中間節點合併的時候需要特別注意關鍵字和孩子指標的更新,具體見程式碼。

    我對改進後的演算法與之前的做了比較,下面的測試我在Macbook air  OS X 10.9.2上做的測試:

階數10階

修改前

修改後

隨機插入100萬條資料

4100ms

2200ms

順序插入100萬條資料

1800ms

940ms

隨機查詢100萬次資料

2800ms

1350ms

順序查詢100萬次資料

730ms

250ms

隨機刪除100萬次資料

4600ms

1400ms

順序刪除100萬次資料

20­­00ms

450ms

 階數100階

修改前

修改後

隨機插入100萬條資料

8100ms

2100ms

順序插入100萬條資料

4300ms

700ms

隨機查詢100萬次資料

2000ms

1200ms

順序查詢100萬次資料

850ms

250ms

隨機刪除100萬次資料

8000ms

1500ms

順序刪除100萬次資料

4500ms

300ms

原始碼:

BplusTree.java

/**
 * B+樹的定義:
 * 
 * 1.任意非葉子結點最多有M個子節點;且M>2;M為B+樹的階數
 * 2.除根結點以外的非葉子結點至少有 (M+1)/2個子節點;
 * 3.根結點至少有2個子節點;
 * 4.除根節點外每個結點存放至少(M-1)/2和至多M-1個關鍵字;(至少1個關鍵字)
 * 5.非葉子結點的子樹指標比關鍵字多1個;
 * 6.非葉子節點的所有key按升序存放,假設節點的關鍵字分別為K[0], K[1] … K[M-2], 
 *  指向子女的指標分別為P[0], P[1]…P[M-1]。則有:
 *  P[0] < K[0] <= P[1] < K[1] …..< K[M-2] <= P[M-1]
 * 7.所有葉子結點位於同一層;
 * 8.為所有葉子結點增加一個鏈指標;
 * 9.所有關鍵字都在葉子結點出現
 */
/**
 * @author LeeJay 2014-04-03
 *
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class BplusTree <K extends Comparable<K>, V>{

	/** 根節點 */
	protected BplusNode<K, V> root;

	/** 階數,M值 */
	protected int order;

	/** 葉子節點的連結串列頭 */
	protected BplusNode<K, V> head;

	/** 樹高*/
	protected int height = 0;
	
	public BplusNode<K, V> getHead() {
		return head;
	}

	public void setHead(BplusNode<K, V> head) {
		this.head = head;
	}

	public BplusNode<K, V> getRoot() {
		return root;
	}

	public void setRoot(BplusNode<K, V> root) {
		this.root = root;
	}

	public int getOrder() {
		return order;
	}

	public void setOrder(int order) {
		this.order = order;
	}
	
	public void setHeight(int height) {
		this.height = height;
	}
	
	public int getHeight() {
		return height;
	}
	
	public V get(K key) {
		return root.get(key);
	}

	public V remove(K key) {
		return root.remove(key, this);
	}

	public void insertOrUpdate(K key, V value) {
		root.insertOrUpdate(key, value, this);

	}

	public BplusTree(int order) {
		if (order < 3) {
			System.out.print("order must be greater than 2");
			System.exit(0);
		}
		this.order = order;
		root = new BplusNode<K, V>(true, true);
		head = root;
	}

	// 測試
	public static void main(String[] args) {

		int size = 1000000;
		int order = 100;
//		 testRandomInsert(size, order);
//
//		 testOrderInsert(size, order);
//
//		 testRandomSearch(size, order);
//
//		 testOrderSearch(size, order);
//
//		 testRandomRemove(size, order);
//
//		 testOrderRemove(size, order);
	}

	private static void testOrderRemove(int size, int order) {
		BplusTree<Integer, Integer> tree = new BplusTree<Integer, Integer>(order);
		System.out.println("\nTest order remove " + size + " datas, of order:"
				+ order);
		System.out.println("Begin order insert...");
		for (int i = 0; i < size; i++) {
			tree.insertOrUpdate(i, i);
		}
		System.out.println("Begin order remove...");
		long current = System.currentTimeMillis();
		for (int j = 0; j < size; j++) {
			if (tree.remove(j) == null) {
				System.err.println("得不到資料:" + j);
				break;
			}
		}
		long duration = System.currentTimeMillis() - current;
		System.out.println("time elpsed for duration: " + duration);
		System.out.println(tree.getHeight());
	}

	private static void testRandomRemove(int size, int order) {
		BplusTree<Integer, Integer> tree = new BplusTree<Integer, Integer>(order);
		System.out.println("\nTest random remove " + size + " datas, of order:"
				+ order);
		Random random = new Random();
		boolean[] a = new boolean[size + 10];
		List<Integer> list = new ArrayList<Integer>();
		int randomNumber = 0;
		System.out.println("Begin random insert...");
		for (int i = 0; i < size; i++) {
			randomNumber = random.nextInt(size);
			a[randomNumber] = true;
			list.add(randomNumber);
			tree.insertOrUpdate(randomNumber, randomNumber);
		}
		System.out.println("Begin random remove...");
		long current = System.currentTimeMillis();
		for (int j = 0; j < size; j++) {
			randomNumber = list.get(j);
			if (a[randomNumber]) {
				if (tree.remove(randomNumber) == null) {
					System.err.println("得不到資料:" + randomNumber);
					break;
				} else {
					a[randomNumber] = false;
				}
			}
		}
		long duration = System.currentTimeMillis() - current;
		System.out.println("time elpsed for duration: " + duration);
		System.out.println(tree.getHeight());
	}

	private static void testOrderSearch(int size, int order) {
		BplusTree<Integer, Integer> tree = new BplusTree<Integer, Integer>(order);
		System.out.println("\nTest order search " + size + " datas, of order:"
				+ order);
		System.out.println("Begin order insert...");
		for (int i = 0; i < size; i++) {
			tree.insertOrUpdate(i, i);
		}
		System.out.println("Begin order search...");
		long current = System.currentTimeMillis();
		for (int j = 0; j < size; j++) {
			if (tree.get(j) == null) {
				System.err.println("得不到資料:" + j);
				break;
			}
		}
		long duration = System.currentTimeMillis() - current;
		System.out.println("time elpsed for duration: " + duration);
	}

	private static void testRandomSearch(int size, int order) {
		BplusTree<Integer, Integer> tree = new BplusTree<Integer, Integer>(order);
		System.out.println("\nTest random search " + size + " datas, of order:"
				+ order);
		Random random = new Random();
		boolean[] a = new boolean[size + 10];
		int randomNumber = 0;
		System.out.println("Begin random insert...");
		for (int i = 0; i < size; i++) {
			randomNumber = random.nextInt(size);
			a[randomNumber] = true;
			tree.insertOrUpdate(randomNumber, randomNumber);
		}
		System.out.println("Begin random search...");
		long current = System.currentTimeMillis();
		for (int j = 0; j < size; j++) {
			randomNumber = random.nextInt(size);
			if (a[randomNumber]) {
				if (tree.get(randomNumber) == null) {
					System.err.println("得不到資料:" + randomNumber);
					break;
				}
			}
		}
		long duration = System.currentTimeMillis() - current;
		System.out.println("time elpsed for duration: " + duration);
	}

	private static void testRandomInsert(int size, int order) {
		BplusTree<Integer, Integer> tree = new BplusTree<Integer, Integer>(order);
		System.out.println("\nTest random insert " + size + " datas, of order:"
				+ order);
		Random random = new Random();
		int randomNumber = 0;
		long current = System.currentTimeMillis();
		for (int i = 0; i < size; i++) {
			randomNumber = random.nextInt(size);
			tree.insertOrUpdate(randomNumber, randomNumber);
		}
		long duration = System.currentTimeMillis() - current;
		System.out.println("time elpsed for duration: " + duration);
		
		System.out.println(tree.getHeight());
	}

	private static void testOrderInsert(int size, int order) {
		BplusTree<Integer, Integer> tree = new BplusTree<Integer, Integer>(order);
		System.out.println("\nTest order insert " + size + " datas, of order:"
				+ order);
		long current = System.currentTimeMillis();
		for (int i = 0; i < size; i++) {
			tree.insertOrUpdate(i, i);
		}
		long duration = System.currentTimeMillis() - current;
		System.out.println("time elpsed for duration: " + duration);
	}
}
BplusNode.java
import java.util.AbstractMap.SimpleEntry; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Map.Entry; 

public class BplusNode <K extends Comparable<K>, V> { 
     
    /** 是否為葉子節點 */ 
    protected boolean isLeaf; 
     
    /** 是否為根節點*/ 
    protected boolean isRoot; 
 
    /** 父節點 */ 
    protected BplusNode<K, V> parent; 
     
    /** 葉節點的前節點*/ 
    protected BplusNode<K, V> previous; 
     
    /** 葉節點的後節點*/ 
    protected BplusNode<K, V> next;     
     
    /** 節點的關鍵字 */ 
    protected List<Entry<K, V>> entries; 
     
    /** 子節點 */ 
    protected List<BplusNode<K, V>> children; 
     
    public BplusNode(boolean isLeaf) { 
        this.isLeaf = isLeaf; 
        entries = new ArrayList<Entry<K, V>>(); 
         
        if (!isLeaf) { 
            children = new ArrayList<BplusNode<K, V>>(); 
        } 
    } 
 
    public BplusNode(boolean isLeaf, boolean isRoot) { 
        this(isLeaf); 
        this.isRoot = isRoot; 
    } 
     
    public V get(K key) { 
         
        //如果是葉子節點 
        if (isLeaf) { 
	        	int low = 0, high = entries.size() - 1, mid;
	            int comp ;
	    		while (low <= high) {
	    			mid = (low + high) / 2;
	    			comp = entries.get(mid).getKey().compareTo(key);
	    			if (comp == 0) {
	    				return entries.get(mid).getValue();
	    			} else if (comp < 0) {
	    				low = mid + 1;
	    			} else {
	    				high = mid - 1;
	    			}
	    		}
            //未找到所要查詢的物件 
            return null; 
        }
        //如果不是葉子節點 
        //如果key小於節點最左邊的key,沿第一個子節點繼續搜尋 
        if (key.compareTo(entries.get(0).getKey()) < 0) { 
            return children.get(0).get(key); 
        //如果key大於等於節點最右邊的key,沿最後一個子節點繼續搜尋 
        }else if (key.compareTo(entries.get(entries.size()-1).getKey()) >= 0) { 
            return children.get(children.size()-1).get(key); 
        //否則沿比key大的前一個子節點繼續搜尋 
        }else { 
            int low = 0, high = entries.size() - 1, mid= 0;
            int comp ;
        		while (low <= high) {
        			mid = (low + high) / 2;
        			comp = entries.get(mid).getKey().compareTo(key);
        			if (comp == 0) {
        				return children.get(mid+1).get(key); 
        			} else if (comp < 0) {
        				low = mid + 1;
        			} else {
        				high = mid - 1;
        			}
        		}
        		return children.get(low).get(key);
        } 
    } 
     
    public void insertOrUpdate(K key, V value, BplusTree<K,V> tree){ 
        //如果是葉子節點 
        if (isLeaf){ 
            //不需要分裂,直接插入或更新 
            if (contains(key) != -1 || entries.size() < tree.getOrder()){ 
                insertOrUpdate(key, value); 
                if(tree.getHeight() == 0){
                		tree.setHeight(1);
                }
                return ;
            }
            	//需要分裂 
            //分裂成左右兩個節點 
            BplusNode<K,V> left = new BplusNode<K,V>(true); 
            BplusNode<K,V> right = new BplusNode<K,V>(true); 
            //設定連結 
            if (previous != null){ 
                previous.next = left; 
                left.previous = previous ; 
            } 
            if (next != null) { 
                next.previous = right; 
                right.next = next; 
            } 
            if (previous == null){ 
                tree.setHead(left); 
            } 
 
            left.next = right; 
            right.previous = left; 
            previous = null; 
            next = null; 
             
            //複製原節點關鍵字到分裂出來的新節點 
            copy2Nodes(key, value, left, right, tree);
            
            //如果不是根節點 
            if (parent != null) { 
                //調整父子節點關係 
                int index = parent.children.indexOf(this); 
                parent.children.remove(this); 
                left.parent = parent; 
                right.parent = parent; 
                parent.children.add(index,left); 
                parent.children.add(index + 1, right); 
                parent.entries.add(index,right.entries.get(0));
                entries = null; //刪除當前節點的關鍵字資訊
                children = null; //刪除當前節點的孩子節點引用
                 
                //父節點插入或更新關鍵字 
                parent.updateInsert(tree); 
                parent = null; //刪除當前節點的父節點引用
            //如果是根節點     
            }else { 
                isRoot = false; 
                BplusNode<K,V> parent = new BplusNode<K,V> (false, true); 
                tree.setRoot(parent); 
                left.parent = parent; 
                right.parent = parent; 
                parent.children.add(left); 
                parent.children.add(right);
                parent.entries.add(right.entries.get(0));
                entries = null; 
                children = null; 
            } 
            return ;
         
        }
        //如果不是葉子節點
        //如果key小於等於節點最左邊的key,沿第一個子節點繼續搜尋 
        if (key.compareTo(entries.get(0).getKey()) < 0) { 
            children.get(0).insertOrUpdate(key, value, tree); 
        //如果key大於節點最右邊的key,沿最後一個子節點繼續搜尋 
        }else if (key.compareTo(entries.get(entries.size()-1).getKey()) >= 0) { 
            children.get(children.size()-1).insertOrUpdate(key, value, tree); 
        //否則沿比key大的前一個子節點繼續搜尋 
        }else { 
            int low = 0, high = entries.size() - 1, mid= 0;
            int comp ;
        		while (low <= high) {
        			mid = (low + high) / 2;
        			comp = entries.get(mid).getKey().compareTo(key);
        			if (comp == 0) {
        				children.get(mid+1).insertOrUpdate(key, value, tree);
        				break;
        			} else if (comp < 0) {
        				low = mid + 1;
        			} else {
        				high = mid - 1;
        			}
        		}
        		if(low>high){
        			children.get(low).insertOrUpdate(key, value, tree);
        		}
        } 
    }

	private void copy2Nodes(K key, V value, BplusNode<K,V> left,
			BplusNode<K,V> right,BplusTree<K,V> tree) {
		//左右兩個節點關鍵字長度 
        int leftSize = (tree.getOrder() + 1) / 2 + (tree.getOrder() + 1) % 2; 
		boolean b = false;//用於記錄新元素是否已經被插入
		for (int i = 0; i < entries.size(); i++) {
			if(leftSize !=0){
				leftSize --;
				if(!b&&entries.get(i).getKey().compareTo(key) > 0){
					left.entries.add(new SimpleEntry<K, V>(key, value));
					b = true;
					i--;
				}else {
					left.entries.add(entries.get(i));
				}
			}else {
				if(!b&&entries.get(i).getKey().compareTo(key) > 0){
					right.entries.add(new SimpleEntry<K, V>(key, value));
					b = true;
					i--;
				}else {
					right.entries.add(entries.get(i));
				}
			}
		}
		if(!b){
			right.entries.add(new SimpleEntry<K, V>(key, value));
		}
	} 
     
    /** 插入節點後中間節點的更新 */ 
    protected void updateInsert(BplusTree<K,V> tree){ 
         
        //如果子節點數超出階數,則需要分裂該節點    
        if (children.size() > tree.getOrder()) { 
            //分裂成左右兩個節點 
            BplusNode<K, V> left = new BplusNode<K, V>(false); 
            BplusNode<K, V> right = new BplusNode<K, V>(false); 
            //左右兩個節點子節點的長度 
            int leftSize = (tree.getOrder() + 1) / 2 + (tree.getOrder() + 1) % 2; 
            int rightSize = (tree.getOrder() + 1) / 2; 
            //複製子節點到分裂出來的新節點,並更新關鍵字 
            for (int i = 0; i < leftSize; i++){ 
                left.children.add(children.get(i)); 
                children.get(i).parent = left; 
            } 
            for (int i = 0; i < rightSize; i++){ 
                right.children.add(children.get(leftSize + i)); 
                children.get(leftSize + i).parent = right; 
            } 
            for (int i = 0; i < leftSize - 1; i++) {
            		left.entries.add(entries.get(i)); 
			}
            for (int i = 0; i < rightSize - 1; i++) {
            		right.entries.add(entries.get(leftSize + i)); 
			}
            
            //如果不是根節點 
            if (parent != null) { 
                //調整父子節點關係 
                int index = parent.children.indexOf(this); 
                parent.children.remove(this); 
                left.parent = parent; 
                right.parent = parent; 
                parent.children.add(index,left); 
                parent.children.add(index + 1, right); 
                parent.entries.add(index,entries.get(leftSize - 1));
                entries = null; 
                children = null; 
                 
                //父節點更新關鍵字 
                parent.updateInsert(tree); 
                parent = null; 
            //如果是根節點     
            }else { 
                isRoot = false; 
                BplusNode<K, V> parent = new BplusNode<K, V>(false, true); 
                tree.setRoot(parent);
                tree.setHeight(tree.getHeight() + 1);
                left.parent = parent; 
                right.parent = parent; 
                parent.children.add(left); 
                parent.children.add(right); 
                parent.entries.add(entries.get(leftSize - 1));
                entries = null; 
                children = null; 
            } 
        }
    } 
     
    /** 刪除節點後中間節點的更新*/ 
    protected void updateRemove(BplusTree<K,V> tree) { 
 
        // 如果子節點數小於M / 2或者小於2,則需要合併節點 
        if (children.size() < tree.getOrder() / 2 || children.size() < 2) { 
            if (isRoot) { 
                // 如果是根節點並且子節點數大於等於2,OK 
                if (children.size() >= 2) return; 
                // 否則與子節點合併 
                BplusNode<K, V> root = children.get(0); 
                tree.setRoot(root); 
                tree.setHeight(tree.getHeight() - 1);
                root.parent = null; 
                root.isRoot = true; 
                entries = null; 
                children = null; 
                return ;
            } 
            //計算前後節點  
            int currIdx = parent.children.indexOf(this); 
            int prevIdx = currIdx - 1; 
            int nextIdx = currIdx + 1; 
            BplusNode<K, V> previous = null, next = null; 
            if (prevIdx >= 0) { 
                previous = parent.children.get(prevIdx); 
            } 
            if (nextIdx < parent.children.size()) { 
                next = parent.children.get(nextIdx); 
            } 
             
            // 如果前節點子節點數大於M / 2並且大於2,則從其處借補 
            if (previous != null  
                    && previous.children.size() > tree.getOrder() / 2 
                    && previous.children.size() > 2) { 
                //前葉子節點末尾節點新增到首位 
                int idx = previous.children.size() - 1; 
                BplusNode<K, V> borrow = previous.children.get(idx); 
                previous.children.remove(idx); 
                borrow.parent = this; 
                children.add(0, borrow);
                int preIndex = parent.children.indexOf(previous);
                
                entries.add(0,parent.entries.get(preIndex));
                parent.entries.set(preIndex, previous.entries.remove(idx - 1));
                return ;
            }
            
            // 如果後節點子節點數大於M / 2並且大於2,則從其處借補
            if (next != null  
                    && next.children.size() > tree.getOrder() / 2 
                    && next.children.size() > 2) { 
                //後葉子節點首位新增到末尾 
                BplusNode<K, V> borrow = next.children.get(0); 
                next.children.remove(0); 
                borrow.parent = this; 
                children.add(borrow); 
                int preIndex = parent.children.indexOf(this);
                entries.add(parent.entries.get(preIndex));
                parent.entries.set(preIndex, next.entries.remove(0));
                return ;
            }
            
            // 同前面節點合併 
            if (previous != null  
                    && (previous.children.size() <= tree.getOrder() / 2 
                    || previous.children.size() <= 2)) { 
                for (int i = 0; i < children.size(); i++) {
                    previous.children.add(children.get(i)); 
				}
                for(int i = 0; i < previous.children.size();i++){
                		previous.children.get(i).parent = this;
                }
                int indexPre = parent.children.indexOf(previous);
                previous.entries.add(parent.entries.get(indexPre));
                for (int i = 0; i < entries.size(); i++) {
					previous.entries.add(entries.get(i));
				}
                children = previous.children;
                entries = previous.entries;
                
                //更新父節點的關鍵字列表
                parent.children.remove(previous);
                previous.parent = null;
                previous.children = null;
                previous.entries = null;
                parent.entries.remove(parent.children.indexOf(this));
                if((!parent.isRoot 
                			&& (parent.children.size() >= tree.getOrder() / 2
                			&& parent.children.size() >= 2))
                			||parent.isRoot && parent.children.size() >= 2){
	                 return ;
				}
                parent.updateRemove(tree); 
                return ;
            }   
            
	        // 同後面節點合併 
            if (next != null  
                    && (next.children.size() <= tree.getOrder() / 2 
                    || next.children.size() <= 2)) { 
                for (int i = 0; i < next.children.size(); i++) { 
                    BplusNode<K, V> child = next.children.get(i); 
                    children.add(child); 
                    child.parent = this; 
                } 
                int index = parent.children.indexOf(this);
                entries.add(parent.entries.get(index));
                for (int i = 0; i < next.entries.size(); i++) {
					entries.add(next.entries.get(i));
				}
                parent.children.remove(next);
                next.parent = null;
                next.children = null;
                next.entries = null;
                parent.entries.remove(parent.children.indexOf(this));
                if((!parent.isRoot && (parent.children.size() >= tree.getOrder() / 2
                			&& parent.children.size() >= 2))
                			||parent.isRoot && parent.children.size() >= 2){
	                 return ;
				}
                parent.updateRemove(tree); 
                return ;
            } 
        } 
    } 
     
    public V remove(K key, BplusTree<K,V> tree){ 
        //如果是葉子節點 
        if (isLeaf){ 
            //如果不包含該關鍵字,則直接返回 
            if (contains(key) == -1){ 
                return null; 
            } 
            //如果既是葉子節點又是根節點,直接刪除 
            if (isRoot) { 
            		if(entries.size() == 1){
            			tree.setHeight(0);
            		}
                return remove(key); 
            }
            //如果關鍵字數大於M / 2,直接刪除 
            if (entries.size() > tree.getOrder() / 2 && entries.size() > 2) { 
               return remove(key); 
            }
            //如果自身關鍵字數小於M / 2,並且前節點關鍵字數大於M / 2,則從其處借補 
            if (previous != null &&  
            		    previous.parent == parent
                    && previous.entries.size() > tree.getOrder() / 2 
                    && previous.entries.size() > 2 ) { 
                //新增到首位 
            		int size = previous.entries.size(); 
                entries.add(0, previous.entries.remove(size - 1)); 
                int index = parent.children.indexOf(previous);
                parent.entries.set(index, entries.get(0));
                return remove(key);
            }
            //如果自身關鍵字數小於M / 2,並且後節點關鍵字數大於M / 2,則從其處借補 
            if (next != null 
            				&& next.parent == parent 
                        && next.entries.size() > tree.getOrder() / 2 
                        && next.entries.size() > 2) { 
                entries.add(next.entries.remove(0)); 
                int index = parent.children.indexOf(this);
                parent.entries.set(index, next.entries.get(0));
                return remove(key);
            }
            	
            //同前面節點合併 
            if (previous != null	 
            			&& previous.parent == parent 
                    && (previous.entries.size() <= tree.getOrder() / 2 
                    || previous.entries.size() <= 2)) { 
            		V returnValue =  remove(key);
                for (int i = 0; i < entries.size(); i++) { 
                    //將當前節點的關鍵字新增到前節點的末尾
                		previous.entries.add(entries.get(i));
                } 
                entries = previous.entries;
                parent.children.remove(previous);
                previous.parent = null; 
                previous.entries = null;
                //更新連結串列 
                if (previous.previous != null) { 
                    BplusNode<K, V> temp = previous; 
                    temp.previous.next = this; 
                    previous = temp.previous; 
                    temp.previous = null; 
                    temp.next = null;                          
                }else { 
                    tree.setHead(this); 
                    previous.next = null; 
                    previous = null; 
                }
                parent.entries.remove(parent.children.indexOf(this));
                if((!parent.isRoot && (parent.children.size() >= tree.getOrder() / 2
                			&& parent.children.size() >= 2))
                			||parent.isRoot && parent.children.size() >= 2){
                	 	return returnValue;
                }
                parent.updateRemove(tree);
                return returnValue;
            }
            //同後面節點合併
            if(next != null  
            			&& next.parent == parent
	                && (next.entries.size() <= tree.getOrder() / 2 
	                || next.entries.size() <= 2)) { 
            		V returnValue = remove(key); 
	            for (int i = 0; i < next.entries.size(); i++) { 
	                //從首位開始新增到末尾 
	                entries.add(next.entries.get(i)); 
	            } 
	            next.parent = null; 
	            next.entries = null;
	            parent.children.remove(next); 
	            //更新連結串列 
	            if (next.next != null) { 
	                BplusNode<K, V> temp = next; 
	                temp.next.previous = this; 
	                next = temp.next; 
	                temp.previous = null; 
	                temp.next = null; 
	            }else { 
	                next.previous = null; 
	                next = null; 
	            } 
	            //更新父節點的關鍵字列表
	            parent.entries.remove(parent.children.indexOf(this));
                if((!parent.isRoot && (parent.children.size() >= tree.getOrder() / 2
                			&& parent.children.size() >= 2))
                			||parent.isRoot && parent.children.size() >= 2){
	                 return returnValue;
				}
	            parent.updateRemove(tree);
                return returnValue;
	        } 
        }
        /*如果不是葉子節點*/
        
        //如果key小於等於節點最左邊的key,沿第一個子節點繼續搜尋 
        if (key.compareTo(entries.get(0).getKey()) < 0) { 
            return children.get(0).remove(key, tree); 
        //如果key大於節點最右邊的key,沿最後一個子節點繼續搜尋 
        }else if (key.compareTo(entries.get(entries.size()-1).getKey()) >= 0) { 
            return children.get(children.size()-1).remove(key, tree); 
        //否則沿比key大的前一個子節點繼續搜尋 
        }else { 
            int low = 0, high = entries.size() - 1, mid= 0;
            int comp ;
        		while (low <= high) {
        			mid = (low + high) / 2;
        			comp = entries.get(mid).getKey().compareTo(key);
        			if (comp == 0) {
        				return children.get(mid + 1).remove(key, tree); 
        			} else if (comp < 0) {
        				low = mid + 1;
        			} else {
        				high = mid - 1;
        			}
        		}
        		return children.get(low).remove(key, tree); 
        } 
    } 
     
    /** 判斷當前節點是否包含該關鍵字*/ 
    protected int contains(K key) { 
    		int low = 0, high = entries.size() - 1, mid;
        int comp ;
		while (low <= high) {
			mid = (low + high) / 2;
			comp = entries.get(mid).getKey().compareTo(key);
			if (comp == 0) {
				return mid;
			} else if (comp < 0) {
				low = mid + 1;
			} else {
				high = mid - 1;
			}
		}
		return -1;
    } 
     
    /** 插入到當前節點的關鍵字中*/ 
    protected void insertOrUpdate(K key, V value){ 
    		//二叉查詢,插入
        int low = 0, high = entries.size() - 1, mid;
        int comp ;
		while (low <= high) {
			mid = (low + high) / 2;
			comp = entries.get(mid).getKey().compareTo(key);
			if (comp == 0) {
				entries.get(mid).setValue(value); 
				break;
			} else if (comp < 0) {
				low = mid + 1;
			} else {
				high = mid - 1;
			}
		}
		if(low>high){
			entries.add(low, new SimpleEntry<K, V>(key, value));
		}
    } 
     
    /** 刪除節點*/ 
    protected V remove(K key){ 
    		int low = 0,high = entries.size() -1,mid;
    		int comp;
    		while(low<= high){
    			mid  = (low+high)/2;
    			comp = entries.get(mid).getKey().compareTo(key);
    			if(comp == 0){
    				return entries.remove(mid).getValue();
    			}else if(comp < 0){
				low = mid + 1;
			}else {
				high = mid - 1;
			}
    		}
        return null;
    }   
    public String toString(){ 
        StringBuilder sb = new StringBuilder(); 
        sb.append("isRoot: "); 
        sb.append(isRoot); 
        sb.append(", "); 
        sb.append("isLeaf: "); 
        sb.append(isLeaf); 
        sb.append(", "); 
        sb.append("keys: "); 
        for (Entry<K,V> entry : entries){ 
            sb.append(entry.getKey()); 
            sb.append(", "); 
        } 
        sb.append(", "); 
        return sb.toString(); 
         
    } 
 
}