ツヌルを盎接知る最も䞀般的に䜿甚されるデヌタ構造の抂芁

画像

少し前に、私はある倧芏暡で尊敬される䌚瀟にむンタビュヌに行きたした。 むンタビュヌはうたくいき、私はそれを気に入っおくれたした。 しかし、翌日、報告䌚の過皋で、むンタビュヌ䞭に少なくずも1぀の質問に察する答えが間違っおいるこずがわかりたした。



質問倧量のデヌタのpython dictでの怜玢が、むンデックス付き配列の繰り返し凊理よりも速いのはなぜですか



回答dictはキヌハッシュを保存したす。 dict倀のキヌを怜玢するたびに、たずそのハッシュを蚈算し、次に突然バむナリ怜玢を実行したす。 したがっお、耇雑さはOlogNです



実際、ここにはバむナリ怜玢はありたせん。 そしお、アルゎリズムの耇雑さはOlogNではなく、Amortです。 O1-python dictはハッシュテヌブルず呌ばれる構造に基づいおいるため。



間違った答えの理由は、 私の奜きな蚀語のコレクションを䜿っお、䜜品の根底にある構造を培底的に研究するこずを気にしなかったからです 。 確かに、いく぀かのよく知られおいる開発者の調査によるず、これは私の問題であるだけでなく、倚くの人がお気に入りのPLでコレクションがどのように機胜するかさえ考えおいないこずがわかりたした。 しかし、私たちはそれらを䞀床ではなく毎日䜿甚しおいたす。 この蚘事のアむデアが生たれたした。





蚘事内の構造の分類に関するいく぀かの蚀葉。 䜿甚枈み情報のリストにリストされおいる゜ヌスを調べるず、この蚘事の分類がどの゜ヌスの分類にも察応しおいないこずに気付くでしょう䞀郚の゜ヌスではたったくありたせん。 これは、構造䜓を䜿甚するずいう文脈で構造䜓を怜蚎する方が適切だず思われたためです。 たずえば、PHP / Python / C ++の連想配列たたは.Net / Pythonのリスト。



行きたしょう。



1.配列-むンデックス付き配列です。



配列は、同じタむプの芁玠で構成される固定サむズのコレクションです。



むンタヌフェヌス



配列内の怜玢は、むンデックス=>耇雑さONで芁玠を゜ヌトするこずにより実行されたす。



アむテムのむンデックスアクセス時間が䞀定なのはなぜですか 配列は同じ型の芁玠で構成され、サむズが固定されおおり、メモリの連続領域に配眮されおいたす=>配列のj番目の芁玠を取埗するには、配列の先頭ぞのポむンタを取埗し、芁玠サむズにそのむンデックスを掛けた倀を远加するだけです。 この単玔な蚈算の結果は、配列の目的の芁玠のみを指したす。

*aj = beginPointer + elementSize*j-1









䟋

/++: int i_array[10];

java/C#: int[10] i_array;

Python: array.array

php: SplFixedArray









2.リスト。



リストは、任意のタむプの可倉長の芁玠のリストです぀たり、リストに芁玠を远加したり、い぀でも削陀したりできたす。 このリストを䜿甚するず、アむテムを反埩凊理したり、むンデックスでアむテムを取埗したり、アむテムを远加および削陀したりできたす。 リストの実装は異なり、䞻なものは単䞀/双方向リンクリストずベクタヌです。 叀兞的なリストは、盎接およびむテレヌタを介しおそれを操䜜する機胜を提䟛したす;以䞋で䞡方のクラスのむンタヌフェヌスを怜蚎したす。



リストむンタヌフェむス



リストむテレヌタむンタヌフェむス



䞀郚のほずんど解釈されるプログラミング蚀語では、これらの2぀のむンタヌフェむスが「接着」および「トリミング」されおいるこずに泚意しおください。 たずえば、Pythonでは、リスト型のオブゞェクトを反埩できたすが、むンデックスから盎接アクセスするこずでリストから取埗するこずもできたす。



実装のリストに移りたしょう。



2.1単䞀のリンクリスト


画像

単方向リンクリスト単䞀リンクリストは、コンテナのチェヌンです。 各コンテナには、芁玠ぞのリンクず次のコンテナぞのリンクが含たれおいるため、単䞀のリンクリストを垞に前に進み、珟圚の芁玠の倀を垞に取埗できたす。 コンテナはメモリ内に配眮するこずができたす=>単玔に接続されたリストに新しい芁玠を远加するのは簡単です。



運甚コスト



䟋

/++: std::list //Bidirectional Linked List

Java: java.util.LinkedList

c#: System.Collection.Generic.LinkedList //Bidirectional Linked List

php: SplDoublyLinkedList // Bidirectional Linked List









双方向リンクリストの詳现は考慮したせんが、双方向リンクリストず単䞀リンクリストの違いは、コンテナ内に次ぞのリンクだけでなく前のコンテナぞのリンクがあるこずです。これにより、リスト内を前方だけでなく埌方にも移動できたす。



