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

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

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

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

ブログ    
ブログ    
ブログ    
ブログ    
ブログ    
ブログ    

推薦する

人工知能の急速な発展により、私たちは職を失うことになるのでしょうか?

音声制御システムから今日のいくつかの無人技術まで、人工知能は徐々に成熟しています。ビッグデータセンタ...

このCVデータセットジェネレーターは人気があり、DeepMindなどが作成した13種類のCVタスクをサポートしています。

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

写真の中のキャラクターを動かしたり歌わせたりできます!このAIブラックテクノロジーは台無しになった

最近、動画サイトをよく見ている人は、とても不思議でワクワクするものを見たことがあるかもしれません。具...

詳細 | ビッグデータアルゴリズムアプリケーションのテストの開発

[[324462]]アリ姉の紹介:近年、データコンピューティング能力と機械知能アルゴリズムの台頭によ...

...

...

...

最大の効率: AIがソースコードを読み取って教えてくれる

みなさんこんにちは、カソンです。テクノロジー系のブログをよく読む友人なら、 Webpilot [1]...

遅い二次アルゴリズムと高速なハッシュマップについての簡単な説明

みなさん、こんにちは!昨日、プログラミング面接の準備をしていて、アルゴリズムの基礎を学ぼうとしている...

ロボットが書いた記事には著作権がありますか?国内初の人工知能論文著作権訴訟を例に挙げる

著作権法実施条例第2条によると、「著作権法でいう著作物とは、文学、芸術、科学の分野における知的成果で...

LLaMA2コンテキストを10万に拡張し、MITと香港中文大学はLongLoRAメソッドを開発

一般的に、大規模なモデルを事前トレーニングする場合、テキストの長さは固定されます。より長いテキストを...

...

新キングクロード3実戦テスト!すべての能力が素晴らしく、麻雀もプレイできます。確かに GPT-4 よりも優れています。

OpenAI の無敵という神話は崩れ去った。 Claude 3 (中国語対応)が一夜にして発売され...

ビッグデータと機械学習を駆使して12星座の素顔を明らかにする!

[[201919]] 「なぜ論文が出版されないのでしょうか?私は研究に向いていないのでしょうか?」...