b树的实现(2)---java版代码

原文地址: http://blog.csdn.net/cdnight/article/details/10619599

  1. 感觉上,b树的插入及删除操作都不如RB树复杂。当年插红黑树的各种操作解释文章都不下几十篇了,数据结构及算法的调试正确运行是一个大问题,因为错误往往出现在细微处。  
  1. package BTree;  
  2.   
  3. public class indexUnit {  
  4.   
  5.   
  6.   
  7.     public  float indexNo;  
  8.     public  Object indexValue=new Object();  
  9. }  

  1. package BTree;  
  2.   
  3.   
  4. import java.util.ArrayList;  
  5.   
  6. public class TreeUnit {  
  7.     public TreeUnit _parent=null;  
  8.     public ArrayList<indexUnit> keys=new ArrayList<indexUnit>();  
  9.   
  10.     public ArrayList<TreeUnit> childNodes=new ArrayList<TreeUnit>();  
  11. }  

  1. package BTree;  
  2.   
  3.   
  4.   
  5.   
  6. /** 
  7.  * Created with IntelliJ IDEA. 
  8.  * User: Administrator 
  9.  * Date: 13-8-19 
  10.  * Time: 上午10:21 
  11.  * To change this template use File | Settings | File Templates. 
  12.  */  
  13. public class BtreeGen {  
  14.   
  15.     public TreeUnit _btreeRootNode=new TreeUnit();  
  16.   
  17.     /* 
  18.      * 请注意,这个是最多容纳的子树的阶,b树的阶应该是最多的子树数量, 
  19.      * 根据b树的性质,最大主键数量+1=最多子树数量。 
  20.      * 并且,任何时刻,主键的数量比下属子树数量少1. 
  21.      * */  
  22.     public int _m=6;  
  23.     private int _min=3;  
  24.   
  25.     public int totalKeys=1;  
  26.   
  27.   
  28.   
  29.   
  30.   
  31.     /** 
  32.      * 确定该b树的最大子节点数。 
  33.      * */  
  34.     public BtreeGen(int m){  
  35.   
  36.         _m=m;  
  37.         _min=(int)Math.ceil((double)m/2);  
  38.     }  
  39.   
  40.     public boolean insert(float indexNO,Object indexValue){  
  41.   
  42.         indexUnit iunit=new indexUnit();  
  43.         iunit.indexNo=indexNO;  
  44.         iunit.indexValue=indexValue;  
  45.   
  46.         TreeUnit needInsertLeaf=recursion_insert_search_leaf_node(indexNO, _btreeRootNode);  
  47.   
  48.         if(needInsertLeaf==null){  
  49.             //--  
  50.             System.out.println("【警告】找不到需要插入的叶节点!");  
  51.             return false;  
  52.         }  
  53.         else{  
  54.             System.out.println("【提示】需要插入的叶节点为:");  
  55.             for(indexUnit iiUnit:needInsertLeaf.keys){  
  56.                 //--  
  57.                 System.out.print("  "+iiUnit.indexNo+"  ");  
  58.             }  
  59.   
  60.         }  
  61.         to_insert(indexNO, indexValue, needInsertLeaf);  
  62.   
  63.   
  64.         return true;  
  65.     }  
  66.   
  67.   
  68. private TreeUnit recursion_insert_search_leaf_node(float indexNO,TreeUnit currentUnit){  
  69. if(currentUnit==null){  
  70.     return null;  
  71. }  
  72. //--假如有下属节点,那么就必须跳到下一个点。  
  73. if(currentUnit.childNodes.size()>0){  
  74.     int childLoc=0;  
  75.     int cindex=0;  
  76.     for(indexUnit iUnit:currentUnit.keys){  
  77.         if(iUnit.indexNo<indexNO){  
  78.             childLoc=cindex+1;  
  79.         }  
  80.         if(iUnit.indexNo==indexNO){  
  81.             //--已经包含该节点了?那么就返回空,不要再插了。  
  82.             return null;  
  83.         }  
  84.         cindex++;  
  85.     }  
  86.     TreeUnit childTree=currentUnit.childNodes.get(childLoc);  
  87.     return  recursion_insert_search_leaf_node(indexNO, childTree);  
  88. }  
  89. else{  
  90.     //--没有下属节点,那么就认定是这个叶节点了。  
  91.   
  92.     return currentUnit;  
  93. }  
  94.   
  95. }  
  96.   
  97. /* 
  98.  * 主键的插入。 
  99.  * */  
  100. private void to_insert(float indexNO,Object value,TreeUnit currentUnit){  
  101.     int insertLoc=0;  
  102.   
  103.     for(indexUnit iUnit:currentUnit.keys){  
  104.   
  105.         if(iUnit.indexNo>indexNO){  
  106.             break;  
  107.         }  
  108.   
  109.         insertLoc++;  
  110.   
  111.     }  
  112.     indexUnit insertedUnit=new indexUnit();  
  113.     insertedUnit.indexNo=indexNO;  
  114.     insertedUnit.indexValue=value;  
  115.     currentUnit.keys.add(insertLoc, insertedUnit);  
  116.     if(currentUnit.keys.size()>_m-1){  
  117.         recursion_division(currentUnit);  
  118.     }  
  119.     else{  
  120.         return;  
  121.     }  
  122.   
  123.   
  124.   
  125. }  
  126.   
  127. private void recursion_division(TreeUnit currentUnit){  
  128.   
  129.     if(currentUnit==null){  
  130.         return;  
  131.     }  
  132.   
  133.    if(currentUnit.keys.size()<=_m-1){  
  134.        return;  
  135.    }  
  136.   
  137.    if(currentUnit._parent==null){  
  138.        System.out.println("没有父节点。");  
  139.        TreeUnit leftTree=new TreeUnit();  
  140.        TreeUnit rightTree=new TreeUnit();  
  141.        leftTree._parent=currentUnit;  
  142.        rightTree._parent=currentUnit;  
  143.        indexUnit keyUnit=currentUnit.keys.get(_min-1);  
  144.   
  145.        int cindex=0;  
  146.        for (indexUnit tmp:currentUnit.keys) {  
  147.   
  148.            if(cindex<_min-1){  
  149.                leftTree.keys.add(tmp);  
  150.            }  
  151.   
  152.            else if(cindex>=_min){  
  153.                rightTree.keys.add(tmp);  
  154.            }  
  155.   
  156.   
  157.            cindex++;  
  158.         }  
  159.   
  160.   
  161.        int theSize=currentUnit.childNodes.size();  
  162.        currentUnit.keys.clear();  
  163.        currentUnit.keys.add(keyUnit);  
  164.   
  165.       if(currentUnit.childNodes.size()>0){  
  166.        //--  
  167.        for(int ii=0;ii<theSize;ii++){  
  168.            if(ii<=_min-1){  
  169.                currentUnit.childNodes.get(ii)._parent=leftTree;  
  170.   
  171.                leftTree.childNodes.add(currentUnit.childNodes.get(ii));  
  172.   
  173.            }  
  174.            else{  
  175.                currentUnit.childNodes.get(ii)._parent=rightTree;  
  176.                rightTree.childNodes.add(currentUnit.childNodes.get(ii));  
  177.            }  
  178.        }  
  179.       }  
  180.   
  181.        currentUnit.childNodes.clear();  
  182.        currentUnit.childNodes.add(leftTree);  
  183.        currentUnit.childNodes.add(rightTree);  
  184.        return;  
  185.   
  186.    }  
  187.    System.out.println("父节点不为空。");  
  188.    //--分裂成为了旧节点及新节点两个节点。  
  189.    indexUnit keyUnit=currentUnit.keys.get(_min-1);  
  190.    TreeUnit newTreeUnit=new TreeUnit();  
  191.    newTreeUnit._parent=currentUnit._parent;  
  192.    int cindex=0;  
  193.    for (indexUnit tmp:currentUnit.keys) {  
  194.        if(cindex>=_min){  
  195.            newTreeUnit.keys.add(tmp);  
  196.        }  
  197.   
  198.        cindex++;  
  199.     }  
  200.   
  201.    int theSize=currentUnit.keys.size();  
  202.    for(int i2=theSize-1;i2>=_min-1;i2--){  
  203.        currentUnit.keys.remove(i2);  
  204.    }  
  205.   
  206.    cindex=0;  
  207.    theSize=currentUnit.childNodes.size();  
  208.    for(int ii4=theSize-1;ii4>=_min;ii4--){  
  209.        TreeUnit tmp2=currentUnit.childNodes.get(ii4);  
  210.        tmp2._parent=newTreeUnit;  
  211.        if(newTreeUnit.childNodes.size()<=0){  
  212.            newTreeUnit.childNodes.add(tmp2);  
  213.        }  
  214.        else{  
  215.        newTreeUnit.childNodes.add(0,tmp2);  
  216.        }  
  217.    }  
  218.   
  219.    for(int ii3=theSize-1;ii3>=_min;ii3--){  
  220.        currentUnit.childNodes.remove(ii3);  
  221.    }  
  222.   
  223.    int insertPLoc=0;  
  224.    cindex=0;  
  225.    for(indexUnit iUnit:currentUnit._parent.keys){  
  226.   
  227.        if(iUnit.indexNo<keyUnit.indexNo){  
  228.            insertPLoc=cindex+1;  
  229.        }  
  230.   
  231.        cindex++;  
  232.    }  
  233.    currentUnit._parent.keys.add(insertPLoc, keyUnit);  
  234.    currentUnit._parent.childNodes.add(insertPLoc+1, newTreeUnit);  
  235.    //--给父节点添加相应子节点。  
  236.    if(currentUnit._parent.keys.size()>_m-1){  
  237.        recursion_division(currentUnit._parent);  
  238.    }  
  239.    return;  
  240.   
  241.   
  242. }  
  243.   
  244.   
  245.     public indexUnit search(float indexNO){  
  246.         _searchResultUnit=null;  
  247.         recursion_search(_btreeRootNode,indexNO);  
  248.   
  249.         return _searchResultUnit;  
  250.   
  251.     }  
  252.   
  253.     private indexUnit _searchResultUnit=null;  
  254.   
  255.     private void recursion_search(TreeUnit currentUnit, float indexNO){  
  256.      if(currentUnit==null){  
  257.          _searchResultUnit=null;  
  258.          return;  
  259.      }  
  260.      for(indexUnit f1:currentUnit.keys){  
  261.          if(f1.indexNo==indexNO){  
  262.              _searchResultUnit=f1;  
  263.              return;  
  264.          }  
  265.      }  
  266.      //--假如上面都找不到,并且该节点下面没有子树了,那么就表示没有这个东西。  
  267.      if(currentUnit.childNodes.size()<=0){  
  268.          return;  
  269.      }  
  270.      int childTreeIndex=0;  
  271.      int ccIndex=0;  
  272.   
  273.      for(indexUnit f2:currentUnit.keys){  
  274.   
  275.          if(f2.indexNo<indexNO){  
  276.              childTreeIndex=ccIndex+1;  
  277.          }  
  278.   
  279.          ccIndex++;  
  280.   
  281.      }  
  282.   
  283.      TreeUnit childTreeUnit=currentUnit.childNodes.get(childTreeIndex);  
  284.   
  285.      recursion_search(childTreeUnit, indexNO);  
  286.   
  287.   
  288.     }  
  289.   
  290.     private TreeUnit _result_treeUnit=null;  
  291.     /** 
  292.      * 获取indexNO所在的节点。 
  293.      * */  
  294.   
  295.     public TreeUnit getSearchNode(float indexNO){  
  296.   
  297.         _result_treeUnit=null;  
  298.         recursion_search_node(_btreeRootNode, indexNO);  
  299.         return _result_treeUnit;  
  300.   
  301.     }  
  302.   
  303. /** 
  304.  *搜查indexNO所在的节点。 
  305.  * */  
  306.     private void recursion_search_node(TreeUnit treeUnit,float indexNO){  
  307.     if(treeUnit==null){  
  308.         return;  
  309.     }  
  310.     int childChosenIndex=0;  
  311.     int cindex=0;  
  312.     for(indexUnit iTMP:treeUnit.keys){  
  313.         if(indexNO>iTMP.indexNo){  
  314.             childChosenIndex=cindex+1;  
  315.         }  
  316.         if(iTMP.indexNo==indexNO){  
  317.             _result_treeUnit=treeUnit;  
  318.             return;  
  319.         }  
  320.   
  321.         cindex++;  
  322.     }  
  323.     if(treeUnit.childNodes.size()<=0){  
  324.         return;  
  325.     }  
  326.     //--假如有下面并且当前没包含相关主键,那么就搜索下面子节点的。  
  327.     TreeUnit childTreeUnit=treeUnit.childNodes.get(childChosenIndex);  
  328.     recursion_search_node(childTreeUnit, indexNO);  
  329.     }  
  330.   
  331.   
  332.     public int[] getRoute(float indexNO){  
  333.   
  334.                   return null;  
  335.     }  
  336.       
  337.     public boolean delete(float indexNO){  
  338.         TreeUnit needDelNode=getSearchNode(indexNO);  
  339.         if(needDelNode==null){  
  340.             return false;  
  341.         }  
  342.         return deleteNode(needDelNode, indexNO);  
  343.           
  344.     }  
  345.       
  346. /** 
  347.  * 删除相关节点。 
  348.  * 删除有几种情况: 
  349.  * 1、假如是叶节点,并且删除以后符合b树的性质,譬如:m=6---最大主键数量为5,最少主键数量为2,叶节点删除主键后,假如关键字数量》=2,那么就完成删除操作, 
  350.  * 否则: 
  351.  * 1、看看有没有左右节点,假如左右节点有空余的关键字,那么就借用相应的关键字, 
  352.  * 假如左右节点的关键字数量都是2,没有空余的,那么只能想父节点借用,并且可能会发生合并操作。 
  353.  * 
  354.  * */  
  355.     public boolean deleteNode(TreeUnit needDelNode,float indexNO){  
  356.         //System.out.println("需要删除的节点为:"+needDelNode.keys.get(0).indexNo);  
  357.   
  358.    
  359.         //--找到当前关键字的在节点里面的位置。  
  360.         int indexLoc=-1;  
  361.         int cindex=0;  
  362.         for(indexUnit iUnit:needDelNode.keys){  
  363.             if(iUnit.indexNo==indexNO){  
  364.                 indexLoc=cindex;  
  365.             }  
  366.   
  367.             cindex++;  
  368.         }  
  369.   
  370.         if(indexLoc==-1){  
  371.               
  372.             return false;  
  373.         }         
  374.         TreeUnit leftChildNode=null;  
  375.         TreeUnit rightChildNode=null;  
  376.         if(needDelNode.childNodes.size()>0){  
  377.             leftChildNode=needDelNode.childNodes.get(indexLoc);  
  378.             rightChildNode=needDelNode.childNodes.get(indexLoc+1);  
  379.         }  
  380.           
  381.           
  382.         /** 
  383.          * 假如关键字所在节点为根节点,并且没有任何下属节点,那么就直接删除好了。 
  384.          * */  
  385.         if(needDelNode._parent==null&&(needDelNode.childNodes==null||needDelNode.childNodes.size()<=0)){  
  386.   
  387.             needDelNode.keys.remove(indexLoc);  
  388.             return true;  
  389.         }  
  390.         /** 
  391.          * 假如关键字包含子节点,那么就进行相关调整,需要递归调整到叶子节点为止。请注意,现在只是调整调换关键字的数值,并没有删除任何关键字,所以 
  392.          * b树的结构没有破坏。 
  393.          * */  
  394.         /** 
  395.          * a.如果x的左孩子节点存在,x->child[i],并且x->child[i]的节点关键字个数至少是n个, 
  396.          * 则找到 child[i]中最大的关键字max替换x中删除的关键字,继续递归child[i]删除关键字max。 
  397.          * 这一段话引用自网上,但是我想说,假如该节点不是叶子节点,那么对于该节点的某一个关键字keys[i], 
  398.          * 其左子结点及右子节点child[i]与child[i+1]必然存在----这是b树的基本性质。 
  399.          * */  
  400.         if(needDelNode.childNodes!=null&&needDelNode.childNodes.size()>0){  
  401.             //假如左节点有空余的关键字可以使用(解释:对于6阶b树--最多6个子树,每个节点最少有3棵子树,最多5个节点,最少2个节点,有空余关键字是指关键字数量大于或等于3个)  
  402.               
  403.             if(leftChildNode!=null&&leftChildNode.keys.size()>=_min){  
  404.                 int leftLastIndex=leftChildNode.keys.size()-1;  
  405.                 needDelNode.keys.remove(indexLoc);  
  406.                 needDelNode.keys.add(indexLoc,leftChildNode.keys.get(leftLastIndex));  
  407.                 float indexNO1=needDelNode.keys.get(indexLoc).indexNo;  
  408.                 //--递归执行  
  409.                   
  410.                 return deleteNode(leftChildNode, indexNO1);  
  411.             }  
  412.             //--假如右侧节点有关键字空余  
  413.             else    if(rightChildNode.keys.size()>=_min){  
  414.                 int rightLastIndex=0;  
  415.                 needDelNode.keys.remove(indexLoc);  
  416.                 needDelNode.keys.add(indexLoc, rightChildNode.keys.get(0));  
  417.                   
  418.                 return deleteNode(rightChildNode, rightChildNode.keys.get(0).indexNo);  
  419.             }  
  420.             else{  
  421.                 //--假如左右子节点都没有空余节点了,那么只能合并了。  
  422.                   
  423.                 leftChildNode.keys.add(needDelNode.keys.get(indexLoc));  
  424.                 for(indexUnit iUnit:rightChildNode.keys){  
  425.                     leftChildNode.keys.add(iUnit);  
  426.                 }  
  427.                 for(TreeUnit item1:rightChildNode.childNodes){  
  428.                     leftChildNode.childNodes.add(item1);  
  429.                 }  
  430.                 needDelNode.keys.remove(indexLoc);  
  431.                 needDelNode.childNodes.remove(indexLoc+1);  
  432.                 //--检查父节点是否符合性质,是否需要回溯合并节点。  
  433.                 /** 
  434.                  * 请注意:这个地方是造成回溯合并的主要情形。 
  435.                  * */  
  436.                 recursion_checkCombination(needDelNode);  
  437.                   
  438.                   
  439.                 return deleteNode(leftChildNode, indexNO);  
  440.                   
  441.                   
  442.             }  
  443.         }  
  444.           
  445.         /** 
  446.          *  
  447.          * 假如是叶子节点,那么就执行相关操作。 
  448.          *  
  449.          * */  
  450.           
  451.         else    if(needDelNode.childNodes==null||needDelNode.childNodes.size()<=0){  
  452.             if(needDelNode.keys.size()>=_min){  
  453.                 needDelNode.keys.remove(indexLoc);  
  454.                 return true;  
  455.             }  
  456.             //---  
  457.             TreeUnit leftBrother=null;  
  458.             TreeUnit rightBrother=null;  
  459.             TreeUnit parentNode=needDelNode._parent;  
  460.             int childIndexLoc=parentNode.childNodes.indexOf(needDelNode);  
  461.   
  462.             int keyIndexLoc=-1;  
  463.             if(childIndexLoc==0){  
  464.                 rightBrother=parentNode.childNodes.get(1);  
  465.             }  
  466.             else if(childIndexLoc==parentNode.childNodes.size()-1){  
  467.                 leftBrother=parentNode.childNodes.get(childIndexLoc-1);  
  468.             }  
  469.             else{  
  470.                 leftBrother=parentNode.childNodes.get(childIndexLoc-1);  
  471.                 rightBrother=parentNode.childNodes.get(childIndexLoc+1);  
  472.             }  
  473.               
  474.             //--假如左侧兄弟存在并且有多余节点那么就借用了。  
  475.             if(leftBrother!=null&&leftBrother.keys.size()>=_min){  
  476.                 keyIndexLoc=childIndexLoc-1;  
  477.                 needDelNode.keys.add(0,parentNode.keys.get(keyIndexLoc));  
  478.                 parentNode.keys.remove(keyIndexLoc);  
  479.                 parentNode.keys.add(keyIndexLoc,leftBrother.keys.get(leftBrother.keys.size()-1));  
  480.                 leftBrother.keys.remove(leftBrother.keys.size()-1);  
  481.                 return deleteNode(needDelNode, indexNO);  
  482.             }  
  483.             //右侧兄弟有多余的。  
  484.             else if(rightBrother!=null&&rightBrother.keys.size()>=_min){  
  485.                 keyIndexLoc=childIndexLoc;  
  486.                 needDelNode.keys.add(parentNode.keys.get(keyIndexLoc));  
  487.                   
  488.                 parentNode.keys.add(keyIndexLoc,rightBrother.keys.get(0));  
  489.                 parentNode.keys.remove(keyIndexLoc+1);  
  490.                   
  491.                   
  492.                 rightBrother.keys.remove(0);///-------------  
  493.                 return deleteNode(needDelNode, indexNO);  
  494.             }  
  495.             //--两个兄弟都没有多余的,那么就合并好了。  
  496.             else{  
  497.                 if(leftBrother!=null){  
  498.                     //leftBrother.keys.add(parentNode.keys.get(keyIndexLoc));  
  499.                     keyIndexLoc=childIndexLoc-1;  
  500.                     leftBrother.keys.add(parentNode.keys.get(keyIndexLoc));  
  501.                       
  502.                     for(indexUnit iUnit:needDelNode.keys){  
  503.                         leftBrother.keys.add(iUnit);  
  504.                     }  
  505.                     parentNode.keys.remove(keyIndexLoc);  
  506.                     parentNode.childNodes.remove(keyIndexLoc+1);  
  507.                       
  508.                     recursion_checkCombination(parentNode);  
  509.                     deleteNode(leftBrother, indexNO);  
  510.                     return true;  
  511.                 }  
  512.                 else if(rightBrother!=null){  
  513.                     //needDelNode.keys.remove(indexLoc);  
  514.                     keyIndexLoc=childIndexLoc;  
  515.                     needDelNode.keys.add(parentNode.keys.get(keyIndexLoc));  
  516.                     for(indexUnit iUnit:rightBrother.keys){  
  517.                         needDelNode.keys.add(iUnit);  
  518.                           
  519.                     }  
  520.                     parentNode.keys.remove(keyIndexLoc);  
  521.                     parentNode.childNodes.remove(keyIndexLoc+1);  
  522.                       
  523.                     recursion_checkCombination(parentNode);  
  524.                     deleteNode(needDelNode, indexNO);  
  525.                     return true;  
  526.                 }  
  527.                 else{  
  528.                     return false;  
  529.                 }  
  530.             }  
  531.               
  532.               
  533.         }  
  534.           
  535.      
  536.   
  537.         return true;  
  538.     }  
  539.       
  540.     private void recursion_checkCombination(TreeUnit currentUnit){  
  541.         if(currentUnit==null){  
  542.             return;  
  543.         }  
  544.         if(currentUnit._parent==null&¤tUnit.childNodes.size()<=1){  
  545.             //假如当前节点为根节点,并且没有关键字,那么根节点丢弃,采用新的根节点。  
  546.             _btreeRootNode=currentUnit.childNodes.get(0);  
  547.             _btreeRootNode._parent=null;  
  548.             return;  
  549.         }  
  550.         //假如当前节点为根节点,并且关键字为一,那么就不管了,符合性质。  
  551.         if(currentUnit._parent==null){  
  552.             return;  
  553.         }  
  554.           
  555.         if(currentUnit.keys.size()>=_min-1){  
  556.             return;  
  557.         }  
  558.         //假如不为根节点,并且节点的关键字小于_min-1,那么必须再回溯递归合并。  
  559.       
  560.             /** 
  561.              * 分几种情况,假如左侧子节点有空余关键字,那么从左侧节点借,假如右侧节点有空余关键字,那么从右侧节点借, 
  562.              * 否则两边都没有只能继续递归合并了。 
  563.              * */  
  564.             TreeUnit parentNode=currentUnit._parent;  
  565.             int indexLOC=currentUnit._parent.childNodes.indexOf(currentUnit);         
  566.             int keyIndexLOC=-1;  
  567.             int childIndexLOC=indexLOC;  
  568.             TreeUnit leftBrother=null;  
  569.             TreeUnit rightBrother=null;  
  570.             if(parentNode.childNodes.size()==2){  
  571.                 if(childIndexLOC==0){  
  572.                     rightBrother=parentNode.childNodes.get(1);  
  573.                 }  
  574.                 else{  
  575.                     leftBrother=parentNode.childNodes.get(0);  
  576.                 }  
  577.             }  
  578.             else if(parentNode.childNodes.size()>=3){  
  579.                 if(childIndexLOC==0){  
  580.                     rightBrother=parentNode.childNodes.get(1);  
  581.                 }  
  582.                 else if(childIndexLOC==parentNode.childNodes.size()-1){  
  583.                     leftBrother=parentNode.childNodes.get(childIndexLOC-1);  
  584.                 }  
  585.                 else{  
  586.                     leftBrother=parentNode.childNodes.get(childIndexLOC-1);  
  587.                     rightBrother=parentNode.childNodes.get(childIndexLOC+1);  
  588.                 }  
  589.             }  
  590.               
  591.             //--左边兄弟节点有余钱,那么就借。  
  592.             if(leftBrother!=null&&leftBrother.keys.size()>=_min){  
  593.             keyIndexLOC=childIndexLOC-1;  
  594.             currentUnit.keys.add(0, parentNode.keys.get(keyIndexLOC));  
  595.             currentUnit.childNodes.add(0,leftBrother.childNodes.get(leftBrother.childNodes.size()-1));  
  596.             parentNode.keys.remove(keyIndexLOC);  
  597.             parentNode.keys.add(keyIndexLOC,leftBrother.keys.get(leftBrother.keys.size()-1));  
  598.             leftBrother.keys.remove(leftBrother.keys.size()-1);  
  599.             leftBrother.childNodes.remove(leftBrother.childNodes.size()-1);  
  600.             return;               
  601.             }  
  602.             //--右边兄弟有余钱,那么就借  
  603.             else if(rightBrother!=null&&rightBrother.keys.size()>=_min){  
  604.                 keyIndexLOC=childIndexLOC;  
  605.                 currentUnit.keys.add(parentNode.keys.get(keyIndexLOC));  
  606.                 currentUnit.childNodes.add(rightBrother.childNodes.get(0));  
  607.                 parentNode.keys.remove(keyIndexLOC);  
  608.                 parentNode.keys.add(rightBrother.keys.get(0));  
  609.                 rightBrother.keys.remove(0);  
  610.                 rightBrother.childNodes.remove(0);  
  611.                   
  612.                 return;  
  613.                   
  614.             }  
  615.             //--大家都没得借,那么就只能递归合并了。  
  616.             else{  
  617.                 //--有左侧兄弟  
  618.                 if(leftBrother!=null){  
  619.                     keyIndexLOC=childIndexLOC-1;  
  620.                     leftBrother.keys.add(parentNode.keys.get(keyIndexLOC));  
  621.                     for(indexUnit iUnit:currentUnit.keys){  
  622.                         leftBrother.keys.add(iUnit);  
  623.                     }  
  624.                     for(TreeUnit tUnit:currentUnit.childNodes){  
  625.                         leftBrother.childNodes.add(tUnit);  
  626.                         tUnit._parent=leftBrother;  
  627.                     }  
  628.                     parentNode.keys.remove(keyIndexLOC);  
  629.                     parentNode.childNodes.remove(keyIndexLOC+1);  
  630.                     recursion_checkCombination(parentNode);  
  631.                     return;  
  632.                 }  
  633.                 else{  
  634.                     //--有右侧兄弟  
  635.                     keyIndexLOC=childIndexLOC;  
  636.                     currentUnit.keys.add(parentNode.keys.get(keyIndexLOC));  
  637.                     for(indexUnit iUnit:rightBrother.keys){  
  638.                         currentUnit.keys.add(iUnit);  
  639.                     }  
  640.                     for(TreeUnit iUnit:rightBrother.childNodes){  
  641.                         currentUnit.childNodes.add(iUnit);  
  642.                         iUnit._parent=currentUnit;  
  643.                     }  
  644.                     parentNode.keys.remove(keyIndexLOC);  
  645.                     parentNode.childNodes.remove(keyIndexLOC+1);  
  646.                     recursion_checkCombination(parentNode);  
  647.                     return;  
  648.                       
  649.                       
  650.                 }  
  651.                   
  652.             }             
  653.   
  654.               
  655.   
  656.               
  657.           
  658.     }  
  659.   
  660.     
  661. }  


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的B树Java代码实现: ``` class BTreeNode { int[] keys; // 存储键值 int t; // 最小度数 BTreeNode[] children; // 子节点 int n; // 当前节点中的键值数量 boolean leaf; // 是否为叶子节点 public BTreeNode(int t, boolean leaf) { this.t = t; this.leaf = leaf; this.keys = new int[2 * t - 1]; this.children = new BTreeNode[2 * t]; this.n = 0; } public void traverse() { int i; for (i = 0; i < this.n; i++) { if (!this.leaf) { this.children[i].traverse(); } System.out.print(this.keys[i] + " "); } if (!this.leaf) { this.children[i].traverse(); } } public BTreeNode search(int key) { int i = 0; while (i < this.n && key > this.keys[i]) { i++; } if (this.keys[i] == key) { return this; } if (this.leaf) { return null; } return this.children[i].search(key); } public void insertNonFull(int key) { int i = this.n - 1; if (this.leaf) { while (i >= 0 && this.keys[i] > key) { this.keys[i + 1] = this.keys[i]; i--; } this.keys[i + 1] = key; this.n++; } else { while (i >= 0 && this.keys[i] > key) { i--; } if (this.children[i + 1].n == 2 * this.t - 1) { splitChild(i + 1, this.children[i + 1]); if (this.keys[i + 1] < key) { i++; } } this.children[i + 1].insertNonFull(key); } } public void splitChild(int i, BTreeNode y) { BTreeNode z = new BTreeNode(y.t, y.leaf); z.n = this.t - 1; for (int j = 0; j < this.t - 1; j++) { z.keys[j] = y.keys[j + this.t]; } if (!y.leaf) { for (int j = 0; j < this.t; j++) { z.children[j] = y.children[j + this.t]; } } y.n = this.t - 1; for (int j = this.n; j >= i + 1; j--) { this.children[j + 1] = this.children[j]; } this.children[i + 1] = z; for (int j = this.n - 1; j >= i; j--) { this.keys[j + 1] = this.keys[j]; } this.keys[i] = y.keys[this.t - 1]; this.n++; } } class BTree { BTreeNode root; int t; public BTree(int t) { this.t = t; this.root = null; } public void traverse() { if (this.root != null) { this.root.traverse(); } } public BTreeNode search(int key) { if (this.root == null) { return null; } return this.root.search(key); } public void insert(int key) { if (this.root == null) { this.root = new BTreeNode(this.t, true); this.root.keys[0] = key; this.root.n = 1; } else { if (this.root.n == 2 * this.t - 1) { BTreeNode s = new BTreeNode(this.t, false); s.children[0] = this.root; s.splitChild(0, this.root); int i = 0; if (s.keys[0] < key) { i++; } s.children[i].insertNonFull(key); this.root = s; } else { this.root.insertNonFull(key); } } } } ``` 此代码实现B树的基本操作,包括遍历、搜索和插入。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值