java b tree_自己写的java实现的多路搜索树 B-Tree

1 packagecom.test1;2

3 importjava.io.BufferedReader;4 importjava.io.IOException;5 importjava.io.InputStreamReader;6 importjava.util.ArrayList;7 importjava.util.List;8 importjava.util.NoSuchElementException;9

10 /**

11 * Created by MSI on 2016/1/5.12 * 该程序参考文章:http://blog.csdn.net/v_JULY_v/article/details/6530142/

13 */

14 public class BsubTree>{15

16 private static BsubTree tree = new BsubTree();17 private static BufferedReader reader = new BufferedReader(newInputStreamReader(System.in));18

19 int m = 4; //此B-树的阶数。关键字数等于阶数-1。m至少为2,m必须大于等于2。

20 int n; //n是关键字最小个数

21 publicBTNode root;22

23 publicBsubTree(){24 root = new BTNode(null,null);25 if(m>=2){26 if(m%2==0){27 n = m/2-1;28 }else{29 n = m/2;30 }31 }else{32 System.out.println("error");33 System.exit(0);34 }35 }36

37 publicBsubTree(BTNode root){38 this.root =root;39 if(m%2==0){40 n = m/2;41 }else{42 n = m/2+1;43 }44 }45

46 publicBTNode findNode(T information){47 returnfindNode(information, root);48 } //isMember应该返回插入点

49

50 private BTNode findNode(T info, BTNode node){ //不论是否找到都返回一个node。

51 BTNode member = null;52

53 if(node.informations.size()==0){//这种情况存在,只有root可能

54 member =node;55 //System.out.println("error");

56 }else{57 if(info.compareTo(node.informations.get(node.informations.size()-1))>0) { //info比节点最大的还大,则直接进入最右分支

58 if(node.ptr.size()>0){//有孩子的情况,进入范围中的子节点

59 member =findNode(info, node.ptr.get(node.informations.size()));60 }else {//没有子节点,直接返回node

61 member =node;62 }63 }else {//没有判断没有子节点的情况,上一个if中判断了,这一个else中就忘了,怒

64 if(node.ptr.size()>0){//有子节点

65 if(info.compareTo(node.informations.get(0))<0){66 member = findNode(info, node.ptr.get(0));67 }else{68 for(int i = 0;i0&&info.compareTo(node.informations.get(i+1))<0){ //只要不是最右,info比之大的,进入它的孩子节点

73 member = findNode(info, node.ptr.get(i+1));74 break;75 }76 }77 }78 }else {//没有子节点

79 member =node;80 }81 }82 }83 returnmember;84 }85

86 public voidinsert(T info){87 BTNode temp =findNode(info);88 if(temp.informations.size()!=0){89 for(T i:temp.informations){90 if(i.compareTo(info)==0){91 System.out.println("已存在所插入的值。");92 return;93 }94 }95 }96 insert(info,temp,temp.parent);97 return;98 }99

