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

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

この記事は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ページの論文を発表した。「アイデアを出して、自分で試してみて」

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

ブログ    
ブログ    

推薦する

...

効率的な多次元空間ポイントインデックスアルゴリズム - Geohash と Google S2

[[201793]]導入毎晩残業して家に帰るときは、Didiやシェア自転車を使うこともあります。ア...

AIに切り替えたい人向け:人工知能ガイドはこちら

人工知能とは何でしょうか? なぜ重要なのでしょうか? 人工知能を恐れるべきでしょうか? なぜ突然、み...

組織の AI 戦略が失敗する 7 つの理由

[[359773]] AI テクノロジーを導入している多くの組織は、成功を収めるどころか、テクノロジ...

AI は今後 10 年間で BAT のリセット ボタンとなるでしょうか?

中国の王朝には必ず一つの法則がある。一代か二代で王位は行き詰まりを迎える。漢の時代には呂后の乱、唐の...

XML暗号化アルゴリズムが解読され、W3C標準が改訂される

シカゴで開催された ACM コンピュータおよび通信セキュリティ会議で、2 人のドイツ人研究者が、ワー...

プラスチックチップを1個1セント未満で製造

あなたの周りの物体が知性に満ちていると想像してください。包帯、バナナの皮、ボトルなどはすべて知性を持...

デフォルトの心配はありません!ファーウェイとSTマイクロエレクトロニクスが共同でチップを設計

ファーウェイにとって、独自のチップを開発することは必ず進むべき道であり、さらなる発展を遂げたいのであ...

...

ディープラーニングを使用してPythonコードを自動的に補完するこのオープンソースプロジェクトは非常に素晴らしい

コード補完機能は IDE では非常に一般的です。優れたコード自動補完機能により、作業効率が大幅に向上...

エッジ AI で建物のシステム障害を回避

ビルの管理者や運営者は、暖房や冷房、照明システム、エレベーターの故障など、ビルのシステムや設備の予期...

CPP アルゴリズム問題のための共通コンテナ技術

[[413003]]アルゴリズムの問​​題を解決するときに CPP でよく使用されるコンテナ テクニ...

AI 偽指紋が登場しても指紋ロック解除は安全ですか?

スマートフォンに生体認証指紋認証ロック解除技術が搭載されて以来、パスワードを入力する面倒なロック解除...

ビッグデータ、クラウドコンピューティング、人工知能が統合され、セキュリティ分野に応用されている

過去2年間、安全都市、インテリジェント交通、スノーブライトプロジェクトの継続的な発展と深化に伴い、ビ...