2.2ベクトル


Vectorは、むンデックス配列の拡匵によるListの実装です。



運甚コスト





明らかに、ベクタヌの䞻な利点は、通垞のむンデックス付き配列から継承されたむンデックスによる芁玠ぞの迅速なアクセスです。 Vectorの反埩も非垞に簡単です。特定のカりンタヌを1぀増やし、むンデックスでアクセスするだけです。 ただし、芁玠ぞのアクセス速床を䞊げるには、芁玠を远加する時間を支払う必芁がありたす。 Vector'aの䞭倮挿入埌に芁玠を挿入するには、反埩子の珟圚䜍眮ず配列の最埌の間にあるすべおの芁玠をコピヌする必芁がありたす。その結果、平均アクセス時間はONになりたす。 配列の䞭倮の芁玠を削陀し、配列の先頭に芁玠を远加するこずでも同じです。 配列の最埌に芁玠を远加するこずはO1で行うこずができたすが、できない堎合がありたす-再び配列を新しい配列にコピヌする必芁がある堎合、ベクタヌの最埌に芁玠を远加するこずはAmortによっお行われたす。 O1。



䟋

/++: std::vector

Java: java.util.ArrayList

C#: System.Collections.ArrayList, System.Collections.List

Python: list









3.連想配列蟞曞/マップ



キヌ=>倀のペアのコレクション。 芁玠倀には任意の型を指定できたす。通垞、キヌは文字列/敎数のみですが、実装によっおは、キヌずしお䜿甚できるオブゞェクトの範囲を広げるこずができたす。 連想配列のサむズは、芁玠を远加/削陀するこずで倉曎できたす。



むンタヌフェヌス



連想配列には、HashMapずBinary Treeの2぀の䞻芁な実装がありたす。



3.1ハッシュテヌブル


画像

名前から掚枬できるように、ここではハッシュが䜿甚されたす。 ハッシュテヌブルの仕組みは次のずおりです。キヌからのハッシュ倀がむンデックスずしお機胜する同じむンデックス付き配列に基づいおおり、倀はキヌず栌玍された芁玠バケットを含むオブゞェクトぞの参照です。 アむテムを远加するずき、ハッシュ関数はキヌからハッシュを蚈算し、察応するむンデックスを持぀配列セルに远加されるアむテムぞのリンクを保存したす。 芁玠にアクセスするには、再びキヌからハッシュを取埗し、通垞の配列ず同様に機胜しお、芁玠ぞのリンクを取埗したす。



奜奇心reader盛な読者は、この糖尿病の実斜に特有の問題に気付くかもしれたせん。



これらの2぀の問題は関連しおいたす少数の芁玠を栌玍する堎合、長いハッシュを蚈算できないこずは明らかです-ハッシュ関数は通垞次のようになるため、䞍圓なメモリコストが発生したす。

index = f(key, arrayLength)









぀たり、キヌ倀に加えお、配列の珟圚のサむズも受け取りたす。これは、ハッシュの長さを決定するために必芁です。3぀の芁玠のみを栌玍する堎合、長さ32ビットのハッシュを䜜成しおも意味がありたせん。 ハッシュ関数のこの動䜜の裏偎は、衝突の可胜性です。 衝突は実際にはハッシュテヌブルの特城であり、衝突を解決するには2぀の方法がありたす。



連鎖

画像

配列Hの各セルは、キヌの同じハッシュ倀に察応するキヌず倀のペアのリンクリストチェヌンぞのポむンタヌです。 衝突は、単玔に1芁玠よりも長いチェヌンの出珟に぀ながりたす。



オヌプンアドレス指定



配列Hは、キヌず倀のペア自䜓を保存したす。 芁玠挿入アルゎリズムは、新しい芁玠が曞き蟌たれる最初の空きセルが芋぀かるたで、ある順序で配列Hのセルをチェックしたす。 この順序はオンザフラむで蚈算され、チェヌンを持぀ハッシュテヌブルに必芁なポむンタヌのメモリを節玄したす。

画像



運甚コスト



ここで、最初の倀は平均耇雑床、2番目は最悪の堎合の操䜜の耇雑床です。 この違いの原因は次のずおりです。芁玠を远加するずきに、配列がいっぱいの堎合、ハッシュテヌブル党䜓を再構築する必芁がある堎合がありたす。 芁玠を怜玢するず、衝突の長い連鎖に出くわすこずが刀明する堎合がありたす。たた、すべおの芁玠を゜ヌトする必芁がありたす。



䟋

c++: QHash boost::unordered_map/boost::unordered_set (by NickLion )

java: java.util.HashMap<K,V>

c#: System.Collections.Hashtable, System.Collections.Dictionary<K, V>

python: dict

php: array()









3.2バむナリツリヌ


画像

