编程内功修炼之数据结构—BTree(三)总结

BTree必须通过各种编程约束,使得不脱离BTree的本身特性;

1)BTree关键字插入操作;插入过程中,如果节点关键字达到上限,添加分裂约束,从而控制每个节点的关键字数维持在 t-1~2*t-1内;

2)BTree节点中的关键字查询;因为关键字按非降序进行排列,所以可以采用二分查找方法进行查询,以提高算法性能;

3)BTree关键字删除操作;

 删除操作必须保证节点关键字数n[x]>=t,这样删除一个关键字才不会违反BTree规则。

   当前节点是叶节点,可以直接删除;

   当前节点是内节点,可以寻找左右子女节点进行关键字替代;

   当前节点不足t方案:

    (a)如果当前节点关键字不足t,可以向兄弟节点进行借取;

         (b)如果左右相近兄弟节点都不满足>=t要求,那么可以采用合并方式;

   Delete实现方法如下:

  1 public void delete(BTreeNode node, Integer key){
  2         //删除关键字时,必须保证关键字大于等于t
  3         assert node.size() >=t || node == root;
  4         
  5         //对当前节点进行二分查找
  6         ResultSearch resultSearch = divideSearch(node.getKeys(), key);
  7         
  8         //成功
  9         if(resultSearch.result){
 10             
 11             //如果当前节点属于叶子节点,可以直接进行删除
 12             if(node.isLeaf()){
 13                 node.getKeys().remove(resultSearch.index.intValue());
 14             }else{
 15                 //如果不是叶子节点 ,判断前于key子节点状态
 16                 BTreeNode leftChildNode = node.childAt(resultSearch.index);
 17                 if(leftChildNode.size() >= t){
 18                     
 19                     //从leftChildNode进行借值 代替当前需要删除的关键字
 20                     //删除当前节点关键字
 21                     node.getKeys().remove(resultSearch.index.intValue());
 22                     node.insertKey(leftChildNode.keyAt(leftChildNode.size()-1), resultSearch.index);
 23                     delete(leftChildNode, leftChildNode.keyAt(leftChildNode.size()-1));
 24                 }else{
 25                     
 26                     BTreeNode rightChildNode = node.childAt(resultSearch.index + 1);
 27                     if(rightChildNode.size() >= t){
 28                         
 29                         //从rightChildNode进行借值 代替当前需要删除的关键字
 30                         node.getKeys().remove(resultSearch.index.intValue());
 31                         node.insertKey(rightChildNode.keyAt(0), resultSearch.index);
 32                         delete(rightChildNode, rightChildNode.keyAt(0));
 33                     }else{
 34                         
 35                         //对于索引的左右子节点的数量都等于t-1
 36                         //合适进行合并
 37                         //1.将父节点删除  将节点右子节点删除
 38                         node.getKeys().remove(resultSearch.index.intValue());
 39                         node.getChildrens().remove(resultSearch.index.intValue() + 1);
 40                         //2.将父节点添加到左子节点上
 41                         leftChildNode.getKeys().add(key);
 42                         //3.将删除的右子节点添加到左子节点上
 43                         for(int i=0 ; i<rightChildNode.size() ; i++){
 44                             leftChildNode.getKeys().add(rightChildNode.getKeys().get(i));
 45                         }
 46                         //如果右子节点非叶子节点,需要将其子女继承到左节点之下
 47                         if(!rightChildNode.isLeaf()){
 48                             for(int k=0 ; k<=rightChildNode.size() ; k++){
 49                                 leftChildNode.getChildrens().add(rightChildNode.childAt(k));
 50                             }
 51                         }
 52                         //递归删除
 53                         delete(leftChildNode, key);
 54                         
 55                     }
 56                 }
 57                 
 58             }
 59             
 60         }else{ //失败
 61             if(node.isLeaf()){
 62                 //不存在删除的对象
 63                 System.out.println("不存在删除的对象");
 64                 return ;
 65             }
 66             
 67             //获取子节点
 68             BTreeNode childNode = node.childAt(resultSearch.index);
 69             
 70             if(root == node && node.size()==0){
 71                 root = childNode;
 72             }
 73             
 74             if(childNode.size() >= t){   //如果满足递归条件
 75                 delete(childNode, key);
 76             }else{
 77                 //不满足size == t
 78                 //采取借关键字手段
 79                 
 80                 BTreeNode subNode = null;
 81                 int subIndex = 0;
 82                 //先检测右兄弟节点
 83                 if(resultSearch.index < node.size()){
 84                     if(node.childAt(resultSearch.index+1).size() >=t){
 85                         subNode  = node.childAt(resultSearch.index+1);
 86                         subIndex = resultSearch.index + 1;
 87                     }
 88                 }
 89                 //测试左兄弟节点
 90                 if(subNode == null){
 91                     if(resultSearch.index > 0){
 92                         if(node.childAt(resultSearch.index-1).size() >= t){
 93                             subNode  = node.childAt(resultSearch.index-1);
 94                             subIndex = resultSearch.index - 1;
 95                         }
 96                     }
 97                 }
 98                 //测试完成后
 99                 if(subNode != null){  //存在兄弟节点大于等于t情况
100                     //判断节点
101                     if(subIndex > resultSearch.index){ //右兄弟
102                         
103                         //将右关键字插入自身
104                         childNode.insertKey(node.keyAt(subIndex - 1), childNode.size());
105                         node.getKeys().remove(subIndex - 1);
106                         node.insertKey(subNode.keyAt(0), subIndex - 1);
107                         subNode.getKeys().remove(0);
108                         
109                         //右兄弟非子叶节点,则带有孩子节点
110                         if(!subNode.isLeaf()){
111                             childNode.getChildrens().add(subNode.getChildrens().get(0));
112                             subNode.getChildrens().remove(0);
113                         }
114                         
115                     }else{  //左兄弟
116                         
117                         //将左关键字插入自身最前位置
118                         childNode.insertKey(node.keyAt(subIndex), 0);
119                         node.getKeys().remove(subIndex);
120                         node.insertKey(subNode.keyAt(subNode.size()-1), subIndex);
121                         subNode.getKeys().remove(subNode.size()-1);
122                         
123                         //如果左兄弟非子叶节点
124                         if(!subNode.isLeaf()){
125                             childNode.insertChild(subNode.childAt(subNode.size()), 0);
126                             subNode.getChildrens().remove(subNode.size()-1);
127                         }    
128                     }
129                     delete(childNode, key);
130                     
131                 }else{
132                     
133                     //该节点的左右兄弟节点关键字都为t-1
134                     //选择合并方案
135                     if(resultSearch.index < node.size()){   //右兄弟存在
136                         
137                         subNode = node.childAt(resultSearch.index + 1);
138                         
139                         //childNode.getKeys().add(node.keyAt(resultSearch.index + 1));
140                         childNode.getKeys().add(node.keyAt(resultSearch.index));
141                         
142                         node.getKeys().remove(resultSearch.index.intValue());
143                         node.getChildrens().remove(resultSearch.index.intValue());
144                         
145                         for(int i=0 ; i<subNode.size() ; i++){
146                             childNode.getKeys().add(subNode.keyAt(i));
147                         }
148                         
149                         if(!subNode.isLeaf()){
150                             for(int k=0 ; k<=subNode.size(); k++){
151                                 childNode.getChildrens().add(subNode.childAt(k));
152                             }
153                         }
154                         
155                     }else{      //左兄弟存在
156                         
157                         subNode = node.childAt(resultSearch.index - 1);
158                         childNode.insertKey(node.keyAt(resultSearch.index-1), 0);
159                         node.getKeys().remove(resultSearch.index - 1);
160                         node.getChildrens().remove(resultSearch.index-1);
161                         
162                         for(int i=subNode.size()-1 ; i>=0 ; --i){
163                             childNode.insertKey(subNode.keyAt(i), 0);
164                         }
165                         
166                         if(!subNode.isLeaf()){
167                             for(int k=subNode.size() ; k>=0 ; --k){
168                                 childNode.insertChild(subNode.childAt(k),0);
169                             }
170                         }
171                         
172                     }
173                     if(root == node && node.size() == 0){
174                         root = childNode;
175                     }
176                     delete(childNode, key);
177                 }
178             }
179             
180         }
181     }

 

posted @ 2015-04-27 15:53  helingfeng  阅读(205)  评论(0编辑  收藏  举报