序文いわゆるソート アルゴリズムは、特定のアルゴリズム要素を通じて、事前に決定されたパターンに従って 1 つ以上のデータ グループを再ソートすることです。この新しいシーケンスは特定のルールに従い、一定の規則性を反映しているため、処理されたデータのスクリーニングと計算が容易になり、計算効率が大幅に向上します。ソートを行うには、まず一定の安定性が必要です。つまり、一定のソート アルゴリズムの後に、シーケンス内に 2 つの同一要素が同時に出現した場合、ソート前後の 2 つの相対的な位置は変化しません。つまり、2 つの要素がまったく同じであっても、ソート処理中に区別され、混乱は許されません。 バブルソートバブルソートは初級レベルのアルゴリズムですが、興味深い使い方もいくつかあります。一般的に言えば、バブルソートを記述する方法は 3 つあります。 一度に 2 つずつ比較して交換し、最大値/最小値を最後の桁までバブルします。 基本アルゴリズム空間計算量はO(1)、時間計算量はO(n2)である。 定数ソート = (arr) => { (i = 0, len = arr.length; i < len-1; i++) の場合{ (j = 0; j < len-1-i; j++) の場合 { もし(arr[j] > arr[j+1])であれば{ [arr[j], arr[j+1]] = [arr[j+1], arr[j]]; } } } リターン } 最も外側の for ループの各ラウンドの後に、残りの数字の最大値が現在のラウンドの最後の桁に移動され、いくつかの隣接する数字が途中で交換されて整然とします。比較の総数は(n-1)+(n-2)+(n-3)+…+1(n−1)+(n−2)+(n−3)+…+1です。 2 番目の書き方は、基本的なアルゴリズムに基づいて改良されています。定数ソート = (arr) => { (i = 0, len = arr.length; i < len - 1; i++) の場合 { isSwap = false とします (j = 0; j < len - 1 - i; j++) の場合 { もし(arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; isSwap = true } } スワップの場合 壊す; } } arr を返します。 }; 空間計算量は O(1)、時間計算量は O(n2) - できれば O(n) です。 最も外側の for ループがラウンドを通過するたびに、残りの数字の最大値は現在のラウンドの最後の桁に移動されます。この方法が最初の方法に比べて優れている点は、比較ラウンドで交換が行われなかった場合、この時点で残りの数字が順番になっているはずなので、ソートが直ちに停止することです。 選択ソート選択ソートの考え方は、配列を二重ループで走査し、比較の各ラウンドの後に最小の要素の添え字を見つけて、それを最初の場所に交換することです。 基本アルゴリズム定数ソート = (arr) => { (i = 0, len = arr.length; i < len - 1; i++) の場合 { minIndex = i とします (j = i+1; j < len; j++) の場合 { もし(arr[i] > arr[j]) { 最小インデックス = j } } [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; } arr を返します。 }; バイナリ選択ソート - 最適化選択ソート アルゴリズムも最適化できます。各トラバース ラウンドで最小値が見つかるので、最大値も探してみませんか?これがバイナリ選択ソートの考え方です。 バイナリ選択ソートを使用すると、選択の各ラウンドで最小値と最大値を記録することで、走査する必要がある配列の範囲を半分に減らすことができます。 定数ソート = (arr) => { (i = 0, len = arr.length; i < len / 2; i++) の場合 { minIndex = i とします。 maxIndex = i とします。 (j = i + 1; j < len-i; j++) の場合 { (arr[minIndex] > arr[j])の場合{ 最小インデックス = j; } (arr[maxIndex] < arr[j])の場合{ 最大インデックス = j; } } minIndex === maxIndexの場合、break; [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; (最大インデックス === i)の場合{ 最大インデックス = 最小インデックス; } 定数 lastIndex = len - i - 1; [arr[最大インデックス]、arr[最終インデックス]] = [arr[最終インデックス]、arr[最大インデックス]]; } arr を返します。 }; 挿入ソート挿入ソートの考え方は非常にシンプルです。人生では非常に一般的なシナリオがあります。ポーカーをプレイするとき、カードを引いたときにそれをソートします。カードを引くたびに、それを手札にある既存のカードの適切な位置に挿入し、徐々にソート全体を完了します。 挿入ソートを記述する方法は 2 つあります。
スワップによる挿入ソート定数ソート = (arr) => { (i = 1、len = arr.length、i < len、i++ とします) { j = iとします。 (j >= 1 && arr[j] < arr[j - 1]) の場合 { [arr[j], arr[j - 1]] = [arr[j - 1], arr[j]]; じーー } } arr を返します。 }; 数字が 2 つ未満の場合は、ソートの問題はなく、もちろん挿入も必要ないので、2 番目の数字から直接挿入します。 モバイル方式交換法挿入ソートでは、数字を毎回交換する必要があることがわかりました。しかし、実際には、新しく挿入された数字は、交換される数字の位置に必ずしも適合するとは限りません。つまり、新しい位置に短時間移動しただけであり、次の比較後に再度交換する必要がある場合は、すぐに前の数字の位置に移動されます。 このことから、最適化の解決策を考えることができます。まず、新しく挿入された数字を比較し、その数字よりも大きい数字を常に後方に移動して、新しい数字に適した位置が見つかるまで、新しい数字を挿入します。 このソリューションでは、新しく挿入された数字を一時的に保存する必要があります。コードは次のとおりです。 定数ソート = (arr) => { (i = 1、len = arr.length、i < len、i++ とします) { j = i-1 とします。 cur = arr[i]とします。 (j >= 0 && cur < arr[j]) の間 { arr[j+1] = arr[j] j--; } arr[j+1] = cur } arr を返します。 }; シェルソート1959 年 7 月、シンシナティ大学で数学の博士号を取得したドナルド シェルは、Communications of the ACM でシェル ソート アルゴリズムを発表しました。このアルゴリズムは、時間の計算量を O(n2) 未満に削減した最初のアルゴリズムの 1 つとなりました。元のシェルソートの最悪の時間計算量は依然として O(n2) ですが、最適化されたシェルソートは O(n1.3) または O(n7/6) に達することもあります。 シェル ソートは、本質的には挿入ソートの最適化です。挿入ソートのシンプルさを活用し、一度に 2 つの隣接する要素しか交換しないという挿入ソートの欠点を克服します。その基本的な考え方は次のとおりです。
最初のパス(5間隔ソート):サブ配列を5の間隔に従って5つのグループに分割します。つまり、[8、1、23]、[3、44]、[34、45]、[6、43]、[4、2]です。これらをソート順に挿入します。ソート後、それぞれ [1, 8, 23]、[3, 44]、[34, 45]、[6, 43]、[2, 4] になります。配列全体は [1, 3, 34, 6, 2, 8, 44, 45, 43, 4, 23] になります。 2 回目のパス (2 間隔ソート): 間隔 2 に従ってサブ配列を 2 つのグループに分割します ([1、34、2、44、43、23]、[3、6、8、45、4])。挿入ソートすると、ソート後は [1, 2, 23, 34, 43, 44]、[3, 4, 6, 8, 45] となり、配列全体は [1, 3, 2, 4, 23, 6, 34, 8, 43, 45, 44] となります。ここで非常に重要な特性があります。2 間隔のソートを完了した後も、配列は 5 間隔の順序のままです。つまり、より狭い間隔でソートしても、前のステップの結果は悪化しません。 3 番目のパス (11 間隔ソート、直接挿入ソートと同じ): 間隔 1 に従ってサブ配列をグループ (配列全体) に分割します。挿入ソートを実行します。最初の 2 回のソートの後、配列は基本的に順序どおりになっているため、この手順ではソートを完了するために少量のスワップのみが必要です。ソート後、配列は[1, 2, 3, 4, 6, 8, 23, 34, 43, 44, 45]となり、ソートが完了します。 定数ソート = arr => { 定数len = arr.length; 長さが2以下の場合 arr を返します。 } ギャップを Math.floor(len / 2) とします。 ギャップ > 0 の場合 (i = ギャップとします; i < len; i++) { j = iとします。 cur = arr[i]とします。 (j >= 0 && cur < arr[j - ギャップ]) { arr[j] = arr[j - ギャップ]; j -= ギャップ; } arr[j] = cur; } ギャップ = Math.floor(ギャップ / 2); } arr を返します。 } ヒープソートヒープソートのプロセスは次のとおりです。
関数sort(arr) { (i = Math.floor(arr.length / 2) - 1 とします; i >= 0; i--) { ヒープを調整します(arr, i, arr.length) } (j = arr.length - 1; j > 0; j--) の場合 { [arr[0], arr[j]] = [arr[j], arr[0]] ヒープを調整(arr, 0, j) } } 関数adjustHeap(arr, i, length) { tmp = arr[i]とする (k = i * 2 + 1 とします; k < 長さ; k = k * 2 + 1) { (k + 1 < 長さ && arr[k] < arr[k + 1]) の場合 { 関数 } (arr[k] > tmp)の場合{ arr[i] = arr[k]; 私 = k; } それ以外 { 壊す; } arr[i] = tmp; } } クイックソートクイックソートアルゴリズムは、1960 年に CAR Hoare によって提案されました。その時間計算量も O(nlogn) ですが、時間計算量が O(nlogn) であるいくつかのソートアルゴリズムの中では、ほとんどの場合にクイックソートの方が効率的であるため、広く使用されています。さらに、クイックソートが採用している分割統治の考え方は非常に実用的であり、クイックソートが面接官の間で非常に人気があるため、クイックソートの考え方を習得することは特に重要です。 クイックソートアルゴリズムの基本的な考え方は次のとおりです。
const パーティション = (arr, 開始, 終了) => { let pivot = arr[start]; // 最初の数値を基数として取得します。let left = start + 1; // 2 番目の数値から分割を開始します。let right = end; // 右境界 // left と right が出会ったらループを終了します。while (left < right) { // カーディナリティより大きい最初の位置を検索します while (left < right && arr[left] <= pivot) left++; // これら 2 つの数値を入れ替えて、左のパーティションがカーディナリティ以下になり、右のパーティションがカーディナリティ以上になるようにします。if (left != right) { [arr[左], arr[右]] = [arr[右], arr[左]]; 右 - ; } } // 左と右が等しい場合は、arr[right] と pivot を別々に比較します if (left == right && arr[right] > pivot) right--; // ベースと中央を入れ替えます if (right != start) [arr[left], pivot] = [pivot, arr[left]]; // 中央の値の添字を返します return right; } const クイックソート = (arr, 開始, 終了) => { (開始 >= 終了) の場合、戻り値: const 中間 = パーティション (arr、開始、終了) クイックソート(arr, start, middle - 1); クイックソート(arr, 中間 + 1, 終了); } 定数ソート = arr => { クイックソート(arr, 0, arr.length -1); } マージソートマージソートは、マージ操作に基づいた効果的なソートアルゴリズムです。このアルゴリズムは、分割統治法の非常に典型的な応用です。順序付けられたサブシーケンスをマージして、完全に順序付けられたシーケンスを取得します。つまり、最初に各サブシーケンスを順序付けし、次にサブシーケンスのセグメントを順序付けます。 2 つの順序付きリストが 1 つの順序付きリストに結合される場合は、2 方向の結合と呼ばれます。 アルゴリズムの説明
const マージ = (左、右) => { 結果 = [] とします。 (左の長さ>0&右の長さ>0){ (左[0] <= 右[0])の場合{ 結果をプッシュします(左にシフトします()); } それ以外 { 結果を右に押します。 } } left.length を result.push(left.shift()); しながら right.length を result.push(right.shift()); しながら 結果を返します。 } 定数ソート = (arr) => { len = arr.length;とします。 長さが2以下の場合 arr を返します。 } const 中間 = Math.floor(len / 2)、 左 = arr.slice(0, 中央)、 右 = arr.slice(中央); merge(sort(left), sort(right)) を返します。 }; 要約するこれで、JavaScript で実装された 7 つのソートアルゴリズムに関するこの記事は終了です。JavaScript ソートアルゴリズムに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Linux で SVN サーバーをインストールする方法
>>: MySQLにおけるSQLの実行順序についてのちょっとした質問
この記事では、ドラミング効果を実現するためのJavascriptの具体的なコードを参考までに紹介しま...
デフォルトでは、Linux の MySQL はテーブル名の大文字と小文字を区別します。 MySQL ...
2 端揃えを実現する div+css レイアウトは、Web ページの組版でよく使用されます。この記事...
ページ: ベース: <テンプレート> <div class="タブコンテ...
目次序文応用フィルタードラッグファイル間での参照の受け渡しwxsはjsロジック層にパラメータを渡しま...
チャレンジ:文字列内の文字 &、<、>、" (二重引用符)、および &...
uwsgi+nginx プロキシ Django をデプロイする場合、uwsgi を使用したアクセスは...
1. --cpu=<値> 1) コンテナが使用できるCPUリソースの量を指定しますが、コ...
目次1. 観察可能2. 高階関数3. エクスプレスボックスモデル3.1. エクスプレスボックスモデル...
さっそく、コードを直接投稿します。具体的なコードは次のとおりです。 <!DOCTYPE htm...
Linux viコマンドの詳しい説明vi エディタは、すべての Unix および Linux システ...
最新のソリューション: -v /usr/share/zoneinfo/Asia/Shanghai:/...
Web ページのパフォーマンスを向上させるために、多くの開発者は、JavaScript、画像の最適化...
今日、MySQL の無料インストール版をデプロイしたところ、テーブル 'mysql.plug...
以下の質問はすべて InnoDB ストレージ エンジンに基づいています。 1. 最も大きな ID を...