頑固なマージソートアルゴリズム

頑固なマージソートアルゴリズム

この記事はWeChatの公開アカウント「Beta Learns JAVA」から転載したもので、著者はSilently9527です。この記事を転載する場合は、Beta Learning JAVA パブリック アカウントにお問い合わせください。

序文

この記事では、マージ操作に基づいてソートを完了するアルゴリズムについて説明します。

マージソートアルゴリズムのアイデア

配列をソートするには、まず配列を 2 つの配列に分割して別々にソートし、次に結果をマージして、配列全体がソートされるまでこのプロセスを再帰的に繰り返します。これがマージ ソートのアルゴリズムの考え方です。

マージソートの利点は、任意の長さ N の配列をソートするのに必要な時間が NlogN に比例することを保証できることです。これはプライマリソートでは実現できない利点です。

欠点は、マージ操作では追加の配列の導入が必要となり、追加のスペースが N に比例することです。

インプレースマージの実装

マージソートを実装する前に、2 つの順序付き配列のマージ操作を完了する必要があります。つまり、2 つの順序付き配列を 1 つの順序付き配列にマージする必要があります。

  • このプロセスでは、補助配列を導入する必要があります。
  • 定義されているメソッド シグネチャは merge(a, lo, mid, hi) です。このメソッドは、配列 a[lo..mid] と a[mid..hi] を順序付けられた配列にマージし、その結果を a[lo..mid] に格納します。
  • このメソッドでは、前回の記事で説明したパブリック関数をあまり使用する必要はありません。前回の記事「一般的なプライマリソートアルゴリズム、今回はすべて理解する」を参照してください。
  1. パブリッククラス MergeSort は SortTemplate を実装します {
  2. プライベートComparable[] aux;
  3.  
  4. @オーバーライド
  5. パブリックvoid ソート(比較可能な[] 配列) {
  6. //実装予定
  7. }
  8.  
  9. プライベートvoidマージ(比較可能[] a、 int lo、 int mid、 int hi) {
  10. ( int i = lo; i <= hi; i++) {
  11. 補助[i] = a[i];
  12. }
  13. int i = lo、j = mid + 1;
  14. ( int k = lo; k <= hi; k++) {
  15. もし(i>中間){
  16. a[k] = aux[j++];
  17. }そうでなければ (j > hi) {
  18. a[k] = aux[i++];
  19. } そうない場合 (aux[i], aux[j]) {
  20. a[k] = aux[i++];
  21. }それ以外{
  22. a[k] = aux[j++];
  23. }
  24. }
  25. }
  26.  
  27. }

トップダウンマージソート

分割統治の考え方に基づいて、大きな配列は、最初に小さな配列に再帰的に分割し、小さな配列が整然と並んでいることを確認してから、配列全体が整然と並ぶまでそれらをマージすることによってソートされます。この操作は、トップダウンマージソートと呼ばれます。

  1. パブリッククラス MergeSort は SortTemplate を実装します {
  2. プライベートComparable[] aux;
  3.  
  4. @オーバーライド
  5. パブリックvoid ソート(比較可能な[] 配列) {
  6. aux = 新しいComparable[配列.長さ];
  7. doSort(配列、0、配列の長さ - 1);
  8. }
  9.  
  10. プライベートvoid doSort(Comparable[]配列、 int lo、 int hi) {
  11. (最低 >= 最高)の場合{
  12. 戻る;
  13. }
  14. int mid = (hi - lo) / 2 + lo;
  15. doSort(配列、lo、mid);
  16. doSort(配列、mid + 1、hi);
  17. マージ(配列、lo、mid、hi);
  18. }
  19.  
  20. プライベートvoidマージ(比較可能[] a、 int lo、 int mid、 int hi) {
  21. //省略
  22. }
  23.  
  24. }

上記のコードは標準的な再帰マージソート操作ですが、慎重に検討すればアルゴリズムを最適化できます。

