归并排序算法
算法思路:采用递归的方式将一串数组逐级划分,直至不可分割时,此时顺序唯一,将元素放回排序序列中。设置递归函数(Merge_Sort)那么递归中需要进行如下操作:
(1) 划分数组,设定划分区间
这里我们向下取整(左序列短于右序列,另一种方式当然也是可以的)
设数组起点为p,终点为r,则:
令:q=(r+p-1)/2;
(2) 分别处理左右区间
Merge_Sort(array[], p, q);
Merge_Sort(array[], q + 1, r);
(3) 合并左右两个区间
Merge(array[], p, q, r);
这里用到了一个归并操作的函数,我们来简单分析一下这个函数中需要处理的任务。首先:这个函数需要实现的功能为合并两个排好顺序的数组,这里简单说明一下为什么是已经排好顺序的两个数组,我们设想最简单的情况,利用Merge_Sort()函数进行逐级递归,当递归到左右区间都只剩一个的情况下,此时再对左右区间进行递归不再处理任何内容,此时回到上层递归中,这时候函数就第一次行进到Merge()函数,此时需要对这两个都只有一个数当然是算是已经排好序的数组进行排序,那么就得到了包含这两个数的一个次小有序数组。按这种逻辑可推知每次执行Merge()时,左右两个数组都是有序数组。那么我们在Merge()内的任务就是归并两个有序数组,并且令归并后的数组有序。
下面用一张图来说明:
假设我们要排列这样一个数组[1,3,7,9,2,4,6,8];
从上图中分析我们可以知道,在函数中我们需要进行如下处理:
(1) 划分数组,元素个数分别为:
n1 = q - p + 1;
n2 = r - q;
分别申请两个动态数组L,R需比其中元素个数多1用于存放一个极大值。
(2)分别进行赋值:
from i = 0 to n1 - 1
L[i] = array[p + i];
From j = 0 to n2 - 1
R[j] = array[q + j + 1];
L(n1) = inf; R(n2) = inf;
i = 0; j = 0;
(3)归并操作
from k = p to r
ifL(i) < R(j);
array[k]=L[i];
i++;
else
array[k] = R[j];
j++;
代码实现(C语言):
#include<stdio.h>
#include<stdlib.h>
#define INF 65535
void Merge(intarray[],int p,int q,int r)
{
int n1 = q - p + 1;
int n2 = r - q;
int i, j, k;
int *L = malloc(sizeof(int) * (n1 + 1));
int *R = malloc(sizeof(int) * (n2 + 1));
for(i=0; i<n1; i++)
L[i] = array[p + i];
for(j=0; j<n2; j++)
R[j] = array[q + j + 1];
L[n1] = INF;
R[n2] = INF;
i = 0; j = 0;
for (k=p; k<=r; k++) {
if (L[i] < R[j]) {
array[k] = L[i];
i++;
} else {
array[k] = R[j];
j++;
}
}
free(L);
free(R);
}
voidMerge_Sort(int array[],int p,int r)
{
int q;
if (p < r) {
q = (r + p - 1) / 2;
Merge_Sort(array, p, q);
Merge_Sort(array, q+1, r);
Merge(array, p, q, r);
}
}
int main()
{
int i;
int array[10]={1, 3, 7, 5, 4, 2, 6, 9, 5, 8};
printf("Merge Sort Example\n");
printf("Before sort:\n");
for (i=0; i<10; i++)
printf("%d ", array[i]);
printf("\n");
Merge_Sort(array, 0, 9);
printf("After sort:\n");
for(i=0; i<10; i++)
printf("%d ", array[i]);
printf("\n");
return 0;
}