データ構造:一般的な並べ替えアルゴリズム(8):マージ並べ替え
(1)基本的な考え方:
マージ(マージ)ソート方法は、2つ(またはそれ以上)の順序付きリストを新しい順序付きリストにマージすることです。つまり、ソートするシーケンスをいくつかのサブシーケンスに分割し、各サブシーケンスを順序付けます。次に、順序付けられたサブシーケンスが全体的な順序付けられたシーケンスにマージされます。マージソートの2番目のステップでは、2つの順序付けられた配列をソートするルールは非常に単純です。同時に、2つの配列の最初の位置のサイズを比較し、小さい方を空の配列に入れてから、その位置を空の配列に入れます。ポインタが1つ後ろに移動してから、別の配列の前の位置との比較を続けます。いずれかのアレイが最初にスタックからポップアウトされるまで、他のアレイのすべての要素が新しいアレイに追加されます。
マージソートとクイックソートの効果は同じです。クイックソート:最初にアレイを2つのサブアレイに大まかにソートし、次に2つのサブアレイを再帰的かつ大まかに分割して、サブアレイに要素が1つだけになると、自然にソートされます。これは、最初に並べ替え、次に再帰的に並べ替えることとして要約できます。マージ並べ替え:何があっても、配列は2つのサブ配列に分割され、配列に要素が1つだけになるまで、配列は2つのサブ配列に再帰的に分割され、並べ替えが開始されます。 2つの配列を順番に並べ替え、再帰的な戻り値に従って2つの配列を順番に並べ替えます。最後に、配列全体を並べ替えることができます。
(2)例
例:a [15] = {3、44、38、5、47、15、36、26、27、2、46、4、19、50、48}マージソートによるソート
2.1反復法
①スペースを申請して、ソートされた2つのシーケンスの合計サイズにします。このスペースは、マージされたシーケンスを格納するために使用されます。
②2つのポインタを設定します。初期位置はそれぞれ2つのソートされたシーケンスの開始位置です。
③2つのポインタが指す要素を比較し、比較的小さい要素を選択してマージスペースに配置し、ポインタを次の位置に移動します
④ポインタがシーケンスの最後に到達するまで、手順③を繰り返します。
⑤別のシーケンスの残りの要素をすべて、マージされたシーケンスの最後に直接コピーします
2.2再帰
①シーケンス内の隣接する2つの番号ごとにマージして、floor(n / 2)シーケンスを形成します。ソート後、各シーケンスには2つの要素が含まれます。
②上記のシーケンスを再度マージしてfloor(n / 4)シーケンスを形成し、各シーケンスには4つの要素が含まれます
③すべての要素がソートされるまで手順②を繰り返します
コード例:
// 归并排序(递归法)
template<typename T>
void merge_sort_recursive(T arr[], T reg[], int start, int end) {
if (start >= end)
return;
int len = end - start, mid = (len >> 1) + start;
int start1 = start, end1 = mid;
int start2 = mid + 1, end2 = end;
merge_sort_recursive(arr, reg, start1, end1);
merge_sort_recursive(arr, reg, start2, end2);
int k = start;
while (start1 <= end1 && start2 <= end2)
reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
while (start1 <= end1)
reg[k++] = arr[start1++];
while (start2 <= end2)
reg[k++] = arr[start2++];
for (k = start; k <= end; k++)
arr[k] = reg[k];
}
// merge_sort
template<typename T>
void merge_sort(T arr[], const int len) {
T reg[15];
merge_sort_recursive(arr, reg, 0, len - 1);
}
3.要約:
時間の複雑さ:マージソートは、主に分割と並べ替え順序付き配列に分けられます。分割操作の時間の複雑さはlognであり、ソートの複雑さはnであるため、マージソートの時間の複雑さはO(nlogn)マージソートです。のスペースの複雑さは、一時的な配列と再帰中にスタックにプッシュされるデータによって占有されるスペースです:n + lognなので、スペースの複雑さはO(n)です。