算法思想
- 如果要排序一個數組,我們先把數組從中間分成前後兩部分,然後對前後兩部分分別排序,再將排好序的兩部分合併在一起,這樣整個數組就都有序了。
代碼實現
/**
* 將數組按中間位置分割成2個數組,直到分出來的數組中只有2個或者1個元素
* @param startIdx
* @param endIdx
*/
public void demerge(int[] list, int startIdx, int endIdx) {
// 2個idx相差1或者0,相差1是2個元素,相差0是1個元素
if(endIdx - startIdx <= 1) {
if(endIdx - startIdx == 1) {
if (sortType == SortType.Positive.type() ? list[startIdx] > list[endIdx] : list[startIdx] < list[endIdx]) {
// 排序(其實就是交換)
int tmp = list[startIdx];
list[startIdx] = list[endIdx];
list[endIdx] = tmp;
}
}
return;
}
else {
// 取中間點進行分組
int n = (startIdx + endIdx) / 2;
int leftStartIdx = startIdx;
int leftEndIdx = n;
int rightStartIdx = n + 1;
int rightEndIdx = endIdx;
demerge(list, leftStartIdx, leftEndIdx);
demerge(list, rightStartIdx, rightEndIdx);
merge(list, leftStartIdx, leftEndIdx, rightEndIdx);
}
}
public void merge(int[] list, int startIdxA, int seperatorIdx, int endIdxB) {
// 左邊區間是從startIdxA到seperatorIdx - 1,右邊區間是從seperatorIdx到endIdxB
int[] tmp = new int[endIdxB - startIdxA + 1];
int i = startIdxA;
int j = seperatorIdx + 1;
for(int n = 0 ; n < tmp.length ; n++) {
// 如果左邊區間遍歷完了,直接把右邊區間全部寫入到數組的後面
if(i > seperatorIdx) {
tmp[n] = list[j];
j++;
}
// 如果右邊區間全部遍歷完了,把左邊區間寫到數組的尾部
else if(j > endIdxB)
{
tmp[n] = list[i];
i++;
}
else {
if(sortType == SortType.Positive.type() ? list[i] <= list[j] : list[i] >= list[j]) {
tmp[n] = list[i];
i++;
}
else {
tmp[n] = list[j];
j++;
}
}
}
// 寫回到原數組
for(int n = 0 ; n < tmp.length ; n++) {
list[startIdxA] = tmp[n];
startIdxA++;
}
}
完整代碼歸併排序