Javaでのソートのマージ
1. 前書き
このチュートリアルでは、the Merge Sort algorithm and its implementation in Javaについて説明します。
マージソートは最も効率的なソート手法の1つであり、「分割統治」パラダイムに基づいています。
2. アルゴリズム
Merge sort is a “divide and conquer” algorithm wherein we first divide the problem into subproblems.サブ問題の解決策の準備ができたら、それらを組み合わせて問題の最終的な解決策を取得します。
これは、主な問題ではなく副問題に対処するため、再帰を使用して簡単に実装できるアルゴリズムの1つです。
このアルゴリズムは、次の2段階のプロセスとして説明できます。
-
Divide: In this step, we divide the input array into 2 halves、ピボットは配列の中点です。 このステップは、分割する半分の配列がなくなるまで、すべての半分の配列に対して再帰的に実行されます。
-
下から上にConquer: In this step, we sort and merge the divided arraysし、ソートされた配列を取得します。
次の図は、サンプル配列\ {10、6、8、5、7、3、3、4}の完全なマージソートプロセスを示しています。
ダイアグラムを詳しく見ると、サイズが1になるまで、配列が再帰的に2つの半分に分割されていることがわかります。 サイズが1になると、マージプロセスが実行され、ソート中に配列のマージが開始されます。
3. 実装
実装の場合、パラメーターとしてwe’ll write a mergeSort function which takes in the input array and its length。 これは再帰関数になるため、ベース条件と再帰条件が必要です。
基本条件は、配列の長さが1であるかどうかをチェックし、そのまま戻ります。 残りのケースでは、再帰呼び出しが実行されます。
For the recursive case, we get the middle index and create two temporary arrays l[] and r[]。 次に、mergeSort関数が両方のサブ配列に対して再帰的に呼び出されます。
public static void mergeSort(int[] a, int n) {
if (n < 2) {
return;
}
int mid = n / 2;
int[] l = new int[mid];
int[] r = new int[n - mid];
for (int i = 0; i < mid; i++) {
l[i] = a[i];
}
for (int i = mid; i < n; i++) {
r[i - mid] = a[i];
}
mergeSort(l, mid);
mergeSort(r, n - mid);
merge(a, l, r, mid, n - mid);
}
We then call the merge function which takes in the input and both the sub-arrays and the starting and end indices of both the sub arrays。
merge関数は、両方のサブ配列の要素を1つずつ比較し、小さい方の要素を入力配列に配置します。
サブ配列の1つの終わりに達すると、他の配列の残りの要素が入力配列にコピーされ、最終的なソート済み配列が得られます。
public static void merge(
int[] a, int[] l, int[] r, int left, int right) {
int i = 0, j = 0, k = 0;
while (i < left && j < right) {
if (l[i] <= r[j]) {
a[k++] = l[i++];
}
else {
a[k++] = r[j++];
}
}
while (i < left) {
a[k++] = l[i++];
}
while (j < right) {
a[k++] = r[j++];
}
}
プログラムの単体テスト:
@Test
public void positiveTest() {
int[] actual = { 5, 1, 6, 2, 3, 4 };
int[] expected = { 1, 2, 3, 4, 5, 6 };
MergeSort.mergeSort(actual, actual.length);
assertArrayEquals(expected, actual);
}
4. 複雑
マージソートは再帰的なアルゴリズムであるため、時間の複雑さは次の再帰的な関係として表現できます。
T(n) = 2T(n/2) + O(n)
2T(n/2)はサブ配列のソートに必要な時間に対応し、O(n)は配列全体をマージするのに必要な時間に対応します。
解決すると、the time complexity will come to O(nLogn).
これは、最悪の場合、平均的な場合、および最良の場合に当てはまります。これは、配列を常に2つに分割してからマージするためです。
再帰呼び出しごとに一時配列を作成するため、アルゴリズムのスペースの複雑さはO(n)です。
5. 結論
このクイックチュートリアルでは、マージソートアルゴリズムの動作と、それをJavaで実装する方法について説明しました。
作業コード全体がover on GitHubで利用可能です。