赞
踩
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法。
归并过程为:比较a[i]和b[j]的大小,若a[i]≤b[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素b[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
下段代码中,将a[] 和 b[]合并到一个数组T[]
int a[5] = {1,3,5,7,9};
int b[5] = {,2,4,6,8,10};
int T[10] = {0};
for(int i =0;i<5;i++)
T[i] = a[i];
for(int i =5;i<10;i++)
T[i] = b[i];
再进行归并
#include "stdio.h"
void Merge(int A[],int TempA[],int L,int R,int RightEnd)
{
int LeftEnd = R-1; //左边终点位置
int temp = L; //存放结果排序后的数组的初始位置
int NumElements = RightEnd-L+1; //记录总数
while(L<=LeftEnd && R<= RightEnd)
{
if(A[L]<=A[R]) TempA[temp++] = A[L++];/* 将左边元素复制到TmpA */
else TempA[temp++] = A[R++];/* 将右边元素复制到TmpA */
}
while(L<=LeftEnd)
TempA[temp++] = A[L++];/* 直接复制左边剩下的 */
while(R<=RightEnd)
TempA[temp++] = A[R++]; /* 直接复制右边剩下的 */
for( i = 0; i < NumElements; i++, RightEnd -- )
A[RightEnd] = TmpA[RightEnd]; /* 将有序的TmpA[]复制回A[] */
}
int main()
{
int a[10]={1,3,5,7,9,2,4,6,8,10};
int b[10]={0};
Merge(a,b,0,5,9);
for(int i =0;i<10;i++)
printf("%d",a[i]);
return 0;
}
当然,你会有疑问,为什么给我们的两个数组,一开始就是已经排好序的?其实上面只是演示的过程。在现实的问题中,往往会给我们一个杂乱无序的数组。结合上面的例子,我们可以尝试这么做:分而治之。如下图所示:
分而治之的关键在于:
将一个无序的数组分成等分的两小段。接着呢,又可以将两小段每一段再分。。。不断重复直到每一段都无法再分的时候,也就是每一段,都只有一个元素的时候,无法再分,即下面代码中 L<RightEnd
的时候,将数组中的数通过归并排序的核心算法进行排序,并保存到TempA[]中。
注意这是递归。
void MSort(int A[],int TempA[],int L,int RightEnd)
{/* 核心递归排序函数 */
int Center;
if(L<RightEnd){
Center = (L+RightEnd)/2;
MSort(A,TempA,L,Center); /* 递归解决左边 */
MSort(A,TempA,Center+1,RightEnd);/* 递归解决右边 */
Merge(A,TempA,L,Center+1,RightEnd);/* 合并两段有序序列 */
}
}
之后,在将TempA[] 中的数据依次保存回A[]
我们把上面的代码优化一下,即可以提供统一函数的接口。
void Merge_Sort(int A[],int n)
{/* 归并排序 */
int *TempA = (int*)malloc(sizeof(int)*n);
if(TempA !=NULL){
MSort(A,TempA,0,n-1);
free(A);
}
else Error("空间不足");
}
统一代码:
#include "stdio.h"
#include "stdlib.h"
/* L = 左边起始位置, R = 右边起始位置, RightEnd = 右边终点位置*/
void Merge(int A[],int TempA[],int L,int R,int RightEnd)
{/* 将有序的A[L]~A[R-1]和A[R]~A[RightEnd]归并成一个有序序列 */
int LeftEnd = R-1; //左边终点位置
int temp = L; //存放结果排序后的数组的初始位置
int NumElements = RightEnd-L+1; //记录总数
while(L<=LeftEnd && R<= RightEnd)
{
if(A[L]<=A[R]) TempA[temp++] = A[L++];/* 将左边元素复制到TmpA */
else TempA[temp++] = A[R++];/* 将右边元素复制到TmpA */
}
while(L<=LeftEnd)
TempA[temp++] = A[L++]; /* 直接复制左边剩下的 */
while(R<=RightEnd)
TempA[temp++] = A[R++]; /* 直接复制右边剩下的 */
for( i = 0; i < NumElements; i++, RightEnd -- )
A[RightEnd] = TmpA[RightEnd]; /* 将有序的TmpA[]复制回A[] */
}
void MSort(int A[],int TempA[],int L,int RightEnd)
{/* 核心递归排序函数 */
int Center;
if(L<RightEnd){
Center = (L+RightEnd)/2;
MSort(A,TempA,L,Center); /* 递归解决左边 */
MSort(A,TempA,Center+1,RightEnd);/* 递归解决右边 */
Merge(A,TempA,L,Center+1,RightEnd);/* 合并两段有序序列 */
}
}
void Merge_Sort(int A[],int n)
{/* 归并排序 */
int *TempA = (int*)malloc(sizeof(int)*n);
if(TempA !=NULL){
MSort(A,TempA,0,n-1);
free(A);
}
else printf("空间不足\n");
}
int main()
{
int a[10]={1,3,5,7,9,2,4,6,8,10};
//int b[10]={0};
//Merge(a,b,0,5,9);
Merge_Sort(a,10);
for(int i =0;i<10;i++)
printf("%d",a[i]);
return 0;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。