归并排序
动图演示:
如果两个数组原本有序,两个数组的数放在一起形成新数组,新数组的排序还需要像一般排序方式那么排吗??
void Print(int*a,int n)
{
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\n");
}
void MergeArray(int len1,int len2,int*arr1,int* arr2,int* c)
{
int index1 = 0, index2 = 0;
int index3 = 0;
while (index1 < len1&&index2 < len2)
{ //取两数组中小的那个来排在数组c里
if(arr1[index1] <= arr2[index2])
c[index3++] = arr1[index1++];
else
c[index3++] = arr2[index2++];
}
while (index1 < len1)//arr1未排完,arr2排完了
//确保arr1排完,
c[index3++] = arr1[index1++];
while (index2 < len2)//arr2未排完,arr1排完了
//确保arr2排完
c[index3++] = arr2[index2++];
}
void TestMergeArray()
{
int arr1[] = { 1, 3, 4, 5, 6, 9 };
int arr2[] = { 3, 6, 8, 10, 105 };
int len1 = sizeof(arr1) / sizeof(int);
int len2 = sizeof(arr2) / sizeof(int);
int*c = (int*)malloc((len1 + len2)*sizeof(int));
MergeArray(len1,len2,arr1, arr2,c);
Print(c,len1+len2);
}
int main()
{
TestSort();
system("pause");
return 0;
}
那我们是不是可以把一个数组分成两个数组去各自排序,再通过上述方式进行合并形成一个有序的新数组,这种排序方式就称之为归并排序。
那被分的两个数组怎么有序呢??
继续分呐??
这就好比分级管理制度,国家——省——市——县——镇——村。
村还需要再分吗??村民自律形成村委会,不再需要级别管辖。
而一个数组被不断二分,新成的数组里边只有一个数,一个数当然是有序的,然后向回再合并,形成有序数组。
下面介绍的归并都是从中间把数组分成两个数组的。
void MergeArray(int*arr, int*tmp, int left,int right)
{
if (left >= right)
return;
else
{
int index = 0;
int mid = (left + right) / 2;
MergeArray(arr, tmp, left, mid);
MergeArray(arr, tmp, mid + 1, right);//分治
//归并
int index1 = left, index2 = mid+1;
while (index1 <= left && index2 <= right)
{
if (arr[index1] < arr[index2])
tmp[index++] = arr[index1++];
else
tmp[index++] = arr[index2++];
}
while (index1 <= mid)
tmp[index++] = arr[index1++];
while (index2 <= right)
tmp[index++] = arr[index2++];
for (int i = 0; i < index; ++i)
arr[left+i] = tmp[i];
}
}
void MergeSort(int*arr,int n)
{
int*tmp = (int*)malloc(n*sizeof(int));
MergeArray(arr, tmp, 0, n - 1);
free(tmp);
}
建议你敲代码时候一定养成良好习惯,看到没,博主上面有两个函数是同名的,刚开始举得那个例子和后面归并排序数组归并。两个函数参数不同,C语言不支持函数重载,造成函数调错。
我们看到,归并排序的时间复杂度O(n*logn),空间复杂度O(n)。稳定排序。
排序总结
博主的四篇有关排序的博客内容都是比较排序。
非比较排序有:计数排序、基数排序。
计数排序
假设排序数组的范围在100——200之间,定义一个计数数组长度为101。
出现100——200这101个数的某一个时候,就在计数数组对应位置+1.。
最后根据计数数组来取数排序。
计数排序是一个非基于比较的排序算法,它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(n*log(n)), 如归并排序,堆排序)
桶排序/基数排序:
首先根据数据的个位把数据放入0——9不同的桶中,然后由桶顶到底依次取出数据,再进行一次分配,这次根据十位来分配到0——9的桶中。
有关其它排序:
排序一——直接插入排序and希尔排序
https://blog.csdn.net/vickers_xiaowei/article/details/80613544
排序二——冒泡排序、快速排序三种递归实现and快排非递归
https://blog.csdn.net/vickers_xiaowei/article/details/80646873
排序三——选择排序and堆排序
https://blog.csdn.net/vickers_xiaowei/article/details/80646990
排序四——归并排序和排序总结:
https://blog.csdn.net/vickers_xiaowei/article/details/80646992