一、归并排序和递归
-
这篇已经使用递归实现快速排序。感觉也很爽。所以再实现一下归并排序让我更爽。
-
递归先要弄清楚第N步和N-1步的关系。然后想明白终止条件。
-
归并排序思想是什么样呢?
-
比如我要排序 {2,1,8,7,4,3,6,5} 这个数列。我可以先把数列拆分成两部分,然后让这两部分分别有序。然后我们合并两个有序的数列,组成完整的有序数列。
-
所以在这里,第N-1步就是两个数列已经各自有序了。第N步就是把这两个数列合并。 具体的N-1步如何有序,就看N-2步了,依次类推。直到数列只有一个数字,不需要合并为止。
-
终止条件就是,只有一个值的时候,不需要合并。
二、抽象
-
将一个数组进行归并排序。
int merge_sort(int *arr,int arr_len);
-
将前半部分和后半部分有序的数组合并。
int merge(int *arr,int arr_len);
三、实现
-
完整代码
#include<stdio.h> #include<string.h> int print_arr(int *arr,int arr_len) { if(arr == NULL || arr_len == 0) { return -1; } int i = 0; for(i = 0;i < arr_len;i++) { printf("%d,",arr[i]); } printf("\n"); return 0; } int compare(int *a,int *b) { if(a == NULL || b == NULL) { //要特殊处理,这里就按照相等算吧。。。理解一下 return 0; } if(*a > *b) { return 1; } else if( *a == *b) { return 0; } else { return -1; } return 0; } int merge(int *arr,int arr_len) { //这种情况不需要合并。 if(arr == NULL || arr_len <= 1) { return 0; } int tmp = 0; int mid = arr_len/2; int i = 0,j = mid; for( ;j < arr_len;j++) { for(;i < arr_len-1; i++) { if(compare(&arr[j],&arr[i]) <= 0) { //先把 j 的值存下来 tmp = arr[j]; //把i开始的内存往后移动 memcpy(&arr[i+1],&arr[i],(j-i)*sizeof(int)); //把 j 的值赋值给i. arr[i] = tmp; break; } } } return 0; } int merge_sort(int *arr,int arr_len) { if( arr == NULL || arr_len <= 1) { return 0; } // 先把数列分成两部分。 int mid = arr_len/2; //把左半边弄成有序的 merge_sort(arr,mid); //把右半边也弄成有序的 merge_sort(&arr[mid],arr_len-mid); //合并 merge(arr,arr_len); return 0; } int main() { int arr[] = {2,1,8,7,4,3,6,5,9}; //int arr[] = {1,2,7,8,3,4,5,6}; //int arr[] = {2,1}; int arr_len = sizeof(arr)/sizeof(arr[0]); merge_sort(arr,arr_len); print_arr(arr,arr_len); return 0; }
四、整理总结
- 如图
五、方法记忆
六、参考
- https://www.cnblogs.com/chengxiao/p/6194356.html