今儿来聊一聊归并排序, 其实跟快速排序的思想很接近, 但是实现的过程又大不相同 ,在此之前,我们先了解一下 怎么把两个有序的集合 合并在一起 ,可能很多同学在面试过程中 ,会遇到的面试题 。那我们来看看 如何实现最优解:
1.重新排序法: 就是将两个集合放到一个数组里面,再进行排序。 这种方法是最笨的方法了,完全体现不了 两个集合有序的特性 。
2.从头比较法: 先取得两个集合的第一个元素,比较小的放到另外一个集合了,然后小的集合的第二个元素再进行比较,以此类推比较完毕放到另外一个集合中 。 做个图 比较直观吧:
接下来我们了解一下归并排序的思想:分而治之
将一个集合一分为二,分别让两个集合变的有序后,再按照上面的第二种方式进行合并。 分为两个子集合怎么变的有序呢 ? 如果子集合的元素超过两个,那么就继续一分为二。直到子集合小于或者等于2个元素,然后将两个元素进行比较 合并。
老规矩 、上码!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
void mergersort(int *arr, int n)
{
if (n > 2)
{
//如果子集合元素大于两个 继续分
int *left = arr;
int leftsize = n / 2;
int *right = arr + leftsize;
int rightsize = n - leftsize;
mergersort(left, leftsize);
mergersort(right, rightsize);
printf("left-->%d right==>%d %d %d \n", left[0], right[0], leftsize, rightsize);
int i, j, k, m;
i = j = k = 0;
int temp[n];
while (i < leftsize && j < rightsize)
{
if (left[i] < right[j])
{
temp[k] = left[i];
k++;
i++;
}
else
{
temp[k++] = right[j++];
}
}
while (i < leftsize)
{
temp[k++] = left[i++];
}
while (j < rightsize)
{
temp[k++] = right[j++];
}
for (m = 0; m < (leftsize + rightsize); m++)
{
left[m] = temp[m];
}
}
else if (n == 2) //两个元素比较大小
{
int *left = arr;
int *right = arr + 1;
if (left[0] > right[0])
{
left[0] = left[0] ^ right[0];
right[0] = left[0] ^ right[0];
left[0] = left[0] ^ right[0];
}
}
}
int main()
{
int arr[] = {8, 21, 563, 63, 456, 5, 70, 2, 4, 76, 54, 2, 1, 3};
int len = sizeof(arr) / sizeof(arr[0]);
printf("归并排序 -->前的数组:");
for (int i = 0; i < len; i++)
{
printf("%d,", arr[i]);
}
printf("\n");
printf("长度--->%d \n", len);
mergersort(arr, len);
printf("我是归并排序");
for (int i = 0; i < len; i++)
{
printf("%d,", arr[i]);
}
// selectsrot1();
//Insertionsort();
printf("\n");
system("pause");
return 0;
}
运行结果:
老铁们,自己细品一下 归并排序的性能, 好了,今天就聊到这了 ,喜欢的老铁,留个赞咯。