実際には、バむナリツリヌだけでなく、自己バランス型バむナリツリヌもありたす。 さらに、連想配列を実装するために䜿甚できるいく぀かの異なるツリヌがあるこずに泚意する必芁がありたす赀黒ツリヌ、AVLツリヌなど。 これらのツリヌはそれぞれ別の蚘事、たたは耇数のトピックおそらく非垞に慎重にツリヌを研究する堎合のトピックであるため、これらの各ツリヌを詳现に怜蚎するこずはしたせん。 䞀般的な原則のみを説明したす。



定矩バむナリツリヌ-各ノヌドが2぀以䞋の子孫子を持぀ツリヌ状のデヌタ構造。 原則ずしお、最初のノヌドは芪ノヌドず呌ばれ、子は巊ず右の盞続人ず呌ばれたす。 ノヌドに子孫がない堎合、リヌフノヌドず呌ばれたす。



たずえば、バむナリ怜玢ツリヌを芋おみたしょう。各ノヌドは、3぀の芁玠を含むコンテナです。デヌタ-実際に添付されたデヌタデヌタには芁玠自䜓ずキヌ倀の䞡方が含たれたす、巊-基になる巊ノヌドず右ぞのリンク-適切な基になるノヌドぞのリンク。 この堎合、次のルヌルが満たされたすキヌ[å·Š[X]] <キヌ[X]≀キヌ[右[X]]-぀たり、芪ノヌドのデヌタキヌは巊息子のデヌタキヌより倧きく、右息子のデヌタキヌよりも緩やかに小さいです。 芁玠を怜玢するずき、キヌの倀を珟圚のノヌドのキヌず比范するたびにツリヌを䞀呚し、比范の結果に基づいお、どの方向に進むべきかを決定したす。 そのような怜玢の耇雑さは安定しおOlogNであるこずを蚈算するのは簡単です。 新しいノヌドを远加するずき、新しい芁玠をどこに貌り付けるかを芋぀けるたで、䞀般的に同様の手順を実行したす。 確かに、このようなツリヌはただバランスを取る必芁があるこずに泚意する必芁がありたすが、これは既に省略したす。 奜奇心reader盛な読者は、゜ヌスのリストを調べお必芁な情報を芋぀けたす。



運甚コスト



䟋

c++: std::map, std::set

java: java.util.TreeMap<K,V>, java.util.Map<K,V> -

c#: :( SortedDictionary(by NickLion )

python: -

php: -









4.セット。



芁玠の䞍倉のセット。 セットは䞀床だけ定矩されたす-䜜成時に、その埌芁玠ぞの読み取り専甚アクセスを提䟛したす。 セットから芁玠を削陀したり、セットの芁玠を倉曎したりするこずが䞍可胜であるように、セットを展開するこずはできたせん。 このコレクションを実装するためのベヌスずしお、通垞ハッシュテヌブルが䜿甚されたす。ハッシュテヌブルの説明は䞊蚘にありたす。



セットは、単に数孊的なセットの抜象化の実装です。 䞀意の区別可胜な芁玠のセット。  ATP DanilI 

䟋

c++: std::set

java: java.util.Set

C#: System.Collections.HashSet

python: set/frozenset









デヌタ構造の比范特性

画像



さたざたなプログラミング蚀語のデヌタ構造

画像



参照



デヌタ構造en

デヌタ構造rus

バむナリ怜玢ツリヌen

バむナリ怜玢ツリヌrus



たた、著者はPHPの゜ヌスコヌドを芋お、 STLのドックを読みたした。



曎新したした。 はい、pythonには通垞のむンデックス付き配列array.arrayがありたす。 ゚ンチャントナヌに感謝したす。 修正されたように、型は必ずしも数倀ではなく、型を指定できたす。



曎新したした。 テキストで行われた倚くの修正。 idemura 、 zibada 、 tzlom 、 SiGMan 、 freeOne 、 Slaffko 、 korvindest 、 Laplace 、線集者、線集者に感謝



曎新したした。

ゞバダのコメントから

はい、Mapむテレヌションの説明がないずいう理由だけで、ハッシュがあるずきにツリヌが必芁であるず思われる理由は、蚘事からは䞀般に明確ではありたせん。 OlogNvs O1。



その堎合、マップたたはセット芁玠をリストするこずができたす。

-保蚌されおいない順序HashMap、䞀郚のスクリプト蚀語の組み蟌みハッシュ。

-远加する順にLinkedHashMap、他のスクリプト蚀語の組み蟌みハッシュ;

-キヌの昇順+特定の範囲内のキヌのみを反埩凊理する機胜。



ただし、埌者の堎合、ツリヌに代わるものは、各倉曎埌たたはリク゚ストの前にコレクション党䜓を完党に゜ヌトするこずです。

これは倧きなコレクションでは長くお悲しいですが、小さなコレクションでは機胜したす。したがっお、ツリヌはスクリプト蚀語に特に埋め蟌たれおいたせん。



All Articles