java-實現B+樹


參考:https://www.cnblogs.com/jing99/p/11741685.html

https://www.cnblogs.com/ll9507/p/11616417.html

 

B+樹---一種多路平衡查找樹

①與二叉樹,紅黑樹等相比,最大的不同就是一個節點可以有多個子節點(有子節點列表)

平衡二叉樹,每個節點分兩路,大於該節點,小於該節點。B+樹每個節點有n個子節點,分n+1路即多路查詢。

*                X1| X2 | X3
* <X1 | >=X1 <x2 | >=x2 <x3| >=x3

②B+樹的數據都存分在葉子節點,且所有的葉子節點維持一個鏈表可以順序遍歷,非葉子節點只存key,不存value;
③M階B+樹,表示一個節點最多有M個節點(M條查找路),由①可知維持M條路只需要非葉子節點記錄M-1個KEY;



B+樹的平衡過程就是節點總的“路數”,即子節點數,要符合規定超出范圍要添加新的節點,低於范圍要與其他節點合並。

添加節點:
3階B+樹添加節點過程:①當添加第4個節點6時,節點已有三個值,需要分成兩個節點,並生成父節點(非葉子節點,只保存key)1,3<6 6,22>=6

②繼續添加,當又有節點滿了,分出新節點時,一樣將key添加到父節點

③父節點,key達到3個,子節點列表已經4個了。后繼續向分節點,並生成父節點。



刪除節點:
①若是根節點(只有一層),直接刪
②若刪后,節點子節點>=M/2,直接刪。-更新調整父節點Key
③當節點的節點子節點樹等於M/2時(最低為2)即在刪除就違反平衡規定了,若前后節點子節點數>M/2,則向旁邊節點“借一個節點”,再刪除-調節父節點Key
②若前后節點都不富余節點,則該節點刪除后,與旁邊節點合並。-條件子節點間連接(指針)關系


全部代碼
import javax.swing.*;
import java.util.*;

/**
 * B+樹是一種多路平衡查找樹
 *
 * 查找
 * 插入//key不重復
 * 刪除
 * 打印
 */

public class BPlusTree {
    public class Node{
        private boolean isLeaf;
        //節點的子節點列表-非葉子節點肯定有子節點
        private List<Node> children;
        //非葉子節點鍵表
        private List<Integer> keyList;
        //節點鍵值對
        private List<KeyAndValue> keyAndValues;
        //葉子節點的后節點
        private Node nextNode=null;
        //葉子節點的前節點
        private Node preNode=null;
        //節點的父節點
        private Node fatherNode=null;

        //創建新葉子節點
        public Node(boolean a){
            if(a){
                this.keyAndValues=new LinkedList<>();
                this.isLeaf=true;
            }
            else {
                this.children=new LinkedList<>();
                this.keyList=new LinkedList<>();
                this.isLeaf=false;
            }
        }
        //-非葉子節點肯定有子節點
        public boolean isLeaf(){
            return children==null;
        }


    }
    public static class KeyAndValue{
        private int key;
        private Object value;
        private void setValue(Object value){
            this.value=value;
        }
        private KeyAndValue(int key,Object value){
            this.key=key;
            this.value=value;
        }
    }
    //排序
    public class TreeNodeComparator implements Comparator<Integer> {

        @Override
        public int compare(Integer o1, Integer o2) {
            return o1-o2;
        }
    }

    //成員變量
    private int order;
    private Node root=null;
    private Node head=null;
    public BPlusTree(int order){
        if(order<3){
            System.out.println("order must >2");
            System.exit(0);
        }
        this.order=order;
    }