「配列がすでに順序付けられているかどうかをテストする」; a[mid]<=a[mid+1]の場合、マージメソッドをスキップしてマージ操作を減らすことができます。修復後のdoSortメソッド

  1. プライベートvoid doSort(Comparable[]配列、 int lo、 int hi) {
  2. (最低 >= 最高)の場合{
  3. 戻る;
  4. }
  5. int mid = (hi - lo) / 2 + lo;
  6. doSort(配列、lo、mid);
  7. doSort(配列、mid + 1、hi);
  8. 配列[mid].compareTo(配列[mid + 1]) >= 0の場合{
  9. マージ(配列、lo、mid、hi);
  10. }
  11. }

「小さな配列の場合は、挿入ソートを使用できます」。小さな配列にマージソートを使用すると再帰呼び出しスタックが増加するため、サブ配列のソートを処理するために挿入ソートを使用することを検討できます。

  1. プライベートvoid doSort(Comparable[]配列、 int lo、 int hi) {
  2. (最低 >= 最高)の場合{
  3. 戻る;
  4. }
  5.  
  6. if (hi - lo < 5) { //テスト、5未満の場合、挿入ソートを使用する
  7. 挿入ソート(配列、lo、hi);
  8. 戻る;
  9. }
  10.  
  11. int mid = (hi - lo) / 2 + lo;
  12. doSort(配列、lo、mid);
  13. doSort(配列、mid + 1、hi);
  14. if (less(配列[mid + 1], 配列[mid])) {
  15. マージ(配列、lo、mid、hi);
  16. }
  17. }
  18.  
  19. // ソートを挿入
  20. プライベートvoid挿入ソート(比較可能な配列[]、 int lo、 int hi) {
  21. ( int i = lo; i <= hi; i++) {
  22. for ( int j = i; j > lo && less(array[j], array[j - 1]); j --) {  
  23. exch(配列、j、j - 1);
  24. }
  25. }
  26. }

「補助配列に要素をコピーする時間を節約する」; この操作を実装するのはより面倒であり、再帰の各レベルで入力データと出力配列の役割を交換する必要があります。変更後の完全なコードは次のとおりです。

  1. パブリッククラス MergeSort は SortTemplate を実装します {
  2. プライベートComparable[] aux;
  3.  
  4. @オーバーライド
  5. パブリックvoid ソート(比較可能な[] 配列) {
  6. aux = 配列.clone();
  7. doSort(aux, 配列, 0, 配列の長さ - 1);
  8. }
  9.  
  10. プライベートvoid doSort(Comparable[] src、Comparable[] dest、 int lo、 int hi) {
  11. (最低 >= 最高)の場合{
  12. 戻る;
  13. }
  14.  
  15. if (hi - lo < 5) { //テスト、5未満の場合、挿入ソートを使用する
  16. 挿入ソート(dest, lo, hi);
  17. 戻る;
  18. }
  19.  
  20. int mid = (hi - lo) / 2 + lo;
  21. doSort(dest, src, lo, mid);
  22. doSort(dest, src, mid + 1, hi);
  23. if (less(src[mid + 1], src[mid])) {
  24. マージ(src、dest、lo、mid、hi);
  25. }
  26. }
  27.  
  28. // ソートを挿入
  29. プライベートvoid挿入ソート(比較可能な配列[]、 int lo、 int hi) {
  30. ( int i = lo; i <= hi; i++) {
  31. for ( int j = i; j > lo && less(array[j], array[j - 1]); j --) {  
  32. exch(配列、j、j - 1);
  33. }
  34. }
  35. }
  36.  
  37. プライベートvoidマージ(Comparable[] src、Comparable[] dest、 int lo、 int mid、 int hi) {
  38. int i = lo、j = mid + 1;
  39. ( int k = lo; k <= hi; k++) {
  40. もし(i>中間){
  41. dest[k] = src[j++];
  42. }そうでなければ (j > hi) {
  43. dest[k] = src[i++];
  44. }そうでない場合 (less(src[i], src[j])) {
  45. dest[k] = src[i++];
  46. }それ以外{
  47. dest[k] = src[j++];
  48. }
  49. }
  50. }
  51.  
  52. }

再帰操作の各層はサブ配列をソートしますが、サブ配列はaux[lo..hi]またはa[lo..hi]である可能性があります。doSortの最初の呼び出しではsrc = auxとdest = arrayが渡されるため、再帰の最終結果は配列に入力され、配列全体のソートが完了していることを確認する必要があります。

