算法描述:建立在归并操作上的一种有效的排序算法,其是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序的动态图示如下所示:
复杂度分析:最坏时间复杂度为
主要特点:
- 稳定;
- 占用额外内存
O(N) ; - 核心在于有序子列的合并;
- 可以用递归方式实现,也可以用非递归方式实现。
C语言描述(递归算法):
#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
void Swap(ElementType *A, ElementType *B) {
ElementType temp = *A;
*A = *B;
*B = temp;
}
/* 有序子列的合并:Left、Right和RightEnd分别为左边起始位置、右边起始位置和右边终点位置 */
void Merge(ElementType Data[], ElementType Temp[], int Left, int Right, int RightEnd) {
int i;
int LeftEnd = Right - 1;
int temp = Left;
int num = RightEnd - Left + 1;
while (Left <= LeftEnd && Right <= RightEnd) { /*左右两边均有元素*/
if (Data[Left] <= Data[Right]) Temp[temp++] = Data[Left++];
else Temp[temp++] = Data[Right++];
}
while (Left <= LeftEnd) Temp[temp++] = Data[Left++]; /*直接复制左边元素*/
while (Right <= RightEnd) Temp[temp++] = Data[Right++]; /*直接复制右边元素*/
// 将Temp[]中的元素复制到Data[]中
for (i = 0; i < num; i++) Data[RightEnd] = Temp[RightEnd--];
}
/* 核心递归排序函数:分而治之 T(N)=O(NlogN) */
void MSort(ElementType Data[], ElementType Temp[], int Left, int RightEnd) {
int Center;
if (Left < RightEnd) {
Center = (Left + RightEnd) / 2;
MSort(Data, Temp, Left, Center); /*递归解决左边*/
MSort(Data, Temp, Center + 1, RightEnd); /*递归解决右边*/
Merge(Data, Temp, Left, Center + 1, RightEnd); /*合并两段有序序列*/
}
}
/* 归并排序C语言描述(递归方式) */
void Merge_Sort(ElementType Data[], int N) {
/* 在此声明额外空间的好处? */
ElementType *Temp = (ElementType*)malloc(N*sizeof(ElementType));
if (Temp != NULL) {
MSort(Data, Temp, 0, N - 1);
free(Temp);
}
else printf("空间不足");
}
int main() {
ElementType Data[] = {28, 3, 33, 23, 15, 30, 19, 10, 20, 22 };
Merge_Sort(Data, 10);
return 0;
}
C语言描述(非递归算法):
#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
void Swap(ElementType *A, ElementType *B) {
ElementType temp = *A;
*A = *B;
*B = temp;
}
/* 有序子列的合并:Left、Right和RightEnd分别为左边起始位置、右边起始位置和右边终点位置 */
void Merge(ElementType Data[], ElementType Temp[], int Left, int Right, int RightEnd) {
int i;
int LeftEnd = Right - 1;
int temp = Left;
int num = RightEnd - Left + 1;
while (Left <= LeftEnd && Right <= RightEnd) { /*左右两边均有元素*/
if (Data[Left] <= Data[Right]) Temp[temp++] = Data[Left++];
else Temp[temp++] = Data[Right++];
}
while (Left <= LeftEnd) Temp[temp++] = Data[Left++]; /*直接复制左边元素*/
while (Right <= RightEnd) Temp[temp++] = Data[Right++]; /*直接复制右边元素*/
// 将Temp[]中的元素复制到Data[]中
for (i = 0; i < num; i++) Data[RightEnd] = Temp[RightEnd--];
}
/* 两两归并相邻有序子列:length为当前有序子列的长度 */
void Merge_pass(ElementType Data[], ElementType Temp[], int N, int length) {
int i, j;
for (i = 0; i + 2 * length <= N; i += 2 * length)
Merge(Data, Temp, i, i + length, i + 2 * length - 1);
if (i + length < N) /*归并最后2个子列*/
Merge(Data, Temp, i, i + length, N - 1);
else /*最后只剩1个子列*/
for (; i < N; i++) Temp[i] = Data[i];
}
/* 归并排序C语言描述(非递归方式) */
void Merge_Sort(ElementType Data[], int N) {
int length = 1; /*初始化子序列长度*/
ElementType *Temp = (ElementType*)malloc(N*sizeof(ElementType));
if (Temp != NULL) {
while (length < N) {
Merge_pass(Data, Temp, N, length);
length *= 2;
Merge_pass(Temp, Data, N, length);
length *= 2;
}
free(Temp);
}
else printf("空间不足");
}
int main() {
ElementType Data[] = {28, 3, 33, 23, 15, 30, 19, 10, 20, 22 };
Merge_Sort(Data, 10);
return 0;
}