ホームページ > バックエンド開発 > Python チュートリアル > 並べ替えアルゴリズム ||パイソン ||データ構造とアルゴリズム

並べ替えアルゴリズム ||パイソン ||データ構造とアルゴリズム

Mary-Kate Olsen
リリース: 2024-12-18 09:08:11
オリジナル
650 人が閲覧しました

Sorting Algorithms || Python || Data Structures and Algorithms

並べ替えアルゴリズム

1. バブルソート

ここでは、配列の最後に到達するまで、上位の要素をその隣の要素と交換します。これで、最上位の要素が最後の位置になります。そこで、境界を変更して、最後から 1 ずつ減らします。最悪の場合、配列をソートするには n 回反復する必要があります。

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        swapped = False

        # Last i elements are already in place, so we don't need to check them
        for j in range(0, n-i-1):
            # Swap if the element found is greater than the next element
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]  # Swap the elements
                swapped = True
        if not swapped:
            break

    return arr
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

アルゴリズム -

  1. 配列を反復処理して最大の要素を見つけ、それを最後の要素と交換します。
  2. 隣接するすべての要素を比較し、大きい要素が小さい要素の前にある場合は交換します。配列の最後に到達するまでこれを続けます。
  3. フラグを維持します。交換される要素がない場合は、配列がソートされるため、ループを中断できます。

時間計算量:

  • ベストケース - 配列がすでにソートされている場合、必要な反復は 1 回だけです。時間計算量 - O(n)
  • 平均ケース - 配列がランダムにソートされている場合、時間計算量 - O(n2)
  • 最悪のケース - 配列が降順の場合、n*2 回の反復が必要になります。

空間の複雑さ - O(1)、追加のメモリは必要ありません。

利点 -

  1. 追加のメモリは必要ありません。

  2. 要素が相対的な順序を維持するため安定しています。

欠点 -

  1. 時間計算量 - O(n2)。大規模なデータセットでは非常に高くなります。

アプリケーション -

  1. データセットが非常に小さく、時間の複雑さによる非効率性よりも単純さが優先される場合にのみ使用できます。

2. 選択範囲の並べ替え

ここでは、配列内の最小の要素を見つけて、それを最初の要素に置き換えます。次に、境界を 1 ずつ増やし、配列の最後に到達するまで同じ手順を繰り返します。

def selectionSort(a):
    i = 0
    while i<len(a):

        smallest = min(a[i:])
        index_of_smallest = a.index(smallest)
        a[i],a[index_of_smallest] = a[index_of_smallest],a[i]

        i=i+1
    return a
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

アルゴリズム -

  1. 配列を反復処理して最小要素を見つけます。

  2. 最初の要素と交換し、ポインタを 1 増やします。

  3. 配列の最後に到達するまでこのプロセスを繰り返します。

時間計算量: 3 つのケースすべてで O(n2) の時間計算量があります: 最高、平均、最悪。 これは、最小限の要素を選択する必要があるためです。配列がすでにソートされているかどうかに関係なく、毎回それを交換します。

空間の複雑さ - O(1)、追加のメモリは必要ありません。

利点 -

  1. 追加のメモリは必要ありません。

  2. バブルソートよりも少ないスワップが行われます。

欠点 -

  1. 時間計算量 - O(n2)。大規模なデータセットでは非常に高くなります。

  2. 等しい要素の相対的な順序が維持されないため、安定していません。

アプリケーション -

  1. 追加のストレージを必要としないため、メモリが限られたシステムでも使用できます。

  2. これは、書き込み操作が遅いシステムなど、スワップ数を最小限に抑えることが重要なシステムで使用されます。

3. 挿入ソート

これは、要素の位置から配列の先頭まで逆方向に反復チェックすることで、ソートされていない要素を正しい位置に挿入するアルゴリズムです。

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        swapped = False

        # Last i elements are already in place, so we don't need to check them
        for j in range(0, n-i-1):
            # Swap if the element found is greater than the next element
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]  # Swap the elements
                swapped = True
        if not swapped:
            break

    return arr
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

アルゴリズム -

  1. 配列の 2 番目の要素から開始して、最初の要素と比較します。現在の要素が最初の要素より小さい場合は、それらを交換します。

  2. ここでポインターを増やし、3 番目の要素に対してこれを行います。2 番目と最初の要素と比較します。

  3. 残りの要素についても同じプロセスを繰り返し、前のすべての要素と比較し、適切な位置に挿入します。

