アルゴリズムの謎解き - 並べ替えと検索

コンピュータの中核機能はコンピューティングとストレージであり、データ構造とアルゴリズムがコンピュータのコンピューティング効率を直接決定します。したがって、データ構造とアルゴリズムをよく学ぶことは、コンピューター ソフトウェアで良い仕事をするための非常に基本的な能力です。日常業務で最も頻繁に使用されるのは、並べ替えと検索です。この記事では、これら 2 種類のアルゴリズムについて説明します。

1 時間計算量

具体的なアルゴリズムを紹介する前に、以下の図に示すように、さまざまな時間計算量の違いを見てみましょう。

 

2 ソートアルゴリズム

一般的なソート アルゴリズムには、交換ソート、挿入ソート、選択ソート、カウント ソートなどがあります。

 

一般的なアルゴリズムは時間計算量を優先するため、以下は時間計算量に応じた分類分析です。

 

2.1 バブルソート、直接選択ソート、単純挿入ソートでは一対比較が必要ですが、比較後の処理方法の違いと比較順序の違いのみなので、計算量はO(n^2)となります。

(1) バブルソート: 最初の数値から開始し、ペアごとの比較後に大きい数値を右に移動し、シーケンス全体が整うまで最初の数値から新しいラウンドの比較を開始します。

(2) 直接選択ソート: 既存の順序付けされていないシーケンスから最小の番号を選択してシーケンスの先頭に配置し、シーケンス全体が順序どおりになるまで残りの番号から最小の番号を選択し続けます。選択するときはペアごとに比較してください。

(3) 単純な挿入ソート: 既存の順序なしシーケンスから数値を選択し、それを順序付きシーケンスの適切な位置に挿入し、挿入時にペアごとの比較を行います。

 

2.2 素早い並べ替えの核心は、二分法でランダムに数値を取得し、小さい方を左側に、大きい方を右側に置き、再帰を完了することです。これを行う利点は、毎回 2 つのペアごとに比較する必要がなくなり、比較範囲がどんどん小さくなることです。時間計算量は O(n * logn)

 

2.3 空間に制約されない場合は、空間を時間と交換して、時間計算量のより優れた並べ替えアルゴリズム (計数アルゴリズム) を取得することを検討できます。計数アルゴリズムは、並べ替える数値を配列のインデックスとして取得し、それを対応する配列に入れ、インデックスに従って小さい値から大きい値まで数値を取得します。

最も一般的に使用されるアルゴリズムは、交換ソートとクイック ソートです。

 

3 検索アルゴリズム

 

参考

https://www.jianshu.com/p/908f0366e1dc

https://www.jianshu.com/p/95d224c4d13e

https://blog.csdn.net/hao65103940/article/details/89032538

https://blog.csdn.net/yang_yulei/article/details/26066409

 

検索と並べ替えには区別はなく、一般的な検索には並べ替えが含まれますが、もちろん順序なしの検索もあります。一般に、一般的に使用される検索アルゴリズムには、逐次検索、補間検索、ツリー テーブル検索などがあります。さまざまな検索アルゴリズムの時間計算量を以下に示します。

 

3.1 ツリーテーブルの検索

まず、最も複雑なツリー テーブル検索から始めましょう。ツリー検索に関して言えば、幅優先検索と深さ優先検索について話さなければなりません。実際、これら 2 つの検索アルゴリズムは単なるグラフ走査手法であり、エンジニアリングにおいて最適なアルゴリズムではない可能性があり、すべてのノードを走査することに加えて追加のスペースが必要です。

 

幅優先検索: レイヤー順序のトラバーサルと同様に、キューを使用して実装できます。一般的なアルゴリズムの実装手順は次のとおりです。

1) 開始頂点として頂点を選択し、キューに入れます。

2) キューの先頭から頂点を取得し、読み取り済みとしてマークし、頂点のすべての接続を順番にキューの末尾に入れます。

3) ステップ 2 を繰り返します

 

深さ優先検索: 深さ優先検索は、暗闇への道に似ています。前の交差点に戻れない場合は、別の道を選択して歩き続けます。これはスタックの助けを借りて実現できます。

開始頂点として頂点を選択し、前進できる場合は前進し、前進できない場合は一歩後退するか、またはさらに一歩後退して別の前進方法を選択するなど、すべての頂点を通過するまで繰り返します。

 

ツリーの場合、最も一般的なのはバイナリ ツリーですが、もちろん B ツリー、B+ツリーなどのマルチフォーク ツリーもあります。一般的に一般的なものは、バイナリ ツリー、バランスド バイナリ ツリー、2-3 ツリー、赤黒ツリー、B ツリー、B+ ツリーなどです。以下に 1 つずつ紹介します。

 

3.1.1 二分木

左側のサブツリーのノード値はルート ノードより小さく、右側のサブツリーのノード値はルート ノードより大きくなります。バイナリ ツリーの左右のサブツリーが不均一に分散している場合、特定のリーフ ノードを見つけるためにより多くのノードをトラバースする必要があります。左右のサブツリーが均等に分散されている場合にのみ、トラバーサル層の数が最小になります。つまり、二分木のバランスが取れている場合です。

検索時間の複雑さは、最悪の場合は O(n)、最良の場合は O(logN) です。

 

3.1.2 バランスの取れた二分木

ルート ノードの両側のサブツリー間の最大高さの差は 1 です。数値などのデータ構造の場合、ツリーの最大高さが最大検索数となるため、ツリーのバランスを保つためにツリーの高さを下げるようにしてください。

 

3.1.3 2-3 ツリー (2-3 ツリー)

