目录
1.什么是归并排序
归并排序就是将无法再二分的两个有序小序列,利用多项式相加原理,合并成一个大的有序序列的过程。举个例子:
不能继续二分的小序列 ( 8 7 6 5 4 3),实际上指的就是8,7,6,5.....这些单个的数字。
对于8 7这两个序列来说,各自都只有一个元素,利用多项式相加原理,将其视为多项式系数进行比较,较小的放在
前面,较大的放在后面于是就得到7 8这样的一个有序的较大序列。依次对剩余的两个序列运用上述方法得到5 6,
3 4这两个序列。然后(7,8),(5,6)这两个序列进行归并,得到有序序列(5,6,7,8),再和(3,4)进行归并,
得到(3,4,5,6,7,8),排序完成。
2.归并排序的关键点
归并排序整个过程有两个关键点,第一个是利用分治的思想,对待排序列进行递归二分组,直到不可分为止。第二是
利用多项式相加原理,将两个待排序列视为多项式系数,如果待排序列中有相同的元素,多项式相加过程中并不做合
并同类项,而只有根据系数大小进行排列。
分治实现:
分治的原理和二分查找的原理是类似的,所以时间复杂度为O(logN)。
/*
* param A[] : 待排序列
* param TmpA[] : 临时空间
* param L :左起点
* param RightEnd :右终点
*/
void Msort( ElementType A[], ElementType TmpA[], int L, int RightEnd )
{ /* 核心递归排序函数 */
int Center;
if ( L < RightEnd ) {
Center = (L+RightEnd) / 2;
Msort( A, TmpA, L, Center ); /* 递归解决左边 */
Msort( A, TmpA, Center+1, RightEnd ); /* 递归解决右边 */
Merge( A, TmpA, L, Center+1, RightEnd ); /* 合并两段有序序列 */
}
}
归并实现:
由于即将归并的两个子序列是有序的,通过下面这段代码可以看出,一旦出现一个子序列任何的元素都比另一个子序列
的第一个元素都小,那么这个子序列就都罗列在前面,然后另一个子序列直接追加到后面。
while( L <= LeftEnd && R <= RightEnd ) {
if ( A[L] <= A[R] )
TmpA[Tmp++] = A[L++]; /* 将左边元素复制到TmpA */
else
TmpA[Tmp++] = A[R++]; /* 将右边元素复制到TmpA */
}
while( L <= LeftEnd )
TmpA[Tmp++] = A[L++]; /* 直接复制左边剩下的 */
while( R <= RightEnd )
TmpA[Tmp++] = A[R++]; /* 直接复制右边剩下的 */
3.怎么用归并排序
#ifdef SORT_OF_MERGE_DG
/* 归并排序 - 递归实现 */
/* L = 左边起始位置, R = 右边起始位置, RightEnd = 右边终点位置*/
void Merge( ElementType A[], ElementType TmpA[], int L, int R, int RightEnd )
{ /* 将有序的A[L]~A[R-1]和A[R]~A[RightEnd]归并成一个有序序列 */
int LeftEnd, NumElements, Tmp;
int i;
LeftEnd = R - 1; /* 左边终点位置 */
Tmp = L; /* 有序序列的起始位置 */
NumElements = RightEnd - L + 1;
while( L <= LeftEnd && R <= RightEnd ) {
if ( A[L] <= A[R] )
TmpA[Tmp++] = A[L++]; /* 将左边元素复制到TmpA */
else
TmpA[Tmp++] = A[R++]; /* 将右边元素复制到TmpA */
}
while( L <= LeftEnd )
TmpA[Tmp++] = A[L++]; /* 直接复制左边剩下的 */
while( R <= RightEnd )
TmpA[Tmp++] = A[R++]; /* 直接复制右边剩下的 */
for( i = 0; i < NumElements; i++, RightEnd -- )
A[RightEnd] = TmpA[RightEnd]; /* 将有序的TmpA[]复制回A[] */
}
void Msort( ElementType A[], ElementType TmpA[], int L, int RightEnd )
{ /* 核心递归排序函数 */
int Center;
if ( L < RightEnd ) {
Center = (L+RightEnd) / 2;
Msort( A, TmpA, L, Center ); /* 递归解决左边 */
Msort( A, TmpA, Center+1, RightEnd ); /* 递归解决右边 */
Merge( A, TmpA, L, Center+1, RightEnd ); /* 合并两段有序序列 */
}
}
void MergeSort( ElementType A[], int N )
{ /* 归并排序 */
ElementType *TmpA;
TmpA = (ElementType *)malloc(N*sizeof(ElementType));
if ( TmpA != NULL ) {
Msort( A, TmpA, 0, N-1 );
free( TmpA );
}
else printf( "空间不足" );
}
#endif