    //查找
    private Object search(int key,Node root){
        if(root==null){
            System.out.println("樹空,無查找");
            return null;
        }
        //如果是葉子節點
        if(root.isLeaf()){
            //二分查找
            int low=0,high=root.keyAndValues.size()-1,mid;
            int comp;
            while(low<=high){
                mid=(low+high)/2;
                comp=root.keyAndValues.get(mid).key-key;
                if(comp==0)
                    return root.keyAndValues.get(mid).value;
                else if(comp<0)
                    low=mid+1;
                else
                    high=mid-1;
            }
            //未找到對象
            System.out.println("鍵不在樹中,未找到");
            return null;
        }
        /**
         *                X1| X2 | X3
         *     <X1 |  >=X1 <x2 |  >=x2  <x3| >=x3
         *     */
        //非葉子節點
        //如果key小於最左邊的key,沿着第一個子節點繼續搜索
        if(key-root.keyList.get(0)<0)
            return search(key,root.children.get(0));
        //如果key大於等於最右邊ke'y,沿着最后一個子節點繼續搜索
        else if(key-root.keyList.get(root.keyList.size()-1)>=0){
            //System.out.println(root.keyList);
            return search(key,root.children.get(root.children.size()-1));
        }
        //否則沿比key大的前一個子節點繼續搜索
        else{
            //二分查找,
            int low=0,high=root.keyList.size()-1,mid=0;
            int comp;
            while(low<=high){
                mid=(low+high)/2;
                comp=root.keyList.get(mid)-key;
                if(comp==0)
                    return search(key,root.children.get(mid+1));
                else if(comp<0)
                    low=mid+1;
                else
                    high=mid-1;
            }
            return search(key,root.children.get(low));
        }

    }

    /**
     * 插入
     * 鍵在樹中-更新value,不在-插入
     *非葉子節點子節點列表長度>order,需要分裂成兩個節點(父節點增加索引)--回溯平衡
     */

