编程内功修炼之数据结构—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 }