二路归并排序主要运用了“分治算法”,分治算法就是将一个大的问题划分为n个规模较小而结构相似的子问题。
这些子问题解决的方法都是类似的,解决掉这些小的问题之后,归并子问题的结果,就得到了“大”问题的解。
二路归并排序主旨是“分解”与“归并”
分解:
1.将一个数组分成两个数组,分别对两个数组进行排序。
2.循环第一步,直到划分出来的“小数组”只包含一个元素,只有一个元素的数组默认为已经排好序。
归并:
1.将两个有序的数组合并到一个大的数组中。
2.从最小的只包含一个元素的数组开始两两合并。此时,合并好的数组也是有序的。
直接看代码如下
#include <stdio.h>
#include <stdlib.h>
void Merge(int array[], int low, int middle, int high);
void MergeSort(int array[], int p, int q);
void printArray(int array[], int len);
void printAaray(int array[] ,int len){
for(int i=0; i < len; i++){
printf("%d ", array[i]);
}
printf("\n");
}
//合并过程中 low<=middle<high
void Merge(int array[], int low, int middle, int high)
{
int n1 = middle - low + 1;
int n2 = high - middle;
int *L =NULL;
int *R =NULL;
L = (int*)malloc(sizeof(int)*n1);
if (NULL == L){
printf("L 分配内存失败,程序退出。\n");
exit(1);
}
R = (int*)malloc(sizeof(int)*n2);
if (NULL == R){
printf("R 分配内存失败,程序退出。\n");
exit(2) ;
}
int i = 0;
int j = 0;
for(i; i < n1; i++)
L[i] = array[i + low];
for(j; j < n2; j++)
R[j] = array[j + middle +1];
i = j = 0;
int k = low;
while(i!=n1 && j!= n2)
{
// 谁小就把谁copy 到数组中
if(L[i] <= R[j])
array[k++] = L[i++];
else
array[k++] = R[j++];
}
//如果发现 还有没有放入到数组中的 ,直接copy 就可以了,这里 就是L后面 已经排好序了,但是R已经排完此时,j==n2
//
while(i < n1)
array[k++] = L[i++];
while(j < n2)
array[k++] = R[j++];
// 释放内存
if (L !=NULL){
free(L);
}
if(R !=NULL){
free(R);
}
}
void MergeSort(int array[], int p, int q)
{
if(p < q)
{
int mid = (p+q)/2;
MergeSort(array, p, mid);
MergeSort(array, mid+1, q);
Merge(array,p, mid, q);
}
}
int main()
{
//int array[7] = {1,3,5,2,4,5,10};
int array[] = {5,2,4,7,1,3,21,6,23,56,67,23,17,24,15,19,58,29,45};
int length = sizeof(array) /sizeof(*array);
MergeSort(array, 0, length-1);
printAaray(array,length);
return 0;
}
这里要理解 二路归并的思想,以及 递归的概念, 也就是 分治的思想,是这样子。从中间把待排 分为两部分,一部分在排序,另一部分 也在排序,最后 调用merge() ,把两个 已经排好的序列,进行归并 即可。
参考博客:
http://www.cnblogs.com/horizonice/p/4102553.html
分享快乐,留住感动。如果喜欢请点赞,或者有什么疑问,也可以留言,一起讨论。 2017年 10月 16日 星期一 16:16:19 ---biaoge