    //節點中是否存在key鍵-存在返回下標,不存在返回-1
    private Integer isExist(Node root,int key){
        if(root==null){
            System.out.println("樹空,不存在");
            return -1;
        }
        //二分法
        int low=0,high=root.keyAndValues.size()-1,mid;
        int comp;
        while(low<=high){
            mid=(low+high)/2;
            comp=root.keyAndValues.get(mid).key-key;
            if(comp==0)
                return mid;
            else if(comp<0)
                low=mid+1;
            else
                high=mid-1;
        }
        return -1;
    }
    //在不滿的葉子節點插入kv---不存在相等key情況
    private void inseartInleaf(Node root,KeyAndValue kv){
        //二分查找,插入
        int low=0,high=root.keyAndValues.size()-1,mid;
        int comp;
        while(low<=high){
            mid=(low+high)/2;
            comp=root.keyAndValues.get(mid).key-kv.key;
            if(comp>0)
                high=mid-1;
            else
                low=mid+1;
        }
        root.keyAndValues.add(low,kv);
    }
    //插入--key不重復,key重復則更新value
    private void inseart(Node root,KeyAndValue kv){
        //樹空,直接插入,頭,根節點
        if(root==null){
            Node newNode=new Node(true);
            this.root=newNode;
            this.head=newNode;
            this.root.keyAndValues.add(kv);
            return;
        }
        //如果是葉子節點
        if(root.isLeaf()){
            //System.out.println("219- 葉子加節點添加");
            int index=isExist(root,kv.key);
            if(index!=-1){
                root.keyAndValues.get(index).setValue(kv.value);
                return;
            }
            //不在節點中,且節點有位置,插入
            if(root.keyAndValues.size()<order){
                //System.out.println("227-不在節點中,且節點有位置,插入");
                inseartInleaf(root,kv);
                return;
            }
            //不在節點中且節點已滿,先插入進去,再分裂為兩個節點
            //左邊的繼承整除2的一半(比如3個繼承(3+1)/2=2個,4個繼承(4+1)/2=2個)
            //System.out.println("231-不在節點中且節點已滿,先插入進去,再分裂為兩個節點");
            inseartInleaf(root,kv);
            int leftsize=root.keyAndValues.size()/2;
            Node left=new Node(true);
            Node right=new Node(true);
            for(int i=0;i<leftsize;i++){
                left.keyAndValues.add(root.keyAndValues.get(i));
            }
            for(int i=0;i<leftsize;i++){
                right.keyAndValues.add(root.keyAndValues.get(leftsize+i));
            }
            //調整指針(連接);
            if(root.preNode==null){
                //System.out.println("246-");
                this.head=left;
            }
            else{
                left.preNode=root.preNode;
                root.preNode.nextNode=left;
            }
            if(root.nextNode!=null){
                root.nextNode.preNode=right;
                right.nextNode=root.nextNode;
            }
            left.nextNode=right;
            right.preNode=left;
            root.preNode=null;
            root.nextNode=null;
            //調整父節點;
            //如果不是根節點,//找到父節點中root的位置x,刪除,分別在x上插入,right,left
            if(root.fatherNode!=null){
                //System.out.println("262-如果不是根節點,//找到父節點中root的位置x,刪除,分別在x上插入,right,left");
                //調整子節點列表
                int index2=root.fatherNode.children.indexOf(root);
                left.fatherNode=root.fatherNode;
                right.fatherNode=root.fatherNode;
                root.fatherNode.children.remove(index2);
                //System.out.println("274-"+index2);
                root.fatherNode.children.add(index2,right);
                root.fatherNode.children.add(index2,left);
                //調整鍵表
                int index3=0;
                if(root.isLeaf()) {
                    root.fatherNode.keyList.add(right.keyAndValues.get(0).key);
                    Collections.sort(root.fatherNode.keyList,new TreeNodeComparator());
                }else{
                    index3=root.fatherNode.keyList.indexOf(root.keyList.get(0));
                    if(index3>=0){
                        root.fatherNode.keyList.remove(index3);
                        root.fatherNode.keyList.add(index3,right.keyList.get(0));
                        root.fatherNode.keyList.add(index3,left.keyList.get(0));
                        Collections.sort(root.fatherNode.keyList,new TreeNodeComparator());
                    }
                    else{
                        root.fatherNode.keyList.add(right.keyList.get(0));
                        Collections.sort(root.fatherNode.keyList,new TreeNodeComparator());
                        //root.fatherNode.keyList.add(left.keyList.get(0));
                    }
                }
                //System.out.println("276-"+root.fatherNode.keyList);
                //System.out.println("277-"+root.fatherNode.children.size());
                //向上回溯,調整父節點
                updateInseart(root.fatherNode);
                root.fatherNode=null;
            }
            else{
                //System.out.println("287-調節父節點指針,父節點為根");
                Node newNode=new Node(false);
                this.root=newNode;
                left.fatherNode=newNode;
                right.fatherNode=newNode;
                newNode.children.add(left);
                newNode.children.add(right);
                if(right.isLeaf()){
                    newNode.keyList.add(right.keyAndValues.get(0).key);
                    Collections.sort(newNode.keyList,new TreeNodeComparator());
                }
                else{
                    newNode.keyList.add(right.keyList.get(0));
                    Collections.sort(newNode.keyList,new TreeNodeComparator());
                }
                //System.out.println("308-"+newNode.keyList);
                //System.out.println(newNode.keyList);
                //System.out.println(newNode.children);
                if(root.isLeaf())
                    root.keyAndValues=null;
            }
            return;
        }
        //不是葉子節點,遍歷找到葉子節點
        //非葉子節點
        //如果key小於最左邊的key,沿着第一個子節點繼續搜索
        if(kv.key-root.keyList.get(0)<0)
            inseart(root.children.get(0),kv);
            //如果key大於等於最右邊ke'y,沿着最后一個子節點繼續搜索
        else if(kv.key-root.keyList.get(root.keyList.size()-1)>=0){
            //System.out.println("303-"+root.children);
            //System.out.println("304-"+root.children.get(root.children.size()-1).keyAndValues.size());
            inseart(root.children.get(root.children.size()-1),kv);

        }
            //否則沿比key大的前一個子節點繼續搜索
        else{
            //二分查找,
            int low=0,high=root.keyList.size()-1,mid=0;
            int comp;
            while(low<=high){
                mid=(low+high)/2;
                comp=root.keyList.get(mid)-kv.key;
                if(comp==0)
                    inseart(root.children.get(mid+1),kv);
                else if(comp<0)
                    low=mid+1;
                else
                    high=mid-1;
            }
            inseart(root.children.get(low),kv);
        }
    }

