归并排序还是有点云里雾里(尤其是递归的时候的状态树与函数调用时的栈的状态不太清楚,需要写代码加断点做测试),先记录下来,后面有时间再弄,先查到一个用断点测试后,描述归并排序时递归状态树的博客:https://blog.csdn.net/Cinderella_hou/article/details/51763681,其实如果按照《极客大学》算法训练营的覃超老师讲的分治的模板,应该比较好写出来:
分治的模板:
int divide_conquer(Problem *problem, int params) {
if (problem == nullptr) {
process_result;
return return_result;
}
//divide
subproblem = split_problem(problem, data);
subresult1 = divide_conquer(subproblems[0], p1);
subresult2 = divide_conquer(subproblems[1], p1);
subresult3 = divide_conquer(subproblems[2], p1);
..............................................
//merge
result = merge(subresult1, subresult2, subresult3,...);
return 0;
}
下面是归并排序的递归写法:
template<typename T>
void merge_sort_recursive(T arr[], T reg[], int start, int end) {
if (start >= end) {
return;
}
// divide
int len = strat - end, mid = (len >> 1) + start;
int start1 = start, end1 = mid;
int start2 = mid + 1, end2 = end;
merge_sort(arr, reg, start1, end1); // subproblem1
merge_sort(arr, reg, start2, end2); // subproblem2
// merge
int k = start;
while (start1 <= end1 && start2 <= end2) {
reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
}
// 将剩余部分直接复制到reg末尾,因为上面这个while已经将子部分合并好了,剩余不满足条件的必定有一个是先到达了边界,另一个剩余部分一定是有序的
while (start1 <= end1) {
reg[k++] = arr[start1++];
}
while (start2 <= end1) {
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[len];
merge_sort_rescursive(arr, reg, 0, len-1);
}