ボトムアップマージソート

マージ アルゴリズムを実装する別の方法は、最初に小さな配列をマージし、次に配列全体が順序付けられるまでサブ配列をペアでマージすることです。

  1. パブリッククラス MergeSort は SortTemplate を実装します {
  2. プライベートComparable[] aux;
  3.  
  4. @オーバーライド
  5. パブリックvoid ソート(比較可能な[] 配列) {
  6. int長さ = 配列.長さ;
  7. aux = 新しいComparable[長さ];
  8. ( int sz = 1 ; sz < 長さ; sz += sz) {
  9. ( int i = 0; i < 長さ - sz; i += 2 * sz) {
  10. merge(配列、i、i + sz - 1、 Math.min (i + 2 * sz - 1、長さ - 1));
  11. }
  12. }
  13. }
  14.  
  15. プライベートvoidマージ(比較可能[] a、 int lo、 int mid、 int hi) {
  16. ( int i = lo; i <= hi; i++) {
  17. 補助[i] = a[i];
  18. }
  19. int i = lo、j = mid + 1;
  20. ( int k = lo; k <= hi; k++) {
  21. もし(i>中間){
  22. a[k] = aux[j++];
  23. }そうでなければ (j > hi) {
  24. a[k] = aux[i++];
  25. } そうない場合 (aux[i], aux[j]) {
  26. a[k] = aux[i++];
  27. }それ以外{
  28. a[k] = aux[j++];
  29. }
  30. }
  31. }
  32.  
  33. }

<<:  ヒントンは独自に44ページの論文を発表した。「アイデアを出して、自分で試してみて」

>>:  ビッグデータと人工知能 - 機械的思考から統計的思考へ

ブログ    
ブログ    

推薦する

張北院士:生成型人工知能の3つの大きな機能と1つの大きな欠点

網易科技は1月16日、知普AI技術公開デーで中国科学院院士で清華大学教授の張北氏が「大規模言語モデル...

このロボットはバッテリーなしで「自走」でき、バッテリー寿命は無制限です | ワシントン大学

電池なしで自動運転できる「車」が登場した。走行し続けるためのエネルギーを自動的に収集することもできる...

GenAI の成功への道における 10 の「落とし穴」

生成型人工知能 (GenAI) を実装したいですか? 朗報です! ほとんどの IT 意思決定者は、こ...

Langogo 2019 東京カンファレンス: 4 つの新製品が衝撃的なデビューを飾り、メディア界で話題に

(2019年11月21日、東京)Langogoは現地時間午前11時に神田明神文化交流センターで201...

【機械学習を図解で解説】誰でもわかるアルゴリズムの原理

アルゴリズムの式はかなり面倒で、機械学習は苦痛すぎる。機械学習を初めて学ぶ人は、複雑な数式やわかりに...

顔認識、今やアニメキャラクターも例外ではない

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

...

実践的な Golang の基本データ構造とアルゴリズム、k-means クラスタリング アルゴリズム

起源最近読んだ本『はじめてのアルゴリズム』(石田康樹、宮崎修一)この一連のノートは、Golangの実...

人工知能に関する12の有名な引用

[[321443]]アラン・チューリング(1912-1954)は、人工知能の概念を真剣に受け止めた最...

データマイニングの専門家がプログラムアルゴリズムを使って人生の選択をする

[[118153]]毎年、就職活動の時期になると、どうやって内定を選んだらいいのか、テンセントに行く...

クンペンが離陸、ソフトコムが道路を建設、ソフトコム・ウィズダムがファーウェイと手を組み、済南を科学技術革新の高原に築く

10月21日、「泉城の知能、万里の昇り」をテーマにした2020年中国人工知能産業サミットと昇りコンピ...

マイクロソフトは言語モデルをより調和のとれたものにするために複数のツールとデータセットをオープンソース化

Microsoft は最近、AI 駆動型コンテンツ モデレーション システムを監査し、AI モデルの...

...

フロントエンドの面接でよく聞かれるアルゴリズムに関する質問

ただし、フロントエンドでアルゴリズムに触れる機会はほとんどありません。ほとんどがインタラクティブな操...