2 つのフォークは 1 つのキー値とサブツリーへの 2 つのリンクを意味し、3 つのフォークは 2 つのキーとサブツリーへの 3 つのリンクを意味します。2-3 ツリーは効率的な自己バランスをとるためのものです。完全にバランスのとれた 2 ~ 3 ツリーで、すべての空のリンク (リーフ ノード) はルート ノードから同じ距離にあります。

2-3 ツリーにノードを挿入する方法: まず、ノードを挿入する位置を見つけます。ノードが空いている場合 (つまり、2 分岐ノード)、次にノードを直接挿入します。ノードが空でない場合 (つまり、3 分岐ノード)、最初にノードを挿入してこの要素を一時的に収容し、次にこのノードを分割し、中央の要素をその親ノードに移動し、親ノードに対して同じことを行います。(空きが見つかるまで中ボタンは上に移動し続けます。途中で空きがない場合は、一時的に空きを作成してから分割してください)

最悪の場合でも、2-3 ツリーは依然として良好なパフォーマンスを維持しており、各操作で各ノードを処理する時間は小さな定数を超えることはなく、この操作は同じパス上のノードのみを訪問します。したがって、検索または挿入の操作時間コストが対数レベルを超えることはありません。

3.1.4 赤黒木

バランスのとれたバイナリ ツリーは、ノードの挿入または削減時にバランスを崩しやすいですが、赤黒ツリーは自己バランス型のバイナリ ツリーです。これは 2 ~ 3 個のツリーの標準化であり、標準バイナリ ツリーの特性を持ち、同時に自己バランスをとることができます。

赤黒ツリーは、3 点ノードを表すために赤いリンクを使用する 2-3 ツリーであるため、赤黒ツリーの自己平衡は 2-3 ツリーの自己平衡に変換され、赤黒ツリーの挿入ノードは 2-3 ツリー挿入ノードに変換されます。3 分岐ノードは、赤と黒のツリーである左傾斜の赤いリンクによって接続された 2 つの 2 分岐ノードとして表され、すべての赤いリンクは左傾斜でなければなりません。

赤黒ツリーの別の定義は、次の条件を満たす二分探索ツリーです。

1) 赤いリンクはすべて左のリンクです

2) 2 つの赤いリンクに同時に接続されているノードはない

3) ツリーは完全にブラックバランスになっています。つまり、空のリンクからルートノードまでのパス上の黒いリンクの数は同じです。

3.1.5 B ツリー

B ツリーは、バランスの取れた多方向検索ツリーであり、外部ストレージ (ディスクなど) の検索効率を最適化するために生成されるデータ構造です。ディスク IO の単位はディスク ブロックであるため、IO の数をできる限り減らす必要があります。各ディスク ブロックには、できる限り多くのキーと値のペアと、インデックス キーの両側のディスク ブロックのアドレスを格納する必要があります。つまり、B ツリーはマルチフォーク ツリーです。ツリーの合計層の高さを最小限に抑え、IO の数を減らし、クエリ効率を向上させます。

3.1.6 B+ツリー

b+tree は b-tree の最適化された構造です。b-tree の各ツリー ノードはキーと値を格納し、b+tree はキーのみを格納し、リーフ ノードのみがキーと値を格納します。このようにして、b+tree の各ノードはより多くのインデックス キーを格納できるため、ツリーの高さがさらに削減され、クエリ効率が高くなります。

InnoDB は、ツリー B+ツリー インデックス (クラスター化インデックス: リーフ ノードにはキーと行全体のデータが含まれます。補助インデックス: リーフ ノードにはキーのみが含まれますが、データの行全体は含まれません。データの行全体はインデックス キーに従ってさらにクエリされる必要があります。) 層の高さは 2 ~ 4 層で、ルート ノードはメモリに常駐します。同時に、B+tree のリーフ ノードは順序付きリストを形成します。これは区間検索に便利です。b+tree と b-tree はどちらもマルチフォーク ツリーに属します。

Innodb のストレージ構造では、テーブルにはクラスター化インデックス (主キー インデックス) が 1 つだけあり、他のインデックスはセカンダリ インデックスであり、すべて非クラスター化インデックスです。

3.2 補間検索

最も古典的なのは二分探索であり、順序付けされたテーブルを前提としています。これは静的テーブルに適していますが、継続的な並べ替えにより時間の計算量が増加するため、動的テーブルには効果がありません。動的なテーブル ルックアップの場合は、赤黒ツリーなどのバランスのとれたバイナリ ツリーを使用できます。

二分探索のほかに、フィボナッチ探索などのバージョンアップ版もあり、一般的に中間位置(2点)から探索するのではなく、あらかじめ最初の探索点を定義しておきます。

補間検索時間の計算量は通常 O(logN) です

3.3 逐次検索

逐次検索は文字通りの意味で、1 つずつ検索し、時間計算量は O(N) です。

3.4 ハッシュ検索

スペースを気にしない場合は、スペースを時間に交換し、カウントを使用して検索し、キー値を値のインデックスとして使用することができ、時間計算量は O(1) になります。時間を気にしない場合は、順次検索を使用できます。ハッシュ ルックアップは単なる妥協であり、適度な量のスペースと時間を使用して 2 つのバランスをとります。ハッシュ関数により、検索時間の複雑さを柔軟に調整できます。関数の離散性が高い場合は計数検索に相当し、離散的でない場合は連結リストとなり逐次検索に相当します。

アルゴリズムの詳細については、次の章を聞いてください。


さらにエキサイティングなコンテンツ、ぜひ注目してください

志胡: https://www.zhihu.com/people/mei-an-63

ウィーチャット:

 

おすすめ

転載: blog.csdn.net/qq_42672856/article/details/115603237