    //插入節點后回溯更新父節點
    private void updateInseart(Node root){
        //System.out.println("329父節點子節點鏈表長:"+root.children.size()+" order: "+order);
        if(root.children.size()>order){
            int rightsize=root.children.size()/2+root.children.size()%2;
            int leftsize=root.children.size()/2;
            //System.out.println("335-leftsize:"+leftsize);
            Node left=new Node(false);
            Node right=new Node(false);
            for(int i=0;i<leftsize;i++){
                left.children.add(root.children.get(i));
                root.children.get(i).fatherNode=left;
            }
            for(int i=0;i<rightsize;i++){
                right.children.add(root.children.get(leftsize+i));
                root.children.get(leftsize+i).fatherNode=right;
            }
            //System.out.println("346-"+right.children.size());

            for(int i=0;i<leftsize-1;i++){
                left.keyList.add(root.keyList.get(i));
            }
            for(int i=0;i<rightsize-1;i++){
                right.keyList.add(root.keyList.get(leftsize+i));
            }
            //System.out.println("372-"+left.keyList);
            //System.out.println("373-"+right.keyList);
            //System.out.println("374-"+left.children.get(0).fatherNode);
            //System.out.println("375-"+right.preNode.keyList);
            //System.out.print("377-");
            //System.out.println(root.fatherNode!=null);
            //如果不是根節點
            if(root.fatherNode!=null){
                //調整子節點列表
                int index2=root.fatherNode.children.indexOf(root);
                left.fatherNode=root.fatherNode;
                right.fatherNode=root.fatherNode;
                root.fatherNode.children.remove(index2);
                root.fatherNode.children.add(index2,right);
                root.fatherNode.children.add(index2,left);
                //調整鍵表
                int index3=0;
                if(root.isLeaf()) {
                    root.fatherNode.keyList.add(right.keyAndValues.get(0).key);
                    Collections.sort(root.fatherNode.keyList,new TreeNodeComparator());
                }else{
                    index3=root.fatherNode.keyList.indexOf(root.keyList.get(0));
//                    System.out.println("413-index3 "+index3);
//                    System.out.println("414-index3 "+root.fatherNode.keyList);
//                    System.out.println("415-index3 "+root.keyList.get(0));
                    if(index3>=0){
                        root.fatherNode.keyList.remove(index3);
                        root.fatherNode.keyList.add(index3,right.keyList.get(0));
                        root.fatherNode.keyList.add(index3,left.keyList.get(0));
                        Collections.sort(root.fatherNode.keyList,new TreeNodeComparator());
                    }
                    else{
                        root.fatherNode.keyList.add(right.keyList.get(0));
                        Collections.sort(root.fatherNode.keyList,new TreeNodeComparator());
                        //root.fatherNode.keyList.add(left.keyList.get(0));
                    }

                }
                //System.out.println("393-"+root.keyList);
                //System.out.println("394-index3 "+index3);
                //root.fatherNode.keyList.add(index3,root.keyList.get(leftsize-1));
                //System.out.println("388-"+root.fatherNode.keyList);
                //向上回溯,調整父節點
                updateInseart(root.fatherNode);
                root.fatherNode=null;
            }else{
                Node newNode=new Node(false);
                this.root=newNode;
                left.fatherNode=newNode;
                right.fatherNode=newNode;
                newNode.children.add(left);
                newNode.children.add(right);
                newNode.keyList.add(root.keyList.get(leftsize-1));
                Collections.sort(newNode.keyList,new TreeNodeComparator());
                root.keyAndValues=null;
                //root.fatherNode=null;
            }

        }

    }

