归并排序采用的是一种分而治之的策略。首先将待排序数组划分为若干有序数组,然后再两两合并为有序的数组,到最后合并为一个有序数组。
归并排序主要看怎么把待排序数组划分为有序数组和怎么将两个有序的数组合并为一个有序数组。
划分好说,我们可以一分为二 的划分数组,直到划分的子数组只有一个元素为止,只有一个元素时,它自然是有序的。
划分和归并我们可以用下面的图简单演示一下:
关于归并我们演示一下{5,9}和{0,1,2}的合并过程:
假设a【2】={5,9},b【3】={0,1,2},还要一个临时数组存放合并后的数组,假设为c【5】
(1):比较a【0】=5 >b【0】=0;所以c【0】=b【0】=0;
(2):比较a【0】=5>b【1】=1;所以c【1】=b【1】=1;
(3):比较a【0】=5>b【2】=2;所以c【2】 =b【2】=2;
(4):此时b【】中的数组元素已经全部拷贝到临时数组c【】中,
(5):但是,a【】中还有数组元素,此时,将a【】中的元素全部拷贝到c【】就可以了
(6):合并结束
下面是一段测试代码:
1 #include<stdio.h>
2 #include<stdlib.h>
3 void merge(int A[],int begin,int mid,int end);//合并函数
4 void mergesort(int A[],int begin,int end);//归并排序函数
5 void PRINT(int A[],int n);//数组大于函数
6
7 int main()
8 {
9 int a[5] = {9,3,2,0,1};
10
11 PRINT(a,5);
12 mergesort(a,0,5);
13 PRINT(a,5);
14
15 return 0;
16 }
17
18 void PRINT(int A[],int n)//数组大于函数
19 {
20 int i;
21 for(i=0;i<n;i++)
22 {
23 printf("%d--",A[i]);
24
25 }
26
27 printf("\n");
28 }
29
30 void merge(int A[],int begin,int mid,int end)//合并函数实现
31 {
32 int i = begin;//数组左端有序起始
33 int j= mid+1;//数组右端有序起始
34 int k = begin;//临时数组下标起始
35
36 int *T = (int *)malloc((end - begin+1)*sizeof(int)); //申请临时数组空间
37 while(i<=mid && j<=end)//只要左半部分和右半部分还有元素就循环
38 {
39 if(A[i]<A[j])//如果左端元素小于右端元素
40 T[k++] = A[i++];//把左端元素放入临时数组
41 if(A[i]>A[j])//如果左端元素大于右端元素
42 T[k++] = A[j++];//右端元素放入临时数组
43
44 }
45
46 while(i<=mid)//如果左端还有元素
47 T[k++] = A[i++];//拷贝到临时数组
48 while(j<= end)//如果右端还有元素
49 T[k++] = A[j++];//拷贝到临时数组
50
51 for(i=begin,k=begin;k<end-begin+1;i++,k++)
52 {
53 A[i]=T[k];//把临时数组元素拷贝回原数组
54 }
55
56 free(T);//释放申请的临时空间
57 }
58
59
60 void mergesort(int A[],int begin,int end)
61 {
62
63 if(begin < end)//只要数组中元素超过一个
64 {
65 int mid = (begin+end)/2;//从中间开始划分
66 mergesort(A,begin,mid);//左端有序
67 mergesort(A,mid+1,end);//右端有序
68
69 merge(A,begin,mid,end);//归并
70 }
71 }