归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。
时间复杂度:O(n log n)
空间复杂度:O(n)
稳定性:稳定
排序过程如图所示:
从图中我们不难看出
第一次是一个数字为一组进行相邻两组比较,使其组内先有顺序(如果最后由剩余,则单独为一组)
第二次是两个数字为一组进行相邻两组比较,使其组内先有顺序(如果最后由剩余,则单独为一组)
第三次是四个数字为一组进行相邻两组比较,使其组内先有顺序(如果最后由剩余,则单独为一组)
第四次是八个数字为一组进行相邻两组比较,使其组内先有顺序(如果最后由剩余,则单独为一组)
。
。
。
我们不难看出,每一次比较时,每一组比较的数字的个数是2倍的关系
那我们如何用代码实现归并排序呢
例如 31 77 46 97 66
我们定义四个变量h1,h2,e1,e2
刚开始我们让h1,h2为组的第一个元素的下标,e1,e2为组的最后一个元素的下标
我们让下标为h1和h2的元素进行比较,将小的元素放入一个临时储存的数组里,较小元素的下标进行++操作
第一次比较
例如:h1为31下标,h2为77下标,e1为31下标,e2为77下标,进行h1和h2比较,将较小的31放入一个临时储存的数组里,h1进行++操作,这时h1大于e1,所以第一组和第二组数字已经比较完成,可以直接将h2数字继续存入临时储存的数组里,然后令h1 = e2+1;e1=h1+组的数字个数-1;h2=e1+1;e2=h2+组的数字个数-1;(这里注意不能让下标越界)继续进行如上比较
第一次比较结果为:31 77 46 97 66
第二次比较
例如:h1为31下标,h2为46下标,e1为77下标,e2为97下标,进行h1和h2比较,将较小的31放入一个临时储存的数组里,h1进行++操作,这时h1不大于e1,所以继续进行h1和h2比较,将较小的46放入一个临时储存的数组里,h2进行++操作,继续进行h1和h2比较,将较小的77放入一个临时储存的数组里,第一组和第二组数字已经比较完成,可以直接将h2数字继续存入临时储存的数组里,然后令h1 = e2+1;e1=h1+组的数字个数-1;h2=e1+1;e2=h2+组的数字个数-1;(这里注意不能让下标越界)继续进行如上比较(如果最后有单独的组那就直接存入临时储存的数组里)
第二次比较结果为:31 46 77 97 66
第三次比较
如上面操作。。。
第三次比较结果为:31 46 66 77 97
参考代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LENGTH 13 //待排序的数字个数
void Meger(int arr[],int len,int width) //归并排序的一次排序
{
int head1,head2,tail1,tail2;
tail2 = -1;
int count = 0; //brr下标
int *brr = (int *)malloc(sizeof(int)*len); //用来临时存储排序中的过程
if(brr == NULL)
{
return ;
}
while(1) //进行一次归并排序
{
head1 = tail2+1;
tail1 = head1+width-1;
if(tail1>len-1)
{
tail1 = len-1;
}
head2 = tail1+1;
tail2 = head2+width-1;
if(tail2>len-1)
{
tail2 = len-1;
}
if(head2>tail2)
{
break;
}
while( head1 <= tail1 && head2 <= tail2 )
{
if(arr[head1]>arr[head2])
{
brr[count] = arr[head2];
count++;
head2++;
}
else
{
brr[count] = arr[head1];
count++;
head1++;
}
}
while(head1<=tail1)
{
brr[count] = arr[head1];
count++;
head1++;
}
while(head2<=tail2)
{
brr[count] = arr[head2];
count++;
head2++;
}
}
while(head1<len)
{
brr[count] = arr[head1];
count++;
head1++;
}
for(int i=0;i<len;i++)
{
arr[i] = brr[i];
}
free(brr);
}
void MegerSort(int arr[],int len) //归并排序
{
for(int i=1;i<len;i*=2)
{
Meger(arr,len,i);
}
}
void ShowSort(int arr[],int len) //打印
{
for(int i=0;i<len;i++)
{
printf("%2d ",arr[i]);
}
printf("\n");
}
int main()
{
srand((unsigned int)time(NULL));
int arr[LENGTH];
for(int i=0;i<LENGTH;i++)
{
arr[i] = rand()%100; //获得随机数
}
ShowSort(arr,LENGTH);
MegerSort(arr,LENGTH); //归并排序
ShowSort(arr,LENGTH);
return 0;
}