集計ソートの実装コードと構想

2683 ワード

まず、2つの整列数列をマージする方法を考えます.これは非常に簡単で、2つの数列の最初の数を比較するだけで、小さい人は先に誰を取って、取った後に対応する数列の中でこの数を削除します.次に比較を行い、数列が空の場合は、そのまま別の数列のデータを順番に取り出せばよい.
 
  
View Code
 // a[] b[] c[]
 void MemeryArray(int a[], int n, int b[], int m, int c[])
 {
     int i, j, k;

     i = j = k = 0;
     while (i < n && j < m)
     {
         if (a[i] < b[j])
             c[k++] = a[i++];
         else
             c[k++] = b[j++];
     }

     while (i < n)
         c[k++] = a[i++];

     while (j < m)
         c[k++] = b[j++];
 }

結合秩序数列の効率は比較的高く,O(n)に達できることが分かった.
上の連結秩序数列問題を解決し,集計並べ替えを見ると,配列を2組のA,Bに分けることが基本構想であり,この2組のグループ内のデータがすべて秩序化されていれば,この2組のデータを容易に並べ替えることができる.この2つのグループ内のデータを秩序化するにはどうすればいいですか?
A、Bグループをそれぞれ2つのグループに分けることができます.順次類推すると,分割されたグループにデータが1つしかない場合,このグループ内は秩序に達していると考えられ,隣接する2つのグループを統合すればよい.これにより,再帰的に数列を分解し,数列をマージすることで集計ソートが完了する.
 
  
View Code
 // a[first...mid] a[mid...last] 。
 void mergearray(int a[], int first, int mid, int last, int temp[])
 {
     int i = first, j = mid + 1;
     int m = mid,   n = last;
     int k = 0;

     while (i <= m && j <= n)
     {
         if (a[i] <= a[j])
             temp[k++] = a[i++];
         else
             temp[k++] = a[j++];
     }

     while (i <= m)
         temp[k++] = a[i++];

     while (j <= n)
         temp[k++] = a[j++];

     for (i = 0; i < k; i++)
         a[first + i] = temp[i];
 }
 void mergesort(int a[], int first, int last, int temp[])
 {
     if (first < last)
     {
         int mid = (first + last) / 2;
         mergesort(a, first, mid, temp);    //
         mergesort(a, mid + 1, last, temp); //
         mergearray(a, first, mid, last, temp); //
     }
 }

 bool MergeSort(int a[], int n)
 {
     int *p = new int[n];
     if (p == NULL)
         return false;
     mergesort(a, 0, n - 1, p);
     delete[] p;
     return true;
 }

集計ソートの効率は比較的に高く、数列長をNとし、数列を小数列に分けるにはlognステップが必要であり、各ステップは秩序数列をマージするプロセスであり、時間の複雑さはO(N)と記すことができるので、合計O(N*logn)となる.集計ソートは毎回隣接するデータで動作するため、集計ソートO(N*logn)のいくつかのソート方法(高速ソート、集計ソート、ヒルソート、スタックソート)も効率的である