時間計算量:

- 最良のケース - 配列がすでにソートされている場合、必要な反復は 1 回だけです。時間計算量は O(n)
- 平均的なケース - 配列がランダムにソートされている場合、時間計算量は O(n2)
- 最悪の場合 - 配列が降順の場合、n2 回の反復が必要になります。

空間の複雑さ - O(1)、追加のメモリは必要ありません。

利点 -

  1. 追加のメモリは必要ありません。
  2. 要素が相対的な順序を維持するため、安定しています。

欠点 -

  1. 時間計算量 - O(n2)。大規模なデータセットでは非常に高くなります。

  2. 等しい要素の相対的な順序が維持されないため、安定していません。

アプリケーション -

  1. ライブ データ ストリームなど、要素がリアルタイムで到着し、並べ替える必要があるシナリオでは効率的です。

4. マージソート

マージ ソートは、分割統治アプローチに従うアルゴリズムです。これには 2 つの主なステップがあります。1 番目は配列を再帰的に分割し、2 番目は分割された配列をソート順にマージします。

def selectionSort(a):
    i = 0
    while i<len(a):

        smallest = min(a[i:])
        index_of_smallest = a.index(smallest)
        a[i],a[index_of_smallest] = a[index_of_smallest],a[i]

        i=i+1
    return a
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

アルゴリズム -

  1. 中点を計算して配列を 2 つの半分に分割します。

  2. 各部分配列の長さが 1 になるまで分割を続けます。

  3. 両方の半分、つまり左半分と右半分でマージ関数を呼び出します。

  4. マージプロセスには 3 つのポインターを使用します:

  • 左半分の配列の最初のポインタ。
  • 配列の右半分の 2 番目のポインタ。
  • ソートされた配列の 3 番目のポインター。
  1. 両方の半分を反復処理し、それらの要素を比較します。小さい方の要素をソートされた配列に挿入し、対応するポインタを 1 ずつインクリメントします。

  2. 配列全体がソートされるまで、このプロセスを再帰的に繰り返します。

時間計算量: マージ ソートの時間計算量は、最高、平均、最悪の 3 つのケースすべてで O(n log n) です。これは、配列が既にソートされているかどうかに関係なく、分割と結合のたびに同じ手順が実行されるためです。

O( log n ) - 配列サイズは分割フェーズ中の各ステップで半分になります。

O(n) - マージプロセス中に、すべての要素を 1 回反復する必要があります。

したがって、合計時間計算量は O (n) * O (log n) = O (n log n)

空間の複雑さ - O(n)、一時配列を保存するためにマージ プロセス中に追加のメモリが必要です。

利点 -

  1. 要素が相対的な順序を維持するため、安定しています。

  2. 大規模なデータセットであっても、時間計算量は O (n log n) です。

  3. 部分配列が独立してマージされるため、並列処理に適しています。

欠点 -

  1. 時間計算量 - O(n2)。大規模なデータセットでは非常に高くなります。
  2. マージプロセスには追加のメモリが必要です。
  3. 追加のメモリが必要なため、設置されていません。
  4. 一般に、ほとんどのデータセットでは QuickSort よりも遅くなります。

アプリケーション -

  1. 大きなファイルのマージなど、データが大きすぎてメモリに収まらない状況で使用されます。
  2. ランダムアクセスが必要ないため、リンクリストをソートするために使用されます。

5. クイックソート

クイック ソートは、分割統治アプローチに従ったアルゴリズムです。ピボット要素を選択し、ピボットを正しい並べ替え位置に配置した後、ピボット要素を中心に配列を分割します。

最初のステップは、ピボット要素を選択し、ピボットを中心に配列を分割することです。ピボットより小さい要素はすべて左側にあり、ピボットより大きい要素はすべて右側にあります。これで、ピボットは正しいソート位置に配置されます。再帰的には、配列を 2 つの半分に分割することによって、同じプロセスが適用されます。前半にはピボット前の要素が含まれ、後半にはピボット後の要素が含まれます。このプロセスは、各部分配列の長さが 1 に達するまで繰り返されます。

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        swapped = False

        # Last i elements are already in place, so we don't need to check them
        for j in range(0, n-i-1):
            # Swap if the element found is greater than the next element
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]  # Swap the elements
                swapped = True
        if not swapped:
            break

    return arr
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

