JAVAコアナレッジポイントのデータ構造:概要の概要

1.1。スタック

スタックは、挿入と削除を、スタックの最上位と呼ばれるテーブルの最後である1つの位置のみに制限するテーブルです。ラストインファーストアウト(LIFO)です。スタックには、プッシュ(スタックにプッシュ)とポップ(プル)の2つの基本操作しかありません。前者は挿入と同等であり、後者は最後の要素の削除と同等です。
ここに写真の説明を挿入

1.2。キュー

キューは特別な線形テーブルです。特別な機能は、テーブルの前(前)でのみ削除操作を許可し、テーブルの後ろ(後)で挿入を許可することです。スタックと同様に、キューは対象となる操作です。限界の線形表。挿入操作を実行する端をキューの終わりと呼び、削除操作を実行する端をキューの先頭と呼びます。
ここに写真の説明を挿入

1.3。リンク

リンクリストはデータ構造であり、配列と同じレベルです。たとえば、Javaで使用するArrayListは配列に基づいています。LinkedListの実現原理はリンクリストです。リンクリストはループする場合は効率的ではありませんが、挿入および削除する場合には明らかな利点があります。
ここに写真の説明を挿入

1.4。ハッシュテーブル

ハッシュテーブル(ハッシュテーブル、ハッシュテーブルとも呼ばれます)は検索アルゴリズムです。リンクリスト、ツリー、その他のアルゴリズムとは異なり、ハッシュテーブルアルゴリズムは一連のキーワードを必要としません(キーワードは特定のデータ要素です)。データ項目の値は、データ要素の比較操作を識別するために使用されます。

散列表算法希望能尽量做到不经过任何比较,通过一次存取就能得到所查找的数据元素したがって、各キーがハッシュテーブル内の一意の保存場所に対応するように、データ要素の保存場所とそのキー(キーで表される)の間に明確な対応を確立する必要があります。したがって、検索するときは、この対応に従って、ハッシュテーブル内の指定されたキーワードの位置を見つけるだけです。この対応はハッシュ関数と呼ばれます(h(key)で表すことができます)。

ハッシュ関数の作成に使用される方法は次のとおりです。
(1)直接アドレス指定方法:キーワードまたはキーワードの線形関数値をハッシュアドレスとして使用します。
つまり、h(key)= keyまたはh(key)= a * key + bです。ここで、aとbは定数です。
(2)数値解析法
(3)二乗値法:キーワードの二乗後の中桁をハッシュアドレスとします。
(4)折りたたみ方法:キーワードを同じビット数の複数の部分に分割し、これらの部分の重ね合わせた合計をハッシュアドレスとします。
(5)残差法を除算して残す:キーをハッシュテーブルの長さm以下の数pで除算した後に得られた残差をハッシュアドレスとして取得します
。つまり、h(key)=keyMODpp≤m
(6)ランダム番号方法:ランダム関数を選択し、キーのランダム関数値をハッシュアドレスとして取得します
。つまり、h(key)= random(key)

1.5。バイナリツリーを並べ替える

まず、通常のバイナリツリーの各ノードが次の条件を満たす場合:左側のサブツリーのすべてのノード値がそのルートノード値よりも小さく、右側のサブツリーのすべてのノード値がそのルートノード値よりも大きい場合、そのようなバイナリツリーはソートされたバイナリツリーです。

1.5.1。挿入操作

まず、ルートノード(つまり、新しいノードの親ノード)から挿入する位置を見つけます。具体的なプロセスは次のとおりです。新しいノードを現在のノードと比較します。同じ場合はすでに存在し、再度挿入することはできません。現在のノードよりも小さい場合。 、次に、左側のサブツリーを検索します。左側のサブツリーが空の場合、現在のノードが探している親ノードであり、新しいノードを現在のノードの左側のサブツリーに挿入できます。現在のノードよりも大きい場合は、右側のサブツリーを検索します。 、右側のサブツリーが空の場合、現在のノードが探している親ノードであり、新しいノードが現在のノードの右側のサブツリーに挿入されます。
ここに写真の説明を挿入

1.5.2。削除操作

削除操作は3つのケースに分けられ即要删除的节点无子节点,要删除的节点只有一个子节点,要删除的节点有两个子节点ます。

  1. 削除するノードに子ノードがない場合は、直接削除できます。つまり、親ノードで子ノードを空白にします。
  2. 削除するノードの子ノードが1つしかない場合は、削除するノードを子ノードとして置き換えます。
  3. 削除するノードには、2つのサブノード则首先找该节点的替换节点(つまり、右側のサブツリー内の最小のノード)があり、削除するノードを置換ノードとして置き換えてから、置換ノードを削除します。
    ここに写真の説明を挿入

1.5.3。クエリ操作

検索操作の主なプロセスは次のとおりです。最初にルートノードと比較し、それらが同じである場合は戻ります如果小于根节点则到左子树中递归查找,如果大于根节点则到右子树中递归查找したがって、ソートされたバイナリツリーでは、最大(右端と最深の子ノード)と最小(左端と最深の子ノード)の値を簡単に取得できます。

1.6。赤黒の木

RB Tree、フルネームはRed-Black Tree、別名「Red-Black Tree」で、特別なバイナリ検索ツリーです。赤黒ツリーの各ノードには、ノードの色を示すストレージビットがあり、赤または黒にすることができます。

1.6.1。赤黒の木の特徴

(1)各ノードは黒または赤のいずれかです。
(2)ルートノードが黒です。
(3)各リーフノード(NIL)は黒です。[注:ここでのリーフノードとは、空(NILまたはNULL)のリーフノードを指します。](4)ノードが赤の場合、その子ノードは黒でなければなりません。
(5)ノードからノードの子孫へのすべてのパスには、同じ数の黒いノードが含まれています。

1.6.2。左手

xを左に回転させると、「xの右の子」が「xの親ノード」に設定されます。つまり、xは左ノードになります(xはzの左の子になります)。したがって、左利きの「左」は「回転したノードが左のノードになる」ことを意味します。
ここに写真の説明を挿入

LEFT-ROTATE(T、x)
y←right [x] //前提条件:xの右の子はyであると想定されています。正式な操作を開始しましょう
right [x]←left [y] //「yの左の子」を「xの右の子」に設定します。つまり、βをxの右の子に設定します
p [left [y]]←x // 「x」を「yの左子の父」に設定します。つまり、βの父をxに設定します
。p[y]←p [x] //
p [xの場合、「xの父」を「yの父」に設定します。] = nil [T]
then root [T]←y //ケース1:「xの父」が空のノードの場合、yをルートノードとして設定します。
それ以外の場合、x = left [p [x]]の
場合はleft [p [x]]←y //ケース2:xがその親ノードの左の子である場合、yを「xの親ノードの左の子」に設定します。
それ以外の場合はright [p [x]]←y //ケース3: (xはその親ノードの右の子です)yを「xの親ノードの右の子」に設定します
left [y]←x //「x」を「yの左の子」に設定します
p [x]←y / /「xの親ノード」を「y」に設定します

1.6.3。右側

xを右に回転させると、「xの左の子」を「xの親ノード」として設定することになります。つまり、xを右のノードに変換します(xはyの右の子になります)。したがって、右回転の「右」は「回転したノードが右ノードになる」ことを意味します。
ここに写真の説明を挿入

RIGHT-ROTATE(T、y)x←left [y] //前提:ここでは、yの左の子がxであると仮定します。正式な操作を開始しましょうleft [y]
←right [x] //「xの右の子」を「yの左の子」に設定します。つまり、βをyの左の子に設定します
p [right [x]]←y // 「y」を「xの右子の父」に設定します。つまり、βの父をyに設定します> p [x]←p [y] //
p [の場合は「yの父」を「xの父」に設定します。y] = nil [T]
then root [T]←x //ケース1:「yの父」が空のノードの場合、xをルートノードとして設定します。
それ以外の場合、y = right [p [y]]の
場合はright [ p [y]]←x //ケース2:yがその親ノードの右の子である場合、xを「yの親ノードの左の子」に設定します。
それ以外の場合はleft [p [y]]←x //ケース3 :( Yはその親ノードの左の子です)xを「yの親ノードの左の子」に設定します
right [x]←y //「y」を「xの右の子」に設定します
p [y]←x //「yの親ノード」を「x」に設定します

1.6.4。追加

ステップ1:赤黒ツリーをバイナリ検索ツリーとして扱い、ノードを挿入します。
手順2:挿入したノードを「赤」に色付けします。
挿入されたノードの親ノードの状況に応じて、「ノードzが赤いノードに色分けされ、バイナリツリーを挿入する場合」は、3つの状況に分けて処理することができます。
①説明:挿入されたノードはルートノードです。
処理方法:このノードを直接黒く塗ります。
②説明:挿入されたノードの親ノードは黒です。
解決策:何もする必要はありません。ノードが挿入された後も、それは赤黒の木のままです。
③説明:挿入されたノードの親ノードは赤です。この場合、挿入されたノードには空でない祖父母ノードが必要です。さらに言えば、挿入されたノードには叔父ノードも含まれている必要があります(叔父ノードが空であっても、存在すると見なされ、空のノード自体は黒いノードです)。 。この点を理解した上で、この状況を「アンクルノード状況」に基づいてさらに3つのケース(ケース)に分けます。
ここに写真の説明を挿入

ステップ3:回転や色付けなどの一連の操作を行って、再び赤黒の木にします。

1.6.5。削除

手順1:赤黒ツリーをバイナリ検索ツリーとして扱い、ノードを削除します。
これは、「通常のバイナリ検索ツリーでノードを削除する」と同じです。次の3つの状況があります
。①削除されたノードには息子がなく、リーフノードです。その後、ノードを直接削除してもかまいません。
②削除されたノードには息子が1人しかいません。次に、ノードを直接削除し、その位置をノードの唯一の子ノードに置き換えます。
③削除されたノードには2人の息子がいます。次に、最初に後続ノードを見つけ、次に「後続ノードのコンテンツ」を「このノードのコンテンツ」にコピーします。その後、「後続ノード」を削除します。
ステップ2:一連の「回転と色の変更」によってツリーを変更し、再び赤黒のツリーにします。「最初のステップ」でノードを削除した後、赤黒ツリーの特性に違反する可能性があるためです。したがって、ツリーを再び赤黒ツリーにするには、「回転と色の変更」によってツリーを変更する必要があります。
色変更の3つのケースを選択してください。
①状況の説明:xは「赤+黒」ノードです。
加工方法:xを直接黒にセットして仕上げます。このとき、赤と黒の木の性質が完全に復元されます。
②状況説明:xは「黒+黒」ノード、xはルートです。
解決策:何もしないで終了します。このとき、赤と黒の木の性質が完全に復元されます。
③状況説明:xは「黒+黒」ノードであり、xはルートではありません。
治療法:この状況は4つのシード状況に分けることができます。これらの4つのシードの状況を次の表に示します。

ここに写真の説明を挿入

1.7。B-TREE

Bツリーはバランスの取れた多方向検索ツリーとも呼ばれます。m次のBツリー(m-aryツリー)の特性は次のとおりです(ceil(x)は上限のある関数です)。

  1. ツリーの各ノードには、最大m個の子があります。
  2. ルートノードとリーフノードを除いて、他のすべてのノードには少なくともceil(m / 2)個の子があります。
  3. ルートノードがリーフノードでない場合、少なくとも2つの子があります(特殊なケース:子のないルートノード、つまり、ルートノードはリーフノードであり、ツリー全体には1つのルートノードしかありません)。
  4. すべてのリーフノードが同じレイヤーに表示されます。リーフノードにはキーワード情報が含まれていません(外部ノードまたはクエリに失敗したノードと見なすことができます。実際、これらのノードは存在せず、これらのノードへのポインタはヌル);
  5. 各非端末ノードには、n個の重要な情報が含まれています:(n、P0、K1、P1、K2、P2、...、Kn、Pn)。その中で:
    a)Ki(i = 1 ... n)がキーワードであり、キーワードはK(i-1)<Kiの順にソートされます。
    b)Piはサブツリーのルートを指すノードであり、ポインターP(i-1)はサブツリーのすべてのノードを指します。キーワードはKi未満ですが、K(i-1)より大きくなります。
    c)キーワードの数nは、ceil(m / 2)-1 <= n <= m-1を満たす必要があります。
    ここに写真の説明を挿入

次数mのB +ツリーと次数mのBツリーの違いは次のとおり
です。1。n個のサブツリーを持つノードにはn個のキーワードが含まれます;(Bツリーはn-1個のキーワードを持つn個のサブツリーです)
2。すべてのリーフノードには、すべてのキーワードの情報と、これらのキーワードを含むレコードへのポインタが含まれ、リーフノード自体は、キーワードのサイズの小さいものから大きいものの順にリンクされます。(Bツリーのリーフノードには、検索する必要のあるすべての情報が含まれているわけではありません)
3。すべての非ターミナルノードはインデックス部分と見なすことができ、ノードにはサブツリーのルートノードに最大(または最小)のキーワードのみが含まれます。 。
ここに写真の説明を挿入

(Bツリーの非ターミナルノードには、見つける必要のある有効な情報も含まれています)

1.8。ビットマップ

ビットマップの原理は、ビットを使用して数値が存在するかどうかを識別し、ビットを使用してデータを格納することです。これにより、スペースを大幅に節約できます。ビットマップは、ブルームフィルタで使用されるような、非常に一般的に使用されるデータ構造です。繰り返されない整数の並べ替えなどに使用されます。ビットマップは通常、配列に基づいて実装されます。配列内の各要素は一連のバイナリ番号と見なすことができ、すべての要素がより大きなバイナリセットを形成します。

おすすめ

転載: blog.csdn.net/qq_46914021/article/details/109215589