100 private void insert(T info,BTNode node,BTNode parent){//插入一定是在叶子节点

101 if(node == null){//insert中的node为空应该只有一种情况,node=root

102 if(parent == null){103 root = newBTNode(info,parent);104 }else{105 System.out.println("不应该出现的情况,请检查。");106 //node = new BTNode(info,parent);

107 }108 }else{109 if(node.informations.size()==0){110 //System.out.println("这种情况应该不存在,请检查代码");//现在存在这种情况啦

111 node.informations.add(info);112 }else if(node.informations.size()>0 && node.informations.size()0){//info比node最右边最大的值还大,则直接插入

114 node.informations.add(info);115 }else{116 for (int i = 0; i < node.informations.size(); ++i) {117 if (info.compareTo(node.informations.get(i)) < 0) {118 node.informations.add(i, info);119 break;120 }121 }122 }123 }else if(node.informations.size()==m-1){//需要分裂

124 if(info.compareTo(node.informations.get(node.informations.size()-1))>0){//info比node最右边最大的值还大,则直接插入

125 node.informations.add(info);126 }else{127 for(int i = 0;i

135 split(node);136 }else{137 System.out.println("node 的size大于等于m-1,不应该出现,请检查代码");138 }139 }140 }141

142 public voiddelete(T info){143 BTNode temp =findNode(info,root);144 if(temp.informations.size()==0){145 System.out.println("根节点为空!");146 return;147 }148 for(T i:temp.informations){149 if(info.compareTo(i)==0){150 delete(info,temp);151 break;152 }else if(temp.informations.indexOf(i)==temp.informations.size()-1){//循环到最后一个值了,仍到这里,说明不存在要删除的值!

153 System.out.println("不存在要删除的值!");154 }155 }156 }157

158 private void delete(T info,BTNode node)throwsNoSuchElementException {159 if (node == null) { //其实到这里,就一定存在要删除的值了。

160 throw newNoSuchElementException();161 }else{162 inti;163 for(i=0;i

166 break;167 }168 }169 if(node.ptr.size()>0){//删除一个非叶子节点的关键字后,如果有孩子,则判断孩子的孩子,如果孩子有孩子,则将右孩子的孩子最深左孩子的第一个值赋给删除关键字的节点170 //每一个关键字,一定有两个孩子

171 if(node.ptr.get(i+1).ptr.size()==0){//孩子没有孩子的时候,只将孩子的最左关键字上升。

172 node.informations.add(i,node.ptr.get(i+1).informations.get(0));173 node.ptr.get(i+1).informations.remove(0);174 if(node.ptr.get(i+1).informations.size()

178 pullRLeftNode(node,i,node.ptr.get(i+1),i);179 }180

181 }else {//如果没有孩子,要判断该节点关键字数量是否大于最小值

182 if(node.informations.size()>=n){//大于等于就没事,不用动

183 return;184 }else {//叶子节点中关键字数小于n,需要继续判断兄弟节点是否饱满

185 dManageNode(node);186 }187 }188 }189 }190

191 publicString perOrder(BTNode node){192 String result = "";193 if(node.ptr.size()>0){194 int i = 0;195 for(BTNode n:node.ptr){196 result +=perOrder(n);197 if(i

203 if(node.informations.size()>0){204 for(T t:node.informations){205 result += t.toString()+",";206 }207 }else {//叶子节点没有空值的时候,除非是根节点,根节点为空值的时候,说句话意思意思

208 result += "B-树为空!";209 }210 }211 returnresult;212 }213

214 public void split(BTNode node){//进到这里的node都是m个关键字,需要提出m/2

215 if(node == null){216 System.out.println("error");217 }else{218 if(node.informations.size()!=m){219 System.out.println("error");220 }else{221 if(node.parent == null){//node是root时

222 T temp = node.informations.get(n);//这里正好

223 root = new BTNode(temp,null);224 node.informations.remove(n);//加进去了就要删掉!

225 root.ptr.add(node);226 node.parent=root;227 splitNewNode(node,n,root);228 }else {//一个非根节点

229 T temp =node.informations.get(n);230 node.parent.informations.add(node.parent.ptr.indexOf(node),temp);231 node.informations.remove(n);232 splitNewNode(node,n,node.parent);233 if (node.parent.informations.size()>=m){234 split(node.parent);235 }236 }237 }238 }239 }240

241 public void splitNewNode(BTNode node,intn,BTNode parent){242 BTNode newnode = newBTNode(node.informations.get(n),node.parent);243

244 newnode.informations.addAll(node.informations.subList(n+1,node.informations.size()));245

246 node.informations.removeAll(node.informations.subList(n,node.informations.size()));247 //newnode.parent=node.parent;//新增节点的父节点

248 node.parent.ptr.add(node.parent.ptr.indexOf(node)+1,newnode); //新增节点加到父节点上

249 if(node.ptr.size()>0){ //处理新增节点的孩子

250 newnode.ptr.addAll(node.ptr.subList(n+1,node.ptr.size()));251 node.ptr.removeAll(node.ptr.subList(n+1,node.ptr.size()));252 for (BTNode bn:newnode.ptr){ //子节点移到了新节点上,但是子节点的父节点没有处理!!!T_T

253 bn.parent =newnode;254 }255 }256

257 }258

259 public voidcombine(BTNode lnode,BTNode rnode){260 if(lnode.informations.size()

270 lnode.informations.addAll(rnode.informations);271 lnode.ptr.addAll(rnode.ptr);272 for(BTNode n:rnode.ptr){273 n.parent=lnode;274 }275 lnode.parent.ptr.remove(lnode.parent.ptr.indexOf(lnode)+1);276 if(lnode.parent.parent==null&&lnode.parent.informations.size()==0){//父节点是根节点

277 lnode.parent = null; //lnode为新的根节点

278 root =lnode;279 return;280 }281 if(lnode.parent.informations.size()

286 public voidlrotate(BTNode lnode,BTNode rnode){287 lnode.informations.add(lnode.parent.informations.get(lnode.parent.ptr.indexOf(lnode)));288 lnode.parent.informations.remove(lnode.parent.ptr.indexOf(lnode));289 lnode.parent.informations.add(lnode.parent.ptr.indexOf(lnode),rnode.informations.get(0));290 rnode.informations.remove(0);291 if(rnode.ptr.size()>0){//要判断叶子节点没有孩子!

292 lnode.ptr.add(rnode.ptr.get(0));293 rnode.ptr.remove(0);294 lnode.ptr.get(lnode.ptr.size()-1).parent=lnode;295 }296

297 }298

299 public voidrrotate(BTNode lnode,BTNode rnode){300 rnode.informations.add(rnode.parent.informations.get(lnode.parent.ptr.indexOf(lnode)));301 rnode.parent.informations.remove(lnode.parent.ptr.indexOf(lnode));302 rnode.parent.informations.add(lnode.parent.ptr.indexOf(lnode),lnode.informations.get(lnode.informations.size()-1));303 lnode.informations.remove(lnode.informations.size()-1);304 if(lnode.ptr.size()>0){305 rnode.ptr.add(0,lnode.ptr.get(lnode.ptr.size()-1));306 lnode.ptr.remove(lnode.ptr.size()-1);307 rnode.ptr.get(0).parent=rnode;308 }309 }310

311 public void dManageNode(BTNode node){//叶子节点中关键字数小于n,需要继续判断兄弟节点是否饱满,是旋转还是合并

312 if(node.parent==null){313 return;314 }else{315 int x =node.parent.ptr.indexOf(node);316 if(x==0){//被删除关键字所在节点,是父节点最左边的节点时,判断右兄弟,而且肯定有右兄弟

317 if(node.parent.ptr.get(x+1).informations.size()==n){//刚脱贫,需要合并

318 combine(node,node.parent.ptr.get(x+1));319 }else if(node.parent.ptr.get(x+1).informations.size()>n){//关键字数大于最小值,丰满

320 lrotate(node, node.parent.ptr.get(x + 1));321 }else{322 System.out.println("error");323 }324 }else if(x==node.parent.ptr.size()-1){//是父节点最右边的节点时,判断左兄弟

325 if(node.parent.ptr.get(x-1).informations.size()==n){//左兄弟刚脱贫,需要合并

326 combine(node.parent.ptr.get(x-1),node);327 }else if(node.parent.ptr.get(x-1).informations.size()>n){//关键字数大于最小值,丰满

328 rrotate(node.parent.ptr.get(x-1),node);329 }else{330 System.out.println("error");331 }332 }else {//node在父节点的子节点的中间,需要先判断左兄弟,再判断右兄弟。靠,感觉判断兄弟是否饱满,还是应该写一个函数,也许可以传递两个值333 //先跟饱满的借,除非两个兄弟都刚脱贫。

334 if(node.parent.ptr.get(x-1).informations.size()>n){//左兄弟丰满

335 rrotate(node.parent.ptr.get(x - 1),node);336 }else if(node.parent.ptr.get(x+1).informations.size()>n){//右兄弟丰满

337 lrotate(node, node.parent.ptr.get(x + 1));338 }else{//左右兄弟都刚脱贫,需要合并

339 combine(node.parent.ptr.get(x-1),node);340 }341 }342 }343

344 }345

346 public void pullRLeftNode(BTNode donode,int j,BTNode node,int i){//节点删除关键字后,如果该节点有孩子,则孩子需要贡献关键字,由于孩子减少了关键字还需要向下借,一直递归到叶子。

347

348 if(node.ptr.get(0).ptr.size()>0){349 pullRLeftNode(donode,j,node.ptr.get(0),0);350 }else{351 donode.informations.add(j,node.ptr.get(0).informations.get(0));352 node.ptr.get(0).informations.remove(0);353 if(node.ptr.get(0).informations.size()

359 classBTNode{360 BTNode parent; //父节点

361 List informations = new ArrayList(); //关键字的信息

362 List ptr = new ArrayList(); //分支

363

364 publicBTNode(T information,BTNode parent){365 if(information != null){366 informations.add(information);367 this.parent =parent;368 }else{369 this.parent = null;370 }371 }372

373 booleanisLeaf(){374 return (ptr.size()==0);375 }376

377 booleanisNode(){378 return (ptr.size()!=0);379 }380

381 intinfoLength(){382 returninformations.size();383 }384

385 intptrLength(){386 returnptr.size();387 }388

389 }390

391 private static String stringInput(String inputRequest)throwsIOException{392 System.out.println(inputRequest);393 returnreader.readLine();394 }395

396 public static void main(String[] args)throwsIOException {397 System.out.println("test B - balanced tree operations");398 System.out.println("*****************************");399

400 String input;401 Integer value;402

403 do{404 input = stringInput("please select: [i]nsert, [d]elete, [s]how, [e]xit");405 switch (input.charAt(0)) {406 case 'i':407 value = Integer.parseInt(stringInput("insert: "), 10);408 tree.insert(value);409 break;410 case 'd':411 value = Integer.parseInt(stringInput("delete: "), 10);412 tree.delete(value);413 break;414 case 's':415 System.out.println(tree.perOrder(tree.root));416 break;417 //case 'h':418 //System.out.println(tree.getHeight());

419 }420 } while ((input.charAt(0) != 'e'));421 }422 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值