アルゴリズム -

  1. 中点を計算して配列を 2 つの半分に分割します。
  2. ピボットを選択します。任意の要素をピボットとして選択できます。
  3. 配列を反復処理し、各要素をピボットと比較します。
  4. ピボットより小さい要素はすべて左側に、ピボットより大きい要素はすべて右側に配置します。
  5. ピボットが正しいソート位置に配置されるように、ピボットを左ポインターと交換します。
  6. パーティションの長さが 1 より大きくなるまで、このプロセスを再帰的に繰り返します。

時間計算量:

1.最良のケース - 時間計算量 - O(n log n)、ピボットが配列を 2 つの等しい半分に分割する場合。
2.平均的なケース - 時間計算量 - O(n log n)、ピボットが配列を 2 つの等しい半分に分割する場合。しかし、必ずしも等しいわけではありません。
3.最悪の場合 - 時間計算量 - O(n2) 、時 -

  • すでにソートされた配列のピボットとして最小の要素が選択されます。

  • 降順でソートされた配列内のピボットとして最大の要素が選択されます。

O( log n ) - 配列サイズは分割フェーズ中の各ステップで半分になります。

O(n) - 要素の順序付け中。

したがって、合計時間計算量は O (n) * O (log n) = O (n log n)

空間の複雑さ:

  1. 最良および平均のケース - O( log n) - 再帰スタックの場合。

  2. 最悪の場合 - O(n) - 再帰スタックの場合。

利点 -

  1. ピボットの選択が間違っていなければ、大規模なデータセットに対して効率的です。
  2. 同じ配列でソート作業を行い、データを補助配列にコピーしないため、キャッシュに優しいです。
  3. 安定性が必要ない場合の大規模データ向けの最速の汎用アルゴリズムの 1 つ。

欠点 -

  1. 時間計算量 - O(n2)。大規模なデータセットでは非常に高くなります。
  2. 等しい要素の相対的な順序が維持されないため、安定していません。

アプリケーション -

  1. プログラミング ライブラリとフレームワークで使用されます。たとえば、Python のsorted() 関数と Java の Array.sort() はクイック ソートに基づいています。
  2. クエリ実行中に行を効率的に並べ替えることにより、indDatabase クエリの最適化に使用されます。
  3. キャッシュに適した特性があるため、大規模なデータセットのメモリ内での並べ替えに適しています。

6.ヒープソート

ヒープ ソートは、比較ベースのソート アルゴリズムです。これは選択ソートの拡張機能です。ヒープ ソートでは、バイナリ ヒープを作成し、最大または最小の要素を最後の要素と交換します。次に、ヒープ サイズを 1 減らします。このプロセスは、ヒープの長さが 1 より大きくなるまで繰り返されます。

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        swapped = False

        # Last i elements are already in place, so we don't need to check them
        for j in range(0, n-i-1):
            # Swap if the element found is greater than the next element
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]  # Swap the elements
                swapped = True
        if not swapped:
            break

    return arr
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

アルゴリズム -

  1. heapify プロセスを使用して最大ヒープを構築します。 Heapify は、バイナリ ヒープ データ構造のヒープ プロパティを維持するために使用されるメソッドです。
  2. 配列のサイズが n の場合、n//2 個の親ノードが含まれます。
  3. インデックス i の親の場合:

a.その左側の子はインデックス 2i 1 にあります

b.その右側の子はインデックス 2i 2

にあります。
  1. インデックス n//2 から 0 までの親を持つすべてのサブツリーを反復処理し、それらに対して heapify 関数を呼び出します。
  2. これで、配列は最大ヒープになり、最大の要素はインデックス 0 になります。
  3. ヒープの最初の要素と最後の要素を交換し、ヒープのサイズを 1 減らします。
  4. ヒープの長さが 1 より大きくなるまでこのプロセスを繰り返します

時間計算量: ヒープ ソートの時間計算量は、最良、平均、最悪の 3 つのケースすべてで O(n log n) です。これは、配列が既にソートされているかどうかに関係なく、最大ヒープが作成され要素が交換されるたびに同じ手順が実行されるためです。

O( log n ) - 最大ヒープを作成します

O(n) - 最大ヒープが作成され、要素が n 回スワップされるため。

