算法思想
- 如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。
代码实现
/**
* 将数组按中间位置分割成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++;
}
}
完整代码归并排序