0.忘差不多的基础知识
return用法
1.正文
排序问题,想试试分而治之的归并排序,这是一个涉及到递归的算法,使用时需考虑以下几点问题:
- how to devide --func merge
- how to merge while sort --func merge_sort
- what we need:
(1)index:p q mid
(2)array:numList arrayLeft arryRight
1.0 overroll
将 [p,q] 分为[p,mid] 和 [mid+1,q] 区域,Left和Right两部分分别分割成单一数组元素后再进行排序与合并。
merge_sort_L(arr, p, mid);
merge_sort_R(arr, mid + 1, q);
便于区分与理解所以加了L&R,实际两个都是merge_sort函数,以实现递归操作。
详细实现过程在1.1与1.2中叙述。
1.1 merge_sort
递归中止原则:
- numList ==NULL
- p>=q
算法难点为理解实现分、并递归代码的执行顺序,这边摘取merge_sort部分代码展示:
merge_sort(arr, p, mid);
merge_sort(arr, mid + 1, q);
//对分好的 [p,mid] 和 [mid,q] 进行归并操作
merge(arr, p, mid, q);
对照下图,进行步骤顺序的分析
Left:
S1 merge_sort_L(1,8)
S2 merge_sort_L(1,4)
S3 merge_sort_L(1,2)
S4 merge_sort_L(1,1)
p == q ,故return回到merge_sort_L(1,2)下一句
S5 merge_sort_R(2,2)
p == q ,故return回到merge_sort_R(2,2)下一句
S6 merge(1,2)
到这里结束了下图中7,5的分割、排序、归并。
剩余的步骤自行debug查看,不再赘述,下面放分而治之的流程图以供理解。
1.2 merge
needed:
- tmp数组
- L_low L_high R_low R_high
实现:
S1:compare与copy,排序结果先进tmp数组。
if(arrayL>arrayR){
tmp=arrayL
}
期间有L_low、R_low分别指向左右数组当前比较单元,故二者存在++操作,且数值应<=L_hogh\R_high。
//1.compare与copy,L R 比较完后移,排序结果先进tmp数组
for (i = 0; L_low <= L_high && R_low <= R_high; i++) {
if (numList[L_low] < numList[R_low]) {
tmp[i] = numList[L_low];
L_low++;
} else {
tmp[i] = numList[R_low];
R_low++;
}
S2:左数组剩余,直接copy。
剩余条件判断为L_low <= L_high。
将剩余元素copy进tmp数组应该从S1的最后一个下标后。
S3:右数组剩余,直接copy。
同S2
S4:copy。
应该注意递归算法,所以numList不是每次都从[0]开始copy,而是从[first]开始。
2.完整代码
#include <stdio.h>
#include <stdlib.h>
#define Nmax 100
void merge(int numList[], int first, int mid, int last) {
int i, j;
//每次需要排序的divided数组大小都不一样
//进行动态分配临时数组
int* tmp = (int*)malloc((last - first + 1) * sizeof(int));
int L_low = first;
int L_high = mid;
int R_low = mid + 1;
int R_high = last;
//1.compare与copy,L R 比较完后移,排序结果先进tmp数组
for (i = 0; L_low <= L_high && R_low <= R_high; i++) {
if (numList[L_low] < numList[R_low]) {
tmp[i] = numList[L_low];
L_low++;
} else {
tmp[i] = numList[R_low];
R_low++;
}
}
//2.L left
if (L_low <= L_high) {
for (j = L_low; j <= L_high; j++) {
tmp[i] = numList[j];
i++;
}
}
//3.R left
if (R_low <= R_high) {
for (j = R_low; j <= R_high; j++) {
tmp[i] = numList[j];
i++;
}
}
//4.copy 回numList\
//注意递归,所以first+i
for (i = 0; i < last - first + 1; i++) {
numList[first + i] = tmp[i];
}
free(tmp);//
}
void merge_sort(int numList[], int first, int last) {
int mid;
if (first < last) {
mid = (first + last) / 2;
//对Left进行递归分割
merge_sort(numList, first, mid);
//对Right进行递归分割
merge_sort(numList, mid + 1, last);
merge(numList, first, mid, last);
}
}
int main() {
int N, i;
int numList[Nmax];
//1.input
scanf("%d", &N);
for (i = 0; i < N; i++) {
scanf("%d", &numList[i]);
}
//2.func
merge_sort(numList, 0, N - 1);
//3.output
for (i = 0; i < N; i++) {
printf("%d ", numList[i]);
}
}