オリジナル:黒ツリーの深さの分析とJavaの実装では、我々は赤黒木のJava実装は、元のテキストを見に行くことができるかどうかを確認するために、オリジナルでいくつかのミスを犯しました。
赤黒木は平衡二分探索木の一種です。黒の木を理解するために、我々は、二分探索木で開始する必要があります。
BST
バイナリ検索ツリー(バイナリ検索ツリー、BSTと呼ばれる)は、バイナリツリーで、その左の子の値は、親ノードの値は、親ノードと右のノードの値よりも大きい場合よりも小さくなっています。その高さは、その検索効率を決定します。理想的なケースでは、バイナリ検索ツリー検索欠失は、O(logN個)の時間計算量を変更し(Nはノードの数である)、最悪の場合はO(N)です。それはlogN個+ 1の高さだとき、私たちは二分探索木がバランスしていることを言います。
BSTのルックアップ操作
T key = a search key
Node root = point to the root of a BST
while(true){
if(root==null){
break;
}
if(root.value.equals(key)){
return root;
}else if(key.compareTo(root.value)<0){
root = root.left;
}else{
root = root.right;
}
}
return null;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
現在の第1のノードと比較して、BSTを見つけることと、プログラムから見ることができます。
- それらが等しい場合、現在のノードが返されます。
- 現在のノードよりも少ないが、現在のノードの左探し続ける場合。
- 現在のノードよりも大きいが、現在のノードの右側で検索された場合。
現在のノードが空であるか、またはポインタが対応するノードを見つけるまで、プログラムを終了する検索します。
BSTの挿入操作
Node node = create a new node with specify value
Node root = point the root node of a BST
Node parent = null;
//find the parent node to append the new node
while(true){
if(root==null)break;
parent = root;
if(node.value.compareTo(root.value)<=0){
root = root.left;
}else{
root = root.right;
}
}
if(parent!=null){
if(node.value.compareTo(parent.value)<=0){//append to left
parent.left = node;
}else{//append to right
parent.right = node;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
挿入は、第1の循環親ノードを介して挿入するノード、親ノードを検索し、ロジックを検索する、などの右大、小左の大きさの比です。親ノードと比較して親を発見した後、小さな右側の大きい親ノードに挿入された左ノードの親ノードに挿入されています。
BSTの削除
二分探索木では3通りの方法で指定されたノードpを削除します。
- 左と右の子は何のpノードません、対応する親ノードポインタを変更し、ノードを削除します。
- 唯一の左の子ノードp(右の子)、親とpは、pは子(右の子)を入れたまま接続され、その後、削除のp。
- 子供について見つけ、存在するために、P sの即時の前任者を、それがSと右の子のPの右の子に接続され、右端のノード内のpサブツリーのルートノードの左の子である、Pの親接続された子ノードとPを残し、その後、削除のp。
//从二叉查找树中删除指针p所指向的结点
if(p.right == null) //p的右子树为空
{
p = p.left;
}
else if(p.left == null) //p的左子树为空
{
p = p.right;
}
else //左右子树均不空
{
BSTNode s = p.left; //左孩子
while(s.right != null) //寻找结点p的中序前驱结点,
{ //也就是以s为根结点的子树中最右的结点
s = s.right;
}
s.right = p.right; //p的右孩子和s的右孩子相连
p = p.left; //p的左孩子和p的父节点相连
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
RBTree
しかし、BST質問です:ツリー内の挿入結果の数が傾いたときに、異なる挿入順序は、ツリーの高さは同じではありませんつながるが、木の効率に直接影響は、ツリーの高さを発見します。LOGN理想的な高さは、スラッシュ上のすべてのノードは、ツリーの高さはNであるように、最悪の場合には、
新しいツリーに基づいてBST既存の問題-生成平衡二分探索木(バランスBST)。ツリーの挿入と削除時刻バランス動作を回転させることにより、高さlogN個のままであろう。前記2つの代表的なAVLツリーは、バランスツリーと赤黒木です。AVL木の追求グローバルバランスにおける実用化の追求として、パフォーマンスの低下の挿入および削除が得られ、地元のバランス赤黒木の完全公正スケジューラ、高分解能タイマーであるなどのLinuxカーネルとして、(赤黒木は、RBTreeをいいます。) EXT3ファイルシステム、などのJava TreeMapのとTreeSetの、C ++ STLのマップ、マルチマップ、マルチセット、など様々な言語のライブラリーは、JavaのHashMap 8 RBTreeも長いリストを置き換えるために使用されます。
RBTree定義
次のようにRBTreeが定義されて:
- ノードは、黒または赤、任意の色を有しています。
- ルートノードは黒です。
- 二つの連続した赤のノードは、親と子ノードとの間で発生することはできません。
- その子孫の任意のリーフノードへトラバースノードダウン、黒は等しくなければならそこを通ってノードの数。
- 空のノードは黒であると考えられます。
次のようなデータ構造で表されます:
class Node<T>{
public T value;
public Node<T> parent;
public boolean isRed;
public Node<T> left;
public Node<T> right;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
RBTree理論またはツリー内のBST、それは[logN個+ 1 logN個(極端なケースの下に表示されることがツリーRBTreeの高い高さを保証するBSTに挿入および削除操作のツリーのバランスを維持します)2 * logN個に達しますが、出会いに、実際には難しいです。このようなRBTreeの複雑さは常にO(logN個)とても近い理想的なのBSTまでの時間を見つけます。削除、挿入操作RBTree時間の複雑さも、O(logN個)です。
RBTreeのルックアップ操作は、BSTの操作を見つけることです。
挿入操作RBTree
BSTとのRBTree挿入挿入モードが同じであるだけで挿入した後、あなたは(ここと呼ばれる木と色復元操作を回転させる必要がある、木の不均衡につながる可能性が挿入修理それはと一致しているのでこと、) RBTreeの定義。
新しいノードは、赤色に挿入され、それらが親ノードの色は、次に、修復操作黒色である場合、修復操作の終了インサート。換言すれば、親赤ノードは、修復操作を挿入する必要がある場合にのみ。
挿入修復操作は、以下の3つの条件に分かれています:
操作-caseを挿入1
ケース1:新たに挿入されたノード叔父赤ノード。
このとき、操作は、親ノードとノードの色と祖父母叔父を入れ替え、その結果、ミートRBTReeの定義。以下は、ノードAの完了後の動作は、新しいノードになります。親ノードAのノードが黒でない場合、修復操作を行うことを続けます。
挿入は-case 2
ケース2:挿入新しいノードが空のノードの叔父、祖父母ノードと親ノードであり、新しいノードは、対角線上にあります。
このとき、動作は、右利きの操作ノードB、ノードA及び親と互換色。修理作業の高さによってRBTReeと色は赤黒木の定義と一致しています。B及びCは、ノードの右ノードである場合に限り、操作になるように左側その上に。
挿入は-case 3
ケース3:叔父ノードは空で、祖父母ノード、親ノードと新しいノードがスラッシュではありません。
このとき、操作があるので、ケース2からケース3に変換することを、左ノードC、およびライン上のケース2について、次に動作処理。ケース2は、色交換作業の右利きの操作で作られており、目的を達成します。ツリーは、図の構造の鏡像である場合のみ、対応する左回りに右必要、左回り右回りにします。
事業の概要を挿入
修復操作が関与ノード一度ルートノード動作に戻って、中に挿入された後、赤黒木、修復操作端部の定義と一致しています。その理由は、親ノード、叔父、祖父母ノードとなり、色の変化のために、不均衡祖父母ノード(赤黒木定義3)が発生することがあり、操作ケース1バックアップすることによるものです。このときバックアップ、出発点として調整祖父母である必要性は、ルート・ノードまで、ルートノードの定義によれば、常に黒です。
RBTreeの削除
削除最初にする必要が削除操作のBSTで行う必要削除した後、削除、修復への操作を、木がバランスされ、赤、黒の木の高さの定義を満たす、赤黒木の定義を満たしています。
修復操作を削除するには、削除することは黒のみのノード向けられている条IV、黒のノードはメイクを削除されたとき、ツリー全体がRBTreeの定義を満たしていませんが。実行する必要性を処理することで上から出向に黒兄弟ノードない兄弟ノードが黒出向することはできないがあれば、それは唯一の赤のあるツリー全体のラインを作り、各レベルで黒ノードを引き、バックアップ追跡することができ、黒の木を定義します。
あなたが削除したノードの顔に修復操作を削除すると、修復作業が完了し、赤ノードまたはルートノードが到着です。
削除修復操作は4例に分かれています。
削除-case 1
ケース1:削除する兄弟ノードは赤のノードです。
兄弟は、それが親ノードにノードを兄弟に上昇する必要があるので、赤のノードが黒のノードに出向することができない時間なので兄弟が赤くされているので、定義RBTreeによって、の兄弟の子ノードが黒であることから、次のことができ、子ノードが出向します。
こうして変換されたケース1は、一種類の場合には後ケース2、ケース3、または4になった後。左兄弟または右の操作を行うための操作の必要性、そして親ノード変更色まで、子供の兄弟が元の親ノードの右の子として回転左。
-case 2削除
ケース2:ノードを削除する兄弟ノードは黒であり、子ノードの兄弟は黒です。
ノードの兄弟子および兄弟ノードが黒であるので、赤兄弟ノードであってもよいが、親ノードの兄弟ノードが黒と赤とすることができるので、ノードAに必要な時間は、新しい親ノードとなり、上向きの継続します調整ツリー全体の色が定義RBTree片とアップ満たすまで。
削除-case 3
ケース3:ノードを削除する兄弟ノードが黒ノードであり、左の子ノードの兄弟が赤左兄弟ならば、右の子は、その後、(右の兄弟の場合である)黒であります兄弟は、左の子は黒で、右の子が赤です。私はそれを理解し、ノードを削除するために近づくことは赤です。
このとき、動作は、ノードを昇順赤旋回で行われ、その後、親ノードの元の色に変換し、ケース4に変換されます。
削除-case 4
ケース4:ノードの兄弟を削除するノードが黒であり、左兄弟ノードが左の子が赤である場合兄弟の右の子には、赤(右の兄弟の場合)です。それは十分に離れている赤です。
ノードの下に削除されるべきであり、このときの動作は上昇、回転、色変換を行う兄弟ノードDであり、D Bが親ノードであり、左側の子C D Bは今右の子になり、右の子Dは赤色になります黒。
削除操作の概要
赤黒木は、最も複雑な操作で削除し、複雑な場所があるという木の色が定義を満たしていることを保証するために、黒の兄弟ノードからの出向に行くとき、どのように黒のノードを削除したとき。そのため、赤兄弟出向の彼は親ノードに上昇したように、これが唯一の回転により動作することができ、黒のノードではなく、それが赤のノードであるので、その子ノード黒で、出向することができます。
兄弟ノードのために黒のノードが処理された3つのケースに分けることができるされて、ケース1は:兄弟ノードの子ノードは、直接ノードの兄弟ことができる赤、そのような部分の色は黒、赤、黒である場合、ツリーは、に沿ったものです定義。しかし、木の全体の作品は、必ずしも赤黒木の定義に沿って、私たちは上向きの遡及を調整し続ける必要がされていません。
ケース2は、次のとおりです。左と右のダークレッドの兄弟の子ノード。ケース3は、次のとおりです。右の子ノードは、赤(ランダムに左の子ノード)の兄弟です。我々は、削除された黒のノードを確保するように、第二の場合は、第三ケースなり、右の兄弟ノード黒、赤兄弟ノードのためのこの時間は、ノードは、2つの黒のノードを行うためにアウト出向することができる回転させることによって開始することができます、ツリー全体または黒のノードの数が変化していないため、赤黒木の定義を満たします。
オリジナル:黒ツリーの深さの分析とJavaの実装では、我々は赤黒木のJava実装は、元のテキストを見に行くことができるかどうかを確認するために、オリジナルでいくつかのミスを犯しました。
赤黒木は平衡二分探索木の一種です。黒の木を理解するために、我々は、二分探索木で開始する必要があります。