mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-09 12:36:50 +08:00
build
This commit is contained in:
@@ -160,12 +160,6 @@ comments: true
|
||||
[class]{}-[func]{bubble_sort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="bubble_sort.zig"
|
||||
[class]{}-[func]{bubbleSort}
|
||||
```
|
||||
|
||||
## 11.3.2 効率の最適化
|
||||
|
||||
「バブリング」のラウンド中に交換が発生しない場合、配列はすでにソートされているため、すぐに戻ることができます。これを検出するために、`flag`変数を追加できます;パスで交換が行われない場合は、フラグを設定して早期に戻ります。
|
||||
@@ -298,12 +292,6 @@ comments: true
|
||||
[class]{}-[func]{bubble_sort_with_flag}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="bubble_sort.zig"
|
||||
[class]{}-[func]{bubbleSortWithFlag}
|
||||
```
|
||||
|
||||
## 11.3.3 アルゴリズムの特性
|
||||
|
||||
- **$O(n^2)$の時間計算量、適応ソート。** 各「バブリング」ラウンドは長さ$n - 1$、$n - 2$、$\dots$、$2$、$1$の配列セグメントを横断し、合計は$(n - 1) n / 2$となります。`flag`最適化により、配列がすでにソートされている場合、最良ケース時間計算量は$O(n)$に達する可能性があります。
|
||||
|
||||
@@ -171,12 +171,6 @@ comments: true
|
||||
[class]{}-[func]{bucket_sort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="bucket_sort.zig"
|
||||
[class]{}-[func]{bucketSort}
|
||||
```
|
||||
|
||||
## 11.8.2 アルゴリズムの特徴
|
||||
|
||||
バケットソートは非常に大きなデータセットの処理に適しています。例えば、入力データに100万個の要素が含まれ、システムメモリの制限によりすべてのデータを同時にロードできない場合、データを1,000個のバケットに分割し、各バケットを個別にソートしてから結果をマージできます。
|
||||
|
||||
@@ -157,12 +157,6 @@ comments: true
|
||||
[class]{}-[func]{counting_sort_naive}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="counting_sort.zig"
|
||||
[class]{}-[func]{countingSortNaive}
|
||||
```
|
||||
|
||||
!!! note "計数ソートとバケットソートの関係"
|
||||
|
||||
バケットソートの観点から、計数ソートにおける計数配列 `counter` の各インデックスをバケットと考え、カウントの過程を要素を対応するバケットに分散させることと考えることができます。本質的に、計数ソートは整数データのためのバケットソートの特別なケースです。
|
||||
@@ -376,12 +370,6 @@ $$
|
||||
[class]{}-[func]{counting_sort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="counting_sort.zig"
|
||||
[class]{}-[func]{countingSort}
|
||||
```
|
||||
|
||||
## 11.9.3 アルゴリズムの特徴
|
||||
|
||||
- **時間計算量は $O(n + m)$、非適応ソート**:`nums` と `counter` の走査が含まれ、どちらも線形時間を使用します。一般的に、$n \gg m$ であり、時間計算量は $O(n)$ に近づきます。
|
||||
|
||||
@@ -268,14 +268,6 @@ comments: true
|
||||
[class]{}-[func]{heap_sort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="heap_sort.zig"
|
||||
[class]{}-[func]{siftDown}
|
||||
|
||||
[class]{}-[func]{heapSort}
|
||||
```
|
||||
|
||||
## 11.7.2 アルゴリズムの特徴
|
||||
|
||||
- **時間計算量は $O(n \log n)$、非適応ソート**:ヒープの構築は $O(n)$ 時間を使用します。ヒープから最大要素を抽出するには $O(\log n)$ 時間がかかり、$n - 1$ ラウンドループします。
|
||||
|
||||
@@ -141,12 +141,6 @@ comments: true
|
||||
[class]{}-[func]{insertion_sort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="insertion_sort.zig"
|
||||
[class]{}-[func]{insertionSort}
|
||||
```
|
||||
|
||||
## 11.4.2 アルゴリズムの特性
|
||||
|
||||
- **時間計算量は$O(n^2)$、適応ソート**:最悪の場合、各挿入操作には$n - 1$、$n-2$、...、$2$、$1$のループが必要で、合計は$(n - 1) n / 2$となり、時間計算量は$O(n^2)$です。順序付きデータの場合、挿入操作は早期に終了します。入力配列が完全に順序付けられている場合、挿入ソートは最良時間計算量$O(n)$を実現します。
|
||||
|
||||
@@ -274,14 +274,6 @@ comments: true
|
||||
[class]{}-[func]{merge_sort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="merge_sort.zig"
|
||||
[class]{}-[func]{merge}
|
||||
|
||||
[class]{}-[func]{mergeSort}
|
||||
```
|
||||
|
||||
## 11.6.2 アルゴリズムの特性
|
||||
|
||||
- **$O(n \log n)$の時間計算量、非適応ソート**:分割により高さ$\log n$の再帰ツリーが作成され、各層で合計$n$回の操作をマージし、全体的な時間計算量は$O(n \log n)$となります。
|
||||
|
||||
@@ -183,14 +183,6 @@ comments: true
|
||||
[class]{QuickSort}-[func]{partition}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="quick_sort.zig"
|
||||
[class]{QuickSort}-[func]{swap}
|
||||
|
||||
[class]{QuickSort}-[func]{partition}
|
||||
```
|
||||
|
||||
## 11.5.1 アルゴリズムプロセス
|
||||
|
||||
クイックソートの全体的なプロセスは下図に示されます。
|
||||
@@ -310,12 +302,6 @@ comments: true
|
||||
[class]{QuickSort}-[func]{quick_sort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="quick_sort.zig"
|
||||
[class]{QuickSort}-[func]{quickSort}
|
||||
```
|
||||
|
||||
## 11.5.2 アルゴリズムの特徴
|
||||
|
||||
- **$O(n \log n)$の時間計算量、非適応ソート**:平均的なケースでは、ピボット分割の再帰レベルは$\log n$で、レベルあたりのループの総数は$n$であり、全体で$O(n \log n)$の時間を使用します。最悪の場合、各ラウンドのピボット分割は長さ$n$の配列を長さ$0$と$n - 1$の2つのサブ配列に分割し、再帰レベル数が$n$に達すると、各レベルのループ数は$n$で、使用される総時間は$O(n^2)$です。
|
||||
@@ -520,14 +506,6 @@ comments: true
|
||||
[class]{QuickSortMedian}-[func]{partition}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="quick_sort.zig"
|
||||
[class]{QuickSortMedian}-[func]{medianThree}
|
||||
|
||||
[class]{QuickSortMedian}-[func]{partition}
|
||||
```
|
||||
|
||||
## 11.5.5 末尾再帰最適化
|
||||
|
||||
**特定の入力では、クイックソートはより多くの空間を占有する可能性があります**。例えば、完全に順序付けられた入力配列を考えてみましょう。再帰でのサブ配列の長さを$m$とします。各ラウンドのピボット分割で、長さ$0$の左サブ配列と長さ$m - 1$の右サブ配列が生成されます。これは、再帰呼び出しごとに問題サイズが1つの要素のみ減少することを意味し、各レベルの再帰での削減が非常に小さくなります。
|
||||
@@ -654,9 +632,3 @@ comments: true
|
||||
```ruby title="quick_sort.rb"
|
||||
[class]{QuickSortTailCall}-[func]{quick_sort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="quick_sort.zig"
|
||||
[class]{QuickSortTailCall}-[func]{quickSort}
|
||||
```
|
||||
|
||||
@@ -280,16 +280,6 @@ $$
|
||||
[class]{}-[func]{radix_sort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="radix_sort.zig"
|
||||
[class]{}-[func]{digit}
|
||||
|
||||
[class]{}-[func]{countingSortDigit}
|
||||
|
||||
[class]{}-[func]{radixSort}
|
||||
```
|
||||
|
||||
!!! question "なぜ最下位桁から開始するのか?"
|
||||
|
||||
連続するソートラウンドでは、後のラウンドの結果が前のラウンドの結果を上書きします。例えば、最初のラウンドの結果が $a < b$ で、2番目のラウンドが $a > b$ の場合、2番目のラウンドの結果が最初のラウンドの結果を置き換えます。上位桁は下位桁より優先されるため、上位桁の前に下位桁をソートすることが理にかなっています。
|
||||
|
||||
@@ -170,12 +170,6 @@ comments: true
|
||||
[class]{}-[func]{selection_sort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="selection_sort.zig"
|
||||
[class]{}-[func]{selectionSort}
|
||||
```
|
||||
|
||||
## 11.2.1 アルゴリズムの特性
|
||||
|
||||
- **$O(n^2)$の時間計算量、非適応ソート**:外側ループに$n - 1$回の反復があり、未ソートセクションの長さは最初の反復で$n$から始まり、最後の反復で$2$まで減少します。つまり、各外側ループ反復にはそれぞれ$n$、$n - 1$、$\dots$、$3$、$2$回の内側ループ反復が含まれ、合計は$\frac{(n - 1)(n + 2)}{2}$となります。
|
||||
|
||||
Reference in New Issue
Block a user