    /**
     * 刪除
     * 當非葉子節點子節點列表<order/2或者<2,需要合並節點
     */
    public void delete(Node root,int key){
        //鍵不在樹中
        Object result=this.search(key,this.root);
        if(result==null){
            System.out.println("鍵不在樹中,無法刪除");
            return;
        }
        //鍵在樹中
        //如果是葉子節點
        if(root.isLeaf()) {
            int index = isExist(root, key);
            //①如果是葉子節點,且是根節點-直接刪
            if (root.fatherNode == null) {
                root.keyAndValues.remove(index);
                return;
            }
            //②如果刪后不需要合並節點,直接刪
            if (root.keyAndValues.size() > order / 2 && root.keyAndValues.size() > 2) {
                root.keyAndValues.remove(index);
                return;
            }
            //③如果自身關鍵字數數=order/2(小於order/2的情況應該不存在,刪除后就不平衡了)且,
            // 前一個節點關鍵字數>2,則從前面借一個在刪
            if(root.preNode!=null&&root.preNode.fatherNode==root.fatherNode&&root.preNode.keyAndValues.size()>order/2&&root.preNode.keyAndValues.size()>2){
                int index1=root.preNode.keyAndValues.size();
                root.keyAndValues.add(0,root.preNode.keyAndValues.remove(index1-1));
                int index2=root.fatherNode.children.indexOf(root.preNode);
                root.fatherNode.keyList.set(index2,root.keyAndValues.get(0).key);
                //新增了一個節點index+1
                root.keyAndValues.remove(index+1);
                return;
            }
            //④如果自身關鍵字數數=order/2(小於order/2的情況應該不存在,刪除后就不平衡了)且,
            // 后一個節點關鍵字數>2,則從后面借一個在刪
            if(root.nextNode!=null&&root.nextNode.fatherNode==root.fatherNode&&root.nextNode.keyAndValues.size()>order/2&&root.nextNode.keyAndValues.size()>2){
                root.keyAndValues.add(root.nextNode.keyAndValues.remove(0));
                int index3=root.fatherNode.children.indexOf(root);
                root.fatherNode.keyList.set(index3,root.nextNode.keyAndValues.get(0).key);
                //尾部添加,index不變
                root.keyAndValues.remove(index);
                return;
            }

            //⑤上述不成立即借不到節點,只能自己合並給別人了
            //前節點非空,與前節點合並
            if(root.preNode!=null&&root.preNode.fatherNode==root.fatherNode
                    &&(root.preNode.keyAndValues.size()<=order/2||root.preNode.keyAndValues.size()<=2)){
                root.keyAndValues.remove(index);
                for(int i=0;i<root.keyAndValues.size();i++){
                    root.preNode.keyAndValues.add(root.keyAndValues.get(i));
                }
                root.keyAndValues=root.preNode.keyAndValues;
                root.fatherNode.children.remove(root.preNode);
                root.preNode.fatherNode=null;
                root.preNode.keyAndValues=null;
                //更新鏈表
                if(root.preNode.preNode!=null){
                    Node p=root.preNode;
                    p.preNode.nextNode=root;
                    root.preNode=p.preNode;
                    p.preNode=null;
                    p.nextNode=null;
                }else{
                    this.head=root;
                    root.preNode.nextNode=null;
                    root.preNode=null;
                }
                //如果父節點符合平衡,退出
                root.fatherNode.keyList.remove(root.fatherNode.children.indexOf(root));
                if((root.fatherNode.fatherNode!=null&&(root.fatherNode.children.size()>=order/2&&root.fatherNode.children.size()>=2))||root.fatherNode.fatherNode==null&&root.fatherNode.children.size()>=2){
                    return;
                }
                //回溯更新父節點
                updateDelete(root.fatherNode);
                return;
            }

            //⑥到這一步說明前階段空了
            //同后節點合並。
            if(root.nextNode!=null&&root.nextNode.fatherNode==root.fatherNode&&(root.nextNode.keyAndValues.size()<=order/2||root.nextNode.keyAndValues.size()<=2)){
                root.keyAndValues.remove(index);
                for(int i=0;i<root.nextNode.keyAndValues.size();i++){
                    root.keyAndValues.add(root.keyAndValues.get(i));
                }
                root.nextNode.fatherNode=null;
                root.nextNode.keyAndValues=null;
                root.fatherNode.children.remove(root.nextNode);
                //更新鏈表
                if(root.nextNode.nextNode!=null){
                    Node p=root.nextNode;
                    p.nextNode.preNode=root;
                    root.nextNode=p.nextNode;
                    p.preNode=null;
                    p.nextNode=null;
                }else{
                    root.preNode=null;
                    root.nextNode=null;
                }
                //更新父節點鏈表
                root.fatherNode.keyList.remove(root.fatherNode.children.indexOf(root));
                if((root.fatherNode.fatherNode!=null&&(root.fatherNode.children.size()>=order/2&&root.fatherNode.children.size()>=2))||root.fatherNode.fatherNode==null&&root.fatherNode.children.size()>=2){
                    return;
                }
                updateDelete(root.fatherNode);
                return;
            }

        }
        //如果不是葉子節點,就遍歷到葉子節點
        //非葉子節點
        //如果key小於最左邊的key,沿着第一個子節點繼續搜索
        if(key-root.keyList.get(0)<0)
            delete(root.children.get(0),key);
            //如果key大於等於最右邊ke'y,沿着最后一個子節點繼續搜索
        else if(key-root.keyList.get(root.keyList.size()-1)>=0){
            //System.out.println(root.keyList);
            delete(root.children.get(root.children.size()-1),key);
        }
        //否則沿比key大的前一個子節點繼續搜索
        else{
            //二分查找,
            int low=0,high=root.keyList.size()-1,mid=0;
            int comp;
            while(low<=high){
                mid=(low+high)/2;
                comp=root.keyList.get(mid)-key;
                if(comp==0)
                    delete(root.children.get(mid+1),key);
                else if(comp<0)
                    low=mid+1;
                else
                    high=mid-1;
            }
            delete(root.children.get(low),key);
        }

    }

    //刪除后回溯更新-平衡
    private void updateDelete(Node root){
        //如果節點<order/2或者<小於2,
        if(root.children.size()<order/2||root.children.size()<2){
            if(root.fatherNode==null){
                if(root.children.size()>2)
                    return;
                Node p=root.children.get(0);
                this.root=p;
                p.fatherNode=null;
                root.keyList=null;
                root.keyList=null;
                return;
            }
            //計算前后節點
            int currIdx=root.fatherNode.children.indexOf(root);
            int preIdx=currIdx-1;
            int nextIdx=currIdx+1;
            Node preNode=null,nextNode=null;
            if(preIdx>=0)
                preNode=root.fatherNode.children.get(preIdx);
            if(nextIdx<root.fatherNode.children.size())
                nextNode=root.fatherNode.children.get(nextIdx);


            // 前一個節點關鍵字數>2,則從前面借一個在刪
            if(preNode!=null&&preNode.children.size()>order/2&&preNode.children.size()>2){
                int index1=preNode.children.size()-1;
                Node borrow=preNode.children.get(index1);
                preNode.children.remove(index1);
                borrow.fatherNode=root;
                root.children.add(0,borrow);

                int index2=root.fatherNode.children.indexOf(preNode);
                root.keyList.add(0,root.fatherNode.keyList.get(index2));
                root.fatherNode.keyList.set(index2,preNode.keyList.remove(index1-1));
                return;
            }
            //④如果自身關鍵字數數=order/2(小於order/2的情況應該不存在,刪除后就不平衡了)且,
            // 后一個節點關鍵字數>2,則從后面借一個在刪
            if(nextNode!=null&&nextNode.children.size()>order/2&&nextNode.children.size()>2){
                Node borrow=nextNode.children.get(0);
                nextNode.children.remove(0);
                borrow.fatherNode=root;
                root.children.add(borrow);
                int index3=root.fatherNode.children.indexOf(root);
                root.keyList.add(root.fatherNode.keyList.get(index3));
                root.fatherNode.keyList.set(index3,nextNode.keyList.remove(0));
                return;
            }

            //⑤上述不成立即借不到節點,只能自己合並給別人了
            //前節點非空,與前節點合並
            if(preNode!=null&&(preNode.children.size()<=order/2||preNode.children.size()<=2)){
                for(int i=0;i<root.children.size();i++){
                    preNode.children.add(root.children.get(i));
                }
                for(int i=0;i<preNode.children.size();i++){
                    preNode.children.get(i).fatherNode=root;
                }
                int indexPre=root.fatherNode.children.indexOf(preNode);
                preNode.keyList.add(root.fatherNode.keyList.get(indexPre));
                for(int i=0;i<root.keyList.size();i++){
                    preNode.keyList.add(root.keyList.get(i));
                }
                root.children=preNode.children;
                root.keyList=preNode.keyList;

                root.fatherNode.children.remove(preNode);
                preNode.fatherNode=null;
                preNode.keyList=null;
                preNode.children=null;
                root.fatherNode.keyList.remove(root.fatherNode.children.indexOf(root));
                //更新鏈表
                if((root.fatherNode.fatherNode!=null&&(root.fatherNode.children.size()>=order/2&&root.fatherNode.children.size()>=2))
                ||root.fatherNode.fatherNode==null&&root.fatherNode.children.size()>=2){
                    return;
                }
                //回溯更新父節點
                updateDelete(root.fatherNode);
                return;
            }

            //⑥到這一步說明前階段空了
            //同后節點合並。
            if(nextNode!=null&&(nextNode.children.size()<=order/2||nextNode.children.size()<=2)){
                for(int i=0;i<nextNode.children.size();i++){
                    Node child=nextNode.children.get(i);
                    root.children.add(child);
                    child.fatherNode=root;
                }
                int index=root.fatherNode.children.indexOf(root);
                root.keyList.add(root.fatherNode.keyList.get(index));
                for(int i=0;i<nextNode.keyList.size();i++){
                    root.keyList.add(nextNode.keyList.get(i));
                }

                root.fatherNode.children.remove(nextNode);
                nextNode.fatherNode=null;
                nextNode.keyList=null;
                nextNode.children=null;
                root.fatherNode.keyList.remove(root.fatherNode.children.indexOf(root));
                //更新鏈表
                if((root.fatherNode.fatherNode!=null&&(root.fatherNode.children.size()>=order/2&&root.fatherNode.children.size()>=2))
                        ||root.fatherNode.fatherNode==null&&root.fatherNode.children.size()>=2){
                    return;
                }
                updateDelete(root.fatherNode);
                return;
            }
        }
    }

    /**
     * 打印
     */
    private int height(Node root){
        if(root==null)
            return 0;
        if(root.isLeaf())
            return 1;
        int height=1;
        do{
            root=root.children.get(0);
            height++;
        }while(!root.isLeaf());
        return height;
    }
    private void printTree(Node root,Node head){
        int H=height(root);
        int h=H;
        //System.out.println("樹高:"+H);
        if(H==0){
            System.out.println("樹空,無打印");
            return;
        }
        else{
            //System.out.println("446-H=="+H);
            System.out.println("打印樹:");
            Queue<Node> queue=new LinkedList<>();
            queue.add(root);
            //記錄每層孩子個數
            int len=1;
            while(h>0){
                int length=0;
                for(int i=0;i<len;i++){
                    Node curroot=queue.poll();
                    if(curroot.isLeaf()){
                        for(int j=0;j<curroot.keyAndValues.size();j++){
                            System.out.print(curroot.keyAndValues.get(j).key+",");
                        }
                    }else{
                        //System.out.println("根節點鍵表長 "+curroot.children.size());
                        //System.out.println("462-"+curroot.keyList.size());
                        for(int j=0;j<curroot.keyList.size();j++){
                            System.out.print(curroot.keyList.get(j)+",");
                        }
                        for(int j=0;j<curroot.children.size();j++){
                            queue.add(curroot.children.get(j));
                            length++;
                        }
                    }
                    System.out.print("|");
                }
                System.out.println();
                len=length;
                h--;
            }
        }
        //輸出葉子節點value
//        Node h1=head;
//        while(h1!=null){
//            for(int i=0;i<h1.keyAndValues.size();i++)
//                System.out.print(h1.keyAndValues.get(i).value+"-");
//            h1=h1.nextNode;
//            System.out.print("|");
//        }
//        System.out.print("\n");
    }


    public static void main(String args[]) {
        KeyAndValue keyAndValue1 = new KeyAndValue(1,"1");
        KeyAndValue keyAndValue2 = new KeyAndValue(2,"1");
        KeyAndValue keyAndValue3 = new KeyAndValue(3,"2");
        KeyAndValue keyAndValue4 = new KeyAndValue(4,"3");
        KeyAndValue keyAndValue5 = new KeyAndValue(5,"3");
         KeyAndValue keyAndValue6 = new KeyAndValue(6,"1");
         KeyAndValue keyAndValue7 = new KeyAndValue(7,"1");
         KeyAndValue keyAndValue8 = new KeyAndValue(8,"5");
         KeyAndValue keyAndValue9 = new KeyAndValue(9,"1");
         KeyAndValue keyAndValue10 = new KeyAndValue(10,"3");
         KeyAndValue keyAndValue11 = new KeyAndValue(11,"2");
         KeyAndValue keyAndValue12 = new KeyAndValue(12,"2");
         KeyAndValue keyAndValue13 = new KeyAndValue(13,"2");
         KeyAndValue keyAndValue14 = new KeyAndValue(14,"1");
         KeyAndValue keyAndValue15 = new KeyAndValue(15,"1");
         KeyAndValue keyAndValue16 = new KeyAndValue(16,"1");
         KeyAndValue keyAndValue17 = new KeyAndValue(17,"1");
         KeyAndValue keyAndValue18 = new KeyAndValue(18,"1");
         KeyAndValue keyAndValue19 = new KeyAndValue(19,"4");
         KeyAndValue keyAndValue20 = new KeyAndValue(20,"5");
         KeyAndValue keyAndValue21 = new KeyAndValue(21,"5");
         KeyAndValue keyAndValue22 = new KeyAndValue(22,"5");
         KeyAndValue keyAndValue23 = new KeyAndValue(23,"5");
         KeyAndValue keyAndValue24 = new KeyAndValue(24,"5");
        BPlusTree t=new BPlusTree(3);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue1);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue3);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue22);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue6);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue17);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue15);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue24);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue19);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue2);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue5);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue20);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue18);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue7);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue4);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue21);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue11);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue12);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue9);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue10);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue13);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue14);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue8);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue16);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue23);
        t.printTree(t.root,t.head);
        t.inseart(t.root,keyAndValue23);
        t.printTree(t.root,t.head);


        t.delete(t.root,23);
        t.printTree(t.root,t.head);
        t.delete(t.root,3);
        t.printTree(t.root,t.head);
        t.delete(t.root,14);
        t.printTree(t.root,t.head);
        t.delete(t.root,13);
        t.printTree(t.root,t.head);
        t.delete(t.root,12);
        t.printTree(t.root,t.head);
        t.delete(t.root,8);
        t.printTree(t.root,t.head);
        t.delete(t.root,18);
        t.printTree(t.root,t.head);
        t.delete(t.root,22);
        t.printTree(t.root,t.head);
        t.delete(t.root,1);
        t.printTree(t.root,t.head);
        t.delete(t.root,2);
        t.printTree(t.root,t.head);
        t.delete(t.root,4);
        t.printTree(t.root,t.head);


        //System.out.println("search13: "+t.search(33,t.root));

    }

}
View Code

 






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM