私は数日前にビンディと連絡を取りました、彼は書いた私たち全員が常に自分自身を燃やしているので、私たちは常に燃料を補充する必要があると言いました。彼の見解では、もう同意できないので、比較的弱いデータ構造を含むコンピューターの基本的な知識を満たし始めました。
Baidu Baikeのデータ構造の定義は次のとおりです。相互に1つ以上の特定の関係を持つデータ要素のコレクション。定義は非常に抽象的であり、少し感じるために何度か声に出して読む必要があります。この気持ちをより強く、より親密にする方法は?8つの一般的なデータ構造、配列、リンクリスト、スタック、キュー、ツリー、ヒープ、グラフ、およびハッシュテーブルをリストします。
これらの8つのデータ構造の違いは何ですか?
①、配列
利点:
-
インデックスに従って要素をクエリする速度は非常に高速です。
-
配列をインデックスでトラバースすることも便利です。
短所:
-
配列のサイズは作成後に決定され、拡張できません。
-
配列は1つのタイプのデータのみを格納できます。
-
他の要素を移動する必要があるため、要素の追加と削除の操作には時間がかかります。
②、リンクリスト
本「アルゴリズム(第4版)」では、リンクリストを次のように定義しています。
リンクリストは再帰的なデータ構造であり、空(null)またはノードへの参照です。ノードには、要素と別のリンクリストへの参照もあります。
JavaのLinkedListクラスは、リンクリストの構造をコードの形式で鮮明に表現できます。
public class LinkedList<E> {
transient Node<E> first;
transient Node<E> last;
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
}
これは二重にリンクされたリストです。現在の要素アイテムにはprevとnextの両方がありますが、firstのprevがnullで、lastのnextがnullです。単独でリンクされたリストの場合、次のみがあり、前はありません。
単一リンクリストの欠点は、最初から最後まで順番にしかトラバースできないことです。一方、二重リンクリストは、前進または後退することができ、前のノードと同様に次のリストを見つけることができ、各ノードはさらに1つのストレージスペースを割り当てる必要があります。
リンクリストのデータは「チェーン」構造に格納されるため、非連続メモリの効果を実現でき、配列は連続メモリでなければなりません。
順番に格納する必要がないため、リンクリストは挿入および削除時にO(1)時間の複雑さに達する可能性があります(参照を再度ポイントするだけで、配列などの他の要素を移動する必要はありません)。さらに、リンクリストは、配列のデータサイズが事前にわかっている必要があるという欠点を克服し、柔軟な動的メモリ管理を実現できます。
利点:
-
容量を初期化する必要はありません。
-
任意の要素を追加できます。
-
挿入および削除時に参照を更新する必要があるだけです。
短所:
-
多数の参照が含まれ、大きなメモリ空間を占有します。
-
要素を見つけるには、リンクリスト全体を走査する必要があり、時間がかかります。
③、スタック
スタックはバケツのようなもので、底は密閉されており、上部は開いており、水は出入りできます。バケツを使用したことのある友人は、この真実を理解する必要があります。最初に入る水はバケツの下部にあり、後で入る水はバケツの上部にあります。後で入る水が最初に注がれ、最初に入る水が後で注がれます。
同様に、スタックは「後入れ先出し」および「先入れ後出し」の原則に従ってデータを格納します。最初に挿入されたデータはスタックの一番下にプッシュされ、後で挿入されたデータはスタックの一番上にあります。データを読み取るときは、スタックの一番上から開始します。順次読み取ります。
④キュー
キューは水道管の一部のようなもので、両端が開いており、一端から水が入り、他端から出てきます。最初に入る水が最初に出て、後で入る水が出ます。
配水管と異なる点は、キューが2つの端を定義することです。一方の端はチームのヘッドと呼ばれ、もう一方の端はテールと呼ばれます。チームの先頭では削除操作(デキュー)のみが許可され、チームの最後では挿入操作(キューに入る)のみが許可されます。
スタックは先入れ先出しで、キューは先入れ先出しですが、どちらも線形テーブルですが、原理は異なり、構造も異なります。
⑤、木
ツリーは典型的な非線形構造であり、n(n> 0)の有限ノードで構成される階層的なコレクションです。
このデータ構造は、ルートが上部にあり、リーフが下部にあることを除いて、逆さまのツリーのように見えるため、「ツリー」と呼ばれます。ツリーデータ構造には、次の特性があります。
-
各ノードには、子ノードの数に制限があるか、子ノードはありません。
-
親ノードのないノードはルートノードと呼ばれます。
-
すべての非ルートノードには、親ノードが1つだけあります。
-
ルートノードを除いて、各子ノードは複数の互いに素なサブツリーに分割できます。
次の図は、ツリーのいくつかの用語を示しています。
ルートノードはレベル0、その子ノードはレベル1、子ノードの子ノードはレベル2などです。
-
深さ:ノードnの場合、nの深さはルートからnへの唯一のパス長であり、ルートの深さは0です。
-
高さ:ノードnの場合、nの高さはnから葉までの最長パス長であり、すべての葉の高さは0です。
多くの種類の木があり、一般的なものは次のとおりです。
-
順序付けられていないツリー:ツリー内のノードの子ノード間に順序関係はありません。それでは、順不同のツリーをどのように理解し、どのように見えますか?
3つのノードがあり、1つが親ノードで、2つが同じレベルの子ノードである場合、3つの状況があります。
3つのノードがあり、1つが親ノードで、2つが異なるレベルの子ノードである場合、6つの状況があります。
3つのノードで構成される無秩序なツリーは、9つの状況に組み合わせることができます。
-
二分木:各ノードには最大2つのサブツリーが含まれます。二分木は、さまざまな症状に応じて複数のタイプに分けることができます。
完全な二分木:二分木について、その深さがd(d> 1)であるとします。d層を除いて、他の層のノード数が最大値に達し、d層のすべてのノードが左から右に連続して密に配置されています。このような二分木は、完全二分木と呼ばれます。
上の図を例にとると、dは3です。3番目のレイヤーを除いて、1番目と2番目のレイヤーは最大値に達し(2つの子ノード)、3番目のレイヤーのすべてのノードは左から右に密接に接続されています(H 、I、J、K、L)、完全なバイナリツリーの要件に沿っています。
完全な二分木:各層のノードの最大数を持つ二分木。次の2つの症状があり、最初の症状は、下の図に示すように(各レイヤーがいっぱいです)、各レイヤーのノードの最大数2を満たします。
2番目は、次の図のように(ただし、各レイヤーがいっぱいではありません)、各レイヤーのノード数はまだ最大の2に達しています。
二分探索木:英語名は二分探索木(BST)で、次の条件を満たす必要があります。
-
どのノードの左側のサブツリーも空ではなく、左側のサブツリー上のすべてのノードの値は、そのルートノードの値よりも小さくなります。
-
ノードの右側のサブツリーは空ではなく、右側のサブツリー上のすべてのノードの値はルートノードの値よりも大きくなります。
-
ノードの左側と右側のサブツリーも、バイナリ検索ツリーです。
バイナリ検索ツリーの特性に基づくと、他のデータ構造と比較した場合の利点は、検索と挿入の時間の複雑さが比較的低く、O(logn)であることです。上図から5つの要素を検索する場合、ルートノード7から開始します。5は7の左側にあり、4が検索され、5は4の右側にあり、6は6の左側にある必要があります。サイド、見つけた。
理想的には、BSTを介してノードを見つけるには、チェックする必要があるノードの数を半分にすることができます。
平衡二分木:任意のノードの2つのサブツリー間の高さの差が1以下の二分木。1962年に旧ソビエト連邦の数学者Adelse-VelskilとLandisによって提案された高度にバランスのとれた二分木は、科学者の英語名によるとAVLツリーとも呼ばれます。
平衡二分木は本質的に二分探索木です。ただし、左右のサブツリー間の高さの差を制限し、線形構造の進化に偏るツリーの傾斜を回避するために、二分探索ツリーの各ノードの左と右のサブツリーは制限のため、左側と右側のサブツリーの高さの差はバランス係数と呼ばれ、ツリー内の各ノードのバランス係数の絶対値は1以下です。
バイナリツリーのバランスをとるのが難しいのは、ノードが削除または追加されたときに、左利きまたは右利きで左右のバランスを維持する方法にあります。
Javaで最も一般的なバランスのとれたバイナリツリーは赤黒ツリーです。ノードは赤または黒です。バイナリツリーのバランスは、色の制約によって維持されます。
1)各ノードは赤または黒のみです。
2)ルートノードは黒です
3)各リーフノード(NILノード、空のノード)は黒です。
4)ノードが赤の場合、その2つの子ノードは黒です。つまり、2つの隣接する赤いノードをパスに表示することはできません。
5)任意のノードから各リーフへのすべてのパスには、同じ数の黒いノードが含まれます。
-
Bツリー:読み取りおよび書き込み操作用に最適化された自己バランス型のバイナリ検索ツリー。データを順序どおりに保つことができ、3つ以上のサブツリーがあります。Bツリーは、データベースインデックステクノロジで使用されます。
⑥、ヒープ
ヒープは、以下の特性を持つツリーの配列オブジェクトと見なすことができます。
-
ヒープ内のノードの値は、常にその親ノードの値以下です。
-
ヒープは常に完全なバイナリツリーです。
最大のルートノードを持つヒープは最大ヒープまたは大きなルートヒープと呼ばれ、最小のルートノードを持つヒープは最小のヒープまたは小さなルートヒープと呼ばれます。
⑦、写真
グラフは複雑な非線形構造であり、空ではない有限の頂点のセットと頂点間のエッジのセットで構成されます。通常、次のように表されます。G(V、E)、Gはグラフを表し、VはGのグラフです頂点のセット、EはグラフGのエッジのセットです。
上の図には、V0、V1、V2、V3の4つの頂点があり、4つの頂点の間に5つのエッジがあります。
線形構造では、データ要素は一意の線形関係を満たし、各データ要素(最初と最後を除く)には一意の「前駆体」と「後続」があります。
ツリー構造では、データ要素間に明らかな階層関係があり、各データ要素は、上位層(親ノード)の1つの要素と次の層の複数の要素(子ノード)にのみ関連しています。
グラフ構造では、ノード間の関係は任意であり、グラフ内の任意の2つのデータ要素が関連している場合があります。
⑧、ハッシュテーブル
ハッシュテーブルはハッシュテーブルとも呼ばれ、Key-Valueを介して直接アクセスできるデータ構造です。最大の特徴は、すばやく検索、挿入、削除できることです。
配列の最大の特徴は、見つけやすいが挿入や削除が難しいことです。逆に、リンクリストは見つけにくいが挿入や削除が簡単です。ハッシュテーブルは2つの利点を完全に組み合わせたものであり、JavaのHashMapはこれに基づいてツリーの利点も追加します。
ハッシュ関数はハッシュテーブルで非常に重要な役割を果たし、任意の長さの入力を固定長の出力に変換でき、出力はハッシュ値です。ハッシュ関数を使用すると、データシーケンスへのアクセスプロセスがより迅速かつ効果的になります。ハッシュ関数を使用すると、データ要素をすばやく見つけることができます。
キーがkの場合、その値はhash(k)
保管場所に保管され ます。したがって、kに対応する値は、走査せずに直接取得できます。
2つの異なるデータブロックの場合、同じハッシュ値の可能性は非常に小さいです。つまり、特定のデータブロックでは、同じハッシュ値のデータブロックを見つけることは非常に困難です。さらに、データブロックの場合、1ビットだけが変更されても、そのハッシュ値の変更は非常に大きくなります。これがHashの値です。
可能性は非常に小さいですが、それでも起こります。ハッシュが競合する場合、JavaのHashMapはリンクされたリストを配列内の同じ位置に追加します。リンクされたリストの長さが8より大きい場合、処理のために赤黒ツリーに変換されます-これこれは、いわゆるジッパー方式(配列+リンクリスト)です。
正直なところ、この進歩に応じて、私ははげのリズムのように感じますが、それが強くなることができれば、それは価値があります-はい、価値があります。