java实现红黑树
好久没更新了 今天发个有点技术含量的
java实现红黑树代码
下面是代码
由于我才疏学浅 和自己对于特别复杂的问题的讲解能力问题 可能不能特别清晰明了的为大家讲解清晰 后面会抽时间整理思路 单独出一篇来讲这个原理
在这之前 为大家推荐 自己在学习过程中找到的比较好的讲解文章
https://www.jianshu.com/p/96e652ccf720
这是链接
这要求我们对树 平衡树 有一定的了解 不会的可以自己在网上找些教程 这很简单
下面我们上代码
此代码为本人原创
不想网上有些地方的直接复制
对大家应该有不错的参考意义
我想说的是 要理解原理 参透原理 在纸上完全规划好实现的各个方面 然后在进行编码调试
OK 下面看代码
1 package com.company; 2 3 import java.util.ArrayDeque; 4 import java.util.LinkedList; 5 import java.util.Queue; 6 import java.util.Stack; 7 8 public class RedBlackTree { 9 10 node Head; 11 12 13 14 public void NLR(){ 15 // 先序便利 16 NLr(Head); 17 18 } 19 20 private void NLr(node now){ 21 // 先序便利 22 if(now.isNil==false){ 23 System.out.print(now.value +","); 24 if (now.color==node.RED){ 25 System.out.println("Red"); 26 }else { 27 System.out.println("Black"); 28 } 29 NLr(now.nextLeft); 30 NLr(now.nextRight); 31 32 33 }else{ 34 35 } 36 37 } 38 public void LNR(){ 39 // 先序便利 40 LNr(Head); 41 42 } 43 44 private void LNr(node now){ 45 // 先序便利 46 if(now.isNil==false){ 47 48 LNr(now.nextLeft); 49 System.out.print(now.value +" "); 50 if (now.color==node.RED){ 51 System.out.println("Red"); 52 }else { 53 System.out.println("Black"); 54 } 55 LNr(now.nextRight); 56 57 58 }else{ 59 60 } 61 62 } 63 64 65 public void LOT(){ 66 // 先序便利 67 LOt(Head); 68 69 } 70 71 private void LOt(node now){ 72 // 层序遍历 73 Queue<node> arr = new LinkedList<>(); 74 arr.add(Head); 75 while (arr.isEmpty()==false ){ 76 node x = arr.poll(); 77 if(x.isNil){ 78 79 }else { 80 System.out.print(x.value + " "); 81 if (x.color==node.RED){ 82 System.out.println("Red"); 83 }else { 84 System.out.println("Black"); 85 } 86 if (x.getNextLeft().isNil){ 87 88 }else { 89 arr.add(x.getNextLeft()); 90 } 91 92 if (x.getNextRight().isNil){ 93 94 }else { 95 arr.add(x.getNextRight()); 96 } 97 } 98 } 99 100 } 101 102 public RedBlackTree() {//A constructor 103 Head = new node(); 104 Head.isNil = true; 105 } 106 107 private static node getNIL(){//Get a NIL node 108 node a = new node(); 109 a.isNil = true; 110 a.color = 2; 111 return a; 112 } 113 114 115 public static void main(String[] args) { 116 // RedBlackTree c = new RedBlackTree(); 117 // int[] a; 118 // a= new int[]{50,20,60,10,30,70,40}; 119 // for (int i=0;i<a.length;i++){ 120 // c.addNode(a[i]); 121 // } 122 // c.Put(); 123 124 125 test(); 126 } 127 128 129 public void chageNode(int Old, int New){// Modification method 130 deletNode(Old); 131 addNode(New); 132 133 } 134 135 136 public int checkNode(int n){//Query method, with this number, returns 0, otherwise returns-1 137 if (getNode(n)!=null){ 138 return 0; 139 }else{ 140 return -1; 141 } 142 } 143 144 145 public void Put() {//Output method 146 PUT(Head); 147 System.out.println(); 148 } 149 150 private void PUT(node head) {//Specific output method 151 if (head == null) {//In the sequence traversal 152 return; 153 } 154 if (head.isNil == false) { 155 PUT(head.nextLeft); 156 System.out.print(head.getValue()+" ");//A few Spaces in between 157 PUT(head.nextRight); 158 } else { 159 return; 160 } 161 } 162 163 164 public int addNode(int n) {//Add methods 165 return addTwo(n); 166 //Failure returns -1 167 } 168 169 private int addTwo(int n) {//Add a concrete implementation of the method 170 //Find the insert node 171 node to; 172 to = Head; 173 node parent = node.getNIL();//Initialize the parent node to be null 174 while (to.isNil != true) { 175 parent = to;//You need to bind the parent node 176 177 if (n > to.value) { 178 to = to.nextRight; 179 } else { 180 181 if (n == to.value) { 182 return -1;//Returns -1 if this number exists 183 } else { 184 to = to.nextLeft; 185 } 186 } 187 } 188 //The parent node has been found 189 //Insert and bind the parent node 190 to.clone(new node(n)); 191 192 to.setParent(parent);//Binding parent node 193 //The node is now found and the insert is complete 194 195 196 addFixup(parent, to);//Check balance to maintain balance 197 198 return -1; 199 } 200 201 202 private int addFixup(node parent, node n) {//Added method to maintain balance 203 //Judge each situation 204 205 if (n.getValue() == Head.getValue()) {//Add nodes as head nodes 206 Head.setColor(2); 207 Head.setParent(null);//Head node condition 208 return 0; 209 } 210 211 if (parent.getColor() == node.BLACK) {//The parent node is black and ends directly without adjustment 212 return 0; 213 } 214 215 if (parent.getColor() == node.RED) { 216 //When the father is red, we need the uncle node. 217 //Get the uncle node and grandfather node first 218 node gp = parent.getParent();//Get grandfather node 219 node uncle;//Uncle node 220 221 if (parent == gp.getNextLeft()) {//Get Uncle Node 222 uncle = gp.getNextRight(); 223 } else { 224 uncle = gp.getNextLeft(); 225 } 226 //The node has been acquired to judge the situation. 227 //Determined that the father is red 228 if (uncle.getColor() == node.RED) { 229 //Paternal red uncle red condition 230 //Father Hong, uncle Hong, father and uncle are both black, and their grandfather is black for the new N. 231 uncle.setBlack(); 232 parent.setBlack(); 233 gp.setRed(); 234 235 236 return addFixup(gp.getParent(), gp);//Leveling up 237 } else { 238 //Paternal red uncle black condition 239 //Judge the direction 240 if (gp.getNextLeft() == parent && n == parent.getNextLeft()) { 241 // PN Same as left 242 parent.setBlack(); 243 gp.setRed();//Change color first and then rotate to prevent the relationship from getting wrong after rotation. 244 node i = new node(); 245 i.clone(parent.getNextRight());//Why do you do this temporarily? please refer to the clone method in node. 246 parent.getNextRight().clone(gp); 247 parent.getNextRight().setNextLeft(i); 248 i.setParent(parent.getNextRight()); 249 gp.clone(parent); 250 // return addFixup(gp.parent,gp); 251 return 0;//balance 252 } 253 254 if (gp.getNextRight() == parent && parent.getNextRight() == n ) { 255 //PN Same as right 256 parent.setBlack(); 257 gp.setRed(); 258 node i = new node(); 259 i.clone(parent.getNextLeft());//Save the node 260 parent.getNextLeft().clone(gp); 261 parent.getNextLeft().setNextRight(i); 262 i.setParent(parent.getNextLeft()); 263 gp.clone(parent); 264 // return addFixup(gp.parent,gp); 265 return 0;//Rotation completed and leveled successfully. 266 } 267 268 if (gp.getNextLeft() == parent && parent.getNextRight() == n) { 269 //P left N right 270 node ddd = new node(); 271 ddd.clone(n.nextLeft); 272 parent.setNextRight(ddd); 273 ddd.setParent(parent); 274 n.getNextLeft().clone(parent); 275 // n.getNextRight().setNextLeft(getNIL()); 276 277 parent.clone(n); 278 //Complete the right-hand rotation and now PN is the same as the right. 279 parent.setBlack(); 280 gp.setRed(); 281 parent = gp.nextLeft; 282 n = parent.nextLeft; 283 node i = new node(); 284 i.clone(parent.getNextRight());//Why do you do this temporarily? please refer to the clone method in node. 285 parent.getNextRight().clone(gp); 286 parent.getNextRight().setNextLeft(i); 287 i.setParent(parent.getNextRight()); 288 gp.clone(parent); 289 // return addFixup(gp.parent , gp); 290 291 return 0; 292 //Right-hand rotation complete. Leveling complete. 293 } 294 295 if (gp.getNextRight() == parent && parent.getNextLeft() == n) { 296 //P right N left 297 node ddd = new node(); 298 ddd.clone(n.nextRight); 299 parent.setNextLeft(ddd); 300 ddd.setParent(parent); 301 n.getNextRight().clone(parent); 302 // n.getNextRight().setNextLeft(getNIL()); 303 304 parent.clone(n); 305 //Complete the right-hand rotation and now PN is the same as the right. 306 parent.setBlack(); 307 gp.setRed(); 308 parent = gp.nextRight; 309 n = parent.nextRight; 310 node i = new node(); 311 i.clone(parent.getNextLeft());//Save the node 312 parent.getNextLeft().clone(gp); 313 parent.getNextLeft().setNextRight(i); 314 i.setParent(parent.getNextLeft()); 315 gp.clone(parent); 316 // return addFixup(gp.parent , gp); 317 //Complete left-handed rotation 318 return 0; 319 } 320 //The addition situation has been considered. 321 } 322 } 323 return -1; 324 } 325 326 327 public node getNode(int n) {//Get node 328 //Find Node 329 if (Head.getValue() == n) { 330 return Head; 331 } 332 333 node to = Head; 334 while (to.isNil == false && to.getValue() != n) { 335 if (to.getValue() > n) { 336 to = to.nextLeft; 337 } else { 338 to = to.nextRight; 339 } 340 } 341 if (to.getValue()==n) {//Whether the search was successful or not 342 return to; 343 } else { 344 return null; 345 } 346 } 347 348 349 public int deletNode(int x) { 350 //Delete nod 351 // Get the node first, that is, the node to be deleted 352 node n = getNode(x); 353 return deletNodeTwo(n);//Delete nod 354 355 } 356 357 358 private int deletNodeTwo(node n) { 359 //It is not necessary to delete a node to determine whether it exists or not. 360 if (n == null) { 361 //It doesn't exist. 362 return -1; 363 } 364 if (n.getNextRight()==null){//Prevent null pointers from appearing 365 n.nextRight=getNIL(); 366 } 367 368 if (n.nextLeft==null){ 369 n.nextLeft=getNIL(); 370 } 371 //It is not empty now and it is a normal node. 372 //Deal with the case without child nodes first 373 if (n.getNextLeft().isNil && n.getNextRight().isNil) { 374 //No child node 375 //To delete as red 376 if (n.getColor() == node.RED) { 377 n.setValue(-1); 378 n.isNil = true;//Red no child node is deleted directly. 379 n.setBlack(); 380 return 0;//There is no need to maintain balance if the deletion is successful. 381 } else { 382 //Black no child node 383 //Directly delete the dimension level of the successor NIl node 384 n.isNil = true; 385 n.setValue(-1); 386 //`tain balance with n nodes as unbalanced points 387 return deletFixup(n); 388 } 389 } 390 391 392 //Now there is a child node. 393 if ( (n.getNextRight().isNil && n.getNextLeft().isNil == false) || 394 (n.getNextRight().isNil==false && n.getNextLeft().isNil) ){ 395 //Get child nodes 396 node c; 397 if (n.getNextLeft().isNil==false){ 398 c=n.getNextLeft(); 399 }else { 400 c=n.getNextRight(); 401 } 402 //Child nodes have been obtained 403 //Judge in the light of each situation 404 if (n.getColor()==node.RED){ 405 n.clone(c); 406 return 0; 407 //N is red c must be black direct replacement 408 }else { 409 //N is black 410 if (c.getColor()==node.RED){ 411 //If n is black, it is red. 412 n.clone(c); 413 n.setBlack(); 414 return 0; 415 //Replace discoloration 416 }else { 417 //N is sunspot and black is black. 418 n.clone(c);//Replacement leveling 419 return deletFixup(n); 420 } 421 422 } 423 } 424 //The deletion of two child nodes is now handled. 425 if (n.getNextLeft().isNil==false && n.getNextRight().isNil==false){ 426 //Find the successor node and then delete the successor node 427 node max=getMax(n); 428 //Get successor node 429 n.setValue(max.value);//Replace 430 //Delete 431 return deletNodeTwo(max); 432 //Balance 433 } 434 return -1; 435 } 436 437 private int deletFixup(node n){ 438 //The parameter is the node to be balanced. 439 if (n==Head){ 440 //There is no need to operate when the balance node is the root node. 441 return 0; 442 } 443 444 //Non-root node 445 //The subsequent operation is to get the relevant nodes. 446 node S,SL,SR,U,GP,Parent; 447 Parent=n.getParent(); 448 if (n==Parent.getNextLeft()){ 449 S=Parent.getNextRight(); 450 }else { 451 S=Parent.getNextLeft(); 452 } 453 SL=S.getNextLeft(); 454 SR=S.getNextRight(); 455 GP=Parent.getParent(); 456 if (GP!=null) { 457 if (Parent == GP.getNextLeft()) { 458 U = GP.getNextRight(); 459 } else { 460 U = GP.getNextLeft(); 461 } 462 } 463 //Related nodes have been obtained 464 //Related situation analysis 465 466 if (S.getColor()==node.BLACK){ 467 return SisBlack(Parent,S,SL,SR); 468 }else { 469 //Brother node is red 470 //The brothers are on the left and on the right. 471 if (S ==Parent.getNextLeft()) { 472 //The brother node is on the left. 473 S.setBlack(); 474 Parent.setRed(); 475 node i=new node(); 476 i.clone(S.getNextRight()); 477 S.getNextRight().clone(Parent); 478 S.getNextRight().setNextLeft(i); 479 i.setParent(S.getNextRight()); 480 Parent.clone(S); 481 //Complete rotation 482 Parent=Parent.getNextRight(); 483 S=Parent.getNextLeft(); 484 return SisBlack(Parent,S,S.getNextLeft(),S.getNextRight()); 485 }else { 486 S.setBlack(); 487 Parent.setRed(); 488 node i=new node(); 489 i.clone(S.getNextLeft()); 490 S.getNextLeft().clone(Parent); 491 S.getNextLeft().setNextRight(i); 492 i.setParent(S.getNextLeft()); 493 Parent.clone(S); 494 Parent=Parent.getNextLeft(); 495 S=Parent.getNextRight(); 496 return SisBlack(Parent,S,S.getNextLeft(),S.getNextRight()); 497 } 498 499 } 500 501 } 502 503 504 private int SisBlack(node Parent,node S,node SL,node SR){ 505 //The sibling nodes are black 506 if (SL==null){ 507 SL=getNIL(); 508 } 509 510 if (SR==null){ 511 SR=getNIL(); 512 } 513 if (SL.getColor()==node.BLACK && SR.getColor()==node.BLACK){ 514 //All sibling nodes are black 515 if (Parent.getColor()==node.BLACK){ 516 //The parent node is black 517 S.setRed(); 518 return deletFixup(Parent); 519 520 }else { 521 //The father of red 522 Parent.setBlack(); 523 S.setRed(); 524 //The father is black and the brother is red 525 return 0; 526 } 527 }else { 528 //Not all sibling nodes are black 529 //There are four cases 530 531 if (S==Parent.getNextLeft() && SL.getColor()==node.RED){ 532 return SisLAndSLisR(Parent,S,SL); 533 } 534 535 if (S==Parent.getNextRight() && SR.getColor()==node.RED){ 536 //S is the right and the right is red 537 return SisRAndSRisR(Parent,S,SR); 538 } 539 540 if (S==Parent.getNextLeft() && SL.getColor()==node.BLACK){ 541 //S is the left subson S is the left subson black and the right subson red 542 SR.setBlack(); 543 S.setRed(); 544 //First left-handed 545 node i=new node(); 546 i.clone(SR.getNextLeft()); 547 SR.getNextLeft().clone(S); 548 SR.getNextLeft().setNextRight(i); 549 i.setParent(SR.getNextLeft()); 550 S.clone(SR); 551 SL=S.getNextLeft(); 552 //The new left child 553 //Left child and left is red 554 return SisLAndSLisR(Parent,S,SL); 555 } 556 557 if (S==Parent.getNextRight() && SR.getColor()==node.BLACK){ 558 //S is the right and the right is black and the left is red 559 if (SL.getNextRight()==null){ 560 SL.nextRight=getNIL(); 561 } 562 563 if (SL.getNextLeft()==null){ 564 SL.nextLeft=getNIL(); 565 } 566 SL.setBlack(); 567 S.setRed(); 568 node i=new node(); 569 i.clone(SL.getNextRight()); 570 SL.getNextRight().clone(S); 571 SL.getNextRight().setNextLeft(i); 572 i.setParent(SL.getNextRight()); 573 S.clone(SL); 574 SR=S.getNextRight(); 575 //The new right is red 576 return SisRAndSRisR(Parent,S,SR); 577 } 578 579 } 580 return -1; 581 } 582 583 584 private int SisLAndSLisR(node Parent,node S,node SL){ 585 S.setColor( Parent.getColor()); 586 Parent.setBlack(); 587 SL.setBlack(); 588 node i=new node(); 589 i.clone(S.getNextRight()); 590 S.getNextRight().clone(Parent); 591 S.getNextRight().setNextLeft(i); 592 i.setParent(S.getNextRight()); 593 Parent.clone(S); 594 //P and S discoloration, the left hand turns black, and the right hand turns black 595 return 0; 596 } 597 598 599 private int SisRAndSRisR(node Parent,node S,node SR){ 600 //S is the right and the right is red 601 SR.setBlack(); 602 S.setColor(Parent.getColor()); 603 Parent.setBlack(); 604 node i=new node(); 605 i.clone(S.getNextLeft()); 606 S.getNextLeft().clone(Parent); 607 S.getNextLeft().setNextRight(i); 608 i.setParent(S.getNextLeft()); 609 Parent.clone(S); 610 return 0; 611 } 612 613 614 //Find the successor node method 615 private static node getMax(node a){ 616 //Parameter is the node to be deleted with two child nodes 617 a=a.getNextLeft(); 618 while (a.getNextRight().isNil==false){ 619 a=a.getNextRight(); 620 } 621 622 return a; 623 //Return successor node 624 } 625 626 public static void test(){ 627 RedBlackTree tree = new RedBlackTree(); 628 629 /* 630 20 631 12 1 9 2 0 11 7 19 4 15 18 5 14 13 10 16 6 3 8 17 632 */ 633 int[]data ={12,1,9,2,0,11,7,19,4,15,18,5,14,13,10,16,6,3,8,17}; 634 // String df = "9 4 1 0 2 3 6 5 7 8 14 12 11 10 13 18 17 19"; 635 636 637 // System.out.println(data.length); 638 for(int i = 0;i<data.length;i++){ 639 tree.addNode(data[i]); 640 // tree.LNR(); 641 // System.out.println(data[i]); 642 } 643 tree.LOT(); 644 645 } 646 } 647 648 649 class node { 650 651 static final int RED = 1; 652 static final int BLACK = 2; 653 static node NIL; 654 int value; 655 node nextLeft;//left 656 node nextRight;//right 657 node parent;//parent node 658 boolean isNil; 659 int color;//1 is red// 2 is black 660 661 public node() {//The default color is red 662 color = 2; 663 isNil = false; 664 } 665 666 public node(int n) { 667 668 value = n; 669 color = 1; 670 this.isNil = false; 671 // this.toNIL(); 672 } 673 674 public static node getNIL() { 675 node a = new node(); 676 a.isNil = true; 677 a.color = 2; 678 return a; 679 } 680 681 public void setRed() { 682 this.color = RED; 683 } 684 685 public void setBlack() { 686 this.color = BLACK; 687 } 688 689 public void clone(node a) {// Cloning methods all clones except the parent node 690 if (a==null){ 691 this.isNil=true; 692 return; 693 } 694 if (a.isNil) { 695 this.isNil = true; 696 } else { 697 this.value = a.value; 698 this.color = a.color; 699 if (a.getNextLeft() == null) { 700 a.nextLeft = getNIL(); 701 702 }else { 703 704 } 705 this.nextLeft = a.nextLeft; 706 this.nextLeft.setParent(this); 707 if (a.getNextRight() == null) { 708 a.nextRight = getNIL(); 709 }else { 710 711 } 712 this.nextRight = a.nextRight; 713 this.nextRight.setParent(this); 714 715 716 this.isNil = a.isNil; 717 } 718 } 719 720 public void setNil(boolean nil) { 721 isNil = nil; 722 } 723 724 public int getValue() { 725 return value; 726 } 727 728 public void setValue(int value) { 729 this.value = value; 730 } 731 732 public int getColor() { 733 return color; 734 } 735 736 public void setColor(int color) { 737 this.color = color; 738 } 739 740 public node getNextRight() { 741 return nextRight; 742 } 743 744 public void setNextRight(node nextRight) { 745 this.nextRight = nextRight; 746 } 747 748 public node getNextLeft() { 749 return nextLeft; 750 } 751 752 public void setNextLeft(node nextLeft) { 753 this.nextLeft = nextLeft; 754 } 755 756 public node getParent() { 757 return parent; 758 } 759 760 public void setParent(node parent) { 761 this.parent = parent; 762 } 763 764 private void toNIL() { 765 if (this.getNextRight() == null) { 766 this.nextRight = new node(); 767 this.nextRight.setBlack(); 768 this.getNextRight().isNil = true; 769 } 770 771 if (this.getNextLeft() == null) { 772 this.nextLeft = new node(); 773 this.nextRight.setBlack(); 774 this.getNextLeft().isNil = true; 775 776 } 777 } 778 }
再次声明 原创 原创 原创 引用请注明出处
有瑕疵的地方请大家予以指正
感谢
后面会更新原理讲解 可能会有点慢 感谢
个人作品,
如有错误,请指出;
如要转载,请注明出处。
三克油。。