したがって、合計時間計算量は O (n) * O (log n) = O (n log n)

空間複雑度 : すべての場合 - O( log n) - 再帰的スタックの場合。

利点 -

  1. 大規模なデータセットであっても、時間計算量は O (n log n) です。
  2. メモリ使用量はほぼ一定です。

欠点 -

  1. 等しい要素の相対的な順序が維持されないため、安定していません。
  2. マージソートと比較して多くのスワップが必要です。

アプリケーション -

  1. 最大要素または最小要素の抽出が頻繁に行われる優先キューの実装に役立ちます。
  2. インプレースソートが必要でメモリ使用量が重要なシステムで役立ちます。
  3. ランキングが必要なシナリオで使用されます。

7.カウンティングソートと基数ソート

カウンティング ソートは、非比較ベースのソート アルゴリズムです。これは、入力値の範囲がソート対象の要素の数に比べて小さい場合に特に効率的です。カウンティング ソートの背後にある基本的な考え方は、入力配列内の個別の各要素の頻度をカウントし、その情報を使用して要素を正しいソート位置に配置することです。

基数ソートは、サブルーチンとしてカウンティング ソートを使用します。数値の各桁にカウンティング ソートを適用し、配列内の最大の数値のすべての桁が処理されるまでソートを繰り返します。

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        swapped = False

        # Last i elements are already in place, so we don't need to check them
        for j in range(0, n-i-1):
            # Swap if the element found is greater than the next element
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]  # Swap the elements
                swapped = True
        if not swapped:
            break

    return arr
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
def selectionSort(a):
    i = 0
    while i<len(a):

        smallest = min(a[i:])
        index_of_smallest = a.index(smallest)
        a[i],a[index_of_smallest] = a[index_of_smallest],a[i]

        i=i+1
    return a
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

アルゴリズム -

  1. 配列内の最大数を見つけて、その桁数 (d) を決定します。数値の長さが d の場合、配列に対して Counting Sort が d 回呼び出されます。

  2. コール カウンティング 配列内の各桁を 1 の位から順に並べ替え、次に 10 の位まで並べます。

  3. カウントソート中:

  • まず、インデックス配列を作成し、その値に基づいて要素をマップします。たとえば、数字が 4 の場合、インデックス配列の 4 番目のインデックスの値を増分します。
  • インデックス配列からプレフィックス合計配列を作成します。
  • プレフィックス合計配列を使用して、入力配列の長さに等しい新しい並べ替えられた配列を作成します
  • たとえば、プレフィックス合計配列のインデックス 1 の値が 2 である場合、ソートされた配列の位置 2 に値 1 を配置し、プレフィックス合計配列の値を 1 ずつ減分します

時間計算量:

Counting Sort の時間計算量は O(n k) です。ここで、n は並べ替える要素の数、k は値の範囲 (インデックス配列のサイズ) です。この計算量は次の場合に有効です。 3 つのケースすべて: 最良、平均、最悪。

これは、配列が既にソートされているかどうかに関係なく、毎回同じ手順が実行されるためです。

基数ソート の時間計算量は d 倍に増加します。ここで、d は配列内の最大の数値の桁数です。時間計算量は O (d * (n k))

したがって、合計時間計算量は O (d) * O(n k) = O (d * (n k)) となります

空間複雑度: すべての場合 - O(n k)、n は入力配列の長さ、k はインデックス配列内の値の範囲です。

利点 -

  1. 要素が相対的な順序を維持するため安定しています。
  2. カウント ソートは、入力範囲が入力数のオーダーである場合、通常、マージ ソートやクイックソートなどのすべての比較ベースの並べ替えアルゴリズムよりも高速に実行されます。

欠点 -

  1. カウントソートは 10 進数値では機能しません。
  2. ソートする値の範囲が非常に大きい場合、カウントソートは非効率的です。
  3. 余分なスペース O(O(n m)) を使用するため、ソート アルゴリズムが実装されていません。

アプリケーション -

  1. 文字列内の文字の出現数をカウントするなどのアプリケーションで使用されます。
  2. ID や電話番号など、広範囲の値を持つ整数を並べ替える場合に便利です。
  3. 日付やタプルなど、複数のキーを使用してデータを並べ替える場合に効率的です。

以上が並べ替えアルゴリズム ||パイソン ||データ構造とアルゴリズムの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート