パブリック クラスRBNodeDemo { 公共 静的 ボイドメイン(文字列[]引数){ RBNode <整数>ノード1 = 新しい RBNode <>(1 )。 RBNode <整数> NODE2 = 新しい RBNode <>(2 )。 RBNode <整数>ノード3 = 新しい RBNode <>(3 )。 RBNode <整数>ノード4 = 新しい RBNode <>(4 )。 node1.insert(NODE2)。 node1.insert(ノード3)。 node1.insert(ノード4)。 RBNode <整数>ルート= node1.root()。 System.out.println(ルート)。 } } / ** *赤、黒の木 * / クラス RBNode <T 延び匹敵<T >> { ブール赤= 真。 Tデータ。 RBNode <T> 左; RBNode <T> 右; RBNode <T> 親。 公共 RBNode(ブール赤、Tデータ、RBNode <T>左、RBNode <T>右、RBNode <T> 親){ これは .red = 赤。 この .DATA = データ。 この .LEFT =が左; この .RIGHT = 右。 この .parent = 親。 } 公共RBNode(Tデータ){ この .DATAは= データ。 } / ** *現在のノードのルートノードを返します。 *この方法の時間計算量はO(N)であるべきです * * @Return * / 最終 RBNode <T> ルート(){ 用(RBNode <T> =ルートこの、P ;;){ IF((P = root.parent)== NULL){ // もし現在ノードの親ノードは、現在のノードが、現在のノードに戻り、直接ルート・ノードであることを意味し、空で 戻るルート。 } ルート = P; // 現在のノードは、元のノードの親ノードとなります } } / * L *の概略:ノードx Lについて * PP * / / * XY * / \ / \ * LX Y -----> X RY * / \ / \ * RyがLY LY LX * Lは、3つのことを行います。 * Yは、左の子がX、Yの右の子ノードに割り当てられている1であり、xは、親ノードの左の子ノードに割り当てられている(Y左の子ではないヌル) * 2.親ノードP×(空でない)、Yは親ノードに割り当てられ、ノードPを更新サブyは(左または右)であります * 3. Yの左の子をxに設定され、親ノードは、xとy *注:ノードの位置を移動するときは、双方向を指定することを忘れないでください * / 公共 ボイド rotateLeft(RBNode <T> X){ RBNode <T> Y、LY、P; IF(!X = ヌル!&&(Y = x.right)= NULL ){ // 右の子ノード1 xにYの左の子、およびX yは親ノードの左の子ノード(yの左の子ではないヌル)に割り当てられて // いない空の判定対象の操作を行います。yは子供を残していない場合は、右の子は、xノードにハングアップしていない IF(( = = y.left x.right LY)!= nullの){ ly.parent = X。 } // 親ノードに割り当てられた前記親ノードP X(非空)yおよび子ノードを更新Y P(左または右)である IF((P = y.parent = x.parent)== NULL ){ y.parent = NULL ; // Yは、ルートノードが直接黒に設定することが可能になる y.red = falseに。 } 他 IF(p.left == x)は{ // xは左の子ノードPである場合、Yは、ノードP左の子を回転さ p.left = Y; // yが左の子ノードpに設定されています } 他 { // X Pは、その後、Yが右の子のPに回転させ、右の子ノードである p.right = Y; // Yは右の子ノードPに設定されています } // 左の子ノードyは3に設定されているX、X親ノードyに設定されている y.left = X。 x.parent = Y。 } } / * *右旋性模式:のノードYデキストロース * PP * / / * YX * / \ / \ * X RY -----> LX Y * / \ / \ * LX RX RX RY * 3つのことをD-行います。 * 1右の子xが左の子yに割り当てられたノード、および親の右の子ノード(X右の子ではないNULL)にxおよびy 2. * P yを親が(空でない)xは親ノードに割り当てられ、子ノードは、更新は、p×(左または右)であります *、Yは親ノードyにxの3右の子であり、xは * / 公共 ボイド rotateRight(RBNode <T> Y){ RBNode <T> X、RX、P。 もし(Y!= NULL &&(X = y.left)!= NULL ){ // 1.右の子ノードXは、親ノードの右の子ノード(X右の子ではないNULL)にxとy左の子yに割り当てられ、 IF((X = RX = y.left。右)!= nullの) rx.parent = Y。 // 2.親ノードのY P(非空)pの更新がX(左または右)しながらXは親ノード、子ノードに割り当てられた // 2。簡単に説明するとは、左右の垂下に連結されています問題 のiF((= P = x.parent y.parent)== NULL){ // 親がNULLであるか否かを判定する x.parent = NULL ; x.red = falseに ; // ?ここでは、このコード右の場所 } 他の IF(p.right == Y)は{ // 判決が残っている... p.rightを= X; } 他 { // そうでない場合は右 p.left = X。 } // 右の子3は、X、Yとして定義され、Yは、親ノードXに設定されている x.right = Y。 y.parent = X。 } } / ** *スタートはルートノードの比較からトラバース * * @param X * / 公共 ボイド挿入(RBNode <T> X){ RBNode <T>ルート= ルート()。 インサート(ルート、X)。 // TODOの重量バランス... balanceInsertion(根、X-); } / ** 次のように*様々な状況があります。 オリジナルの木が空の場合* 1、根== X、ルートにだけ必要が黒に設定することができます * 2.親ノードが黒であれば、あなたが必要足し、結果的に行うことはできません * 3.次の3つの場合は、より複雑で、回転や変色が必要です 親ノードおよびその伯父ノード(別の祖父母に子ノード)に*(1)は赤であります; *(2)は、親ノードが赤、黒の叔父ノードに挿入され、右の子ノードに挿入された親ノードです。 *(3)ノードの親が赤で挿入し、叔父のノードが黒で、挿入ノードは、その親の左の子です。 * * @paramのルート * @param ×8 ----> 11 ----> 14 -----> 13 -----> 1 ----> 2 -----> 5 -----> 9 ----> X = 4 * / プライベート ボイド balanceInsertion(RBNode <T>根、RBNode <T> X){ } プライベート ボイドインサート(RBNode <T>根、RBNode <T> X){ 場合(root.data.compareTo(x.data)<0 ){ 場合(root.right == NULL ){ root.right = X。 x.parent = ルート。 } 他{ インサート(root.right、X)。 } } 他{ 場合(root.left == NULL ){ root.left = X。 x.parent = ルート。 } 他{ インサート(root.left、X)。 } } } @オーバーライド 公共の文字列のtoString(){ リターンは + "赤="(赤"赤": "ブラック"?)+ "データ=" + データ。 } }
で継続するには......