一、归并排序
归并排序是建立在归并上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。该算法的核心思想是二路归并。
二、归并排序的介绍
<1>归并排序的过程:
(1)根据数组的mid值(数组的起始下标加数组的末尾下标除以二)将序列划分为2个子序列,多次向下递归,直到划分为一个子序列只包含一个数据。
(2)递归的对子序列a[low~mid]和a[mid + 1~high]归并为一个有序的区间a[low~high];
(3)将已排序的两个子区间a[low~mid]和a[mid + 1~high]归并为一个有序的区间a[low~high]
<2>图解二路归并
<3>代码实现及测试
#include<stdio.h>
#include<stdlib.h>
void Merge(int arr[], int tmp[], int startindex,int mid, int endindex)//将子序列合并为一个完整的序列
{
int i = startindex;
int j = mid + 1;
int k = startindex;
while (i < mid + 1 && j < endindex + 1)
{
if (arr[i] <= arr[j])
{
tmp[k++] = arr[i++];
}
if (arr[i] > arr[j])
{
tmp[k++] = arr[j++];
}
}
while (i < mid + 1)
{
tmp[k++] = arr[i++];
}
while (j < endindex + 1)
{
tmp[k++] = arr[j++];
}
for (int i = startindex; i <= endindex; ++i)
{
arr[i] = tmp[i];//将有序的数组拷贝回原来的空间
}
}
void MergeS(int arr[], int tmp[], int startindex, int endindex)
{
if (startindex < endindex)
{
int mid = (startindex + endindex) / 2;
MergeS(arr, tmp, startindex, mid);//使用递归的方式对序列的左半部分进行划分
MergeS(arr, tmp, mid + 1, endindex);//使用递归的方式对序列的右半部分进行划分
Merge(arr, tmp, startindex, mid, endindex);
}
}
void MergeSort(int arr[], int len)
{
int *tmp = (int*)malloc(sizeof(arr[0])*len);//申请空间存放有序序列
MergeS(arr, tmp, 0, len - 1);
free(tmp);
}
int main()
{
int arr[] = { 12, 3, 21, 4, 23, 43, 25, 34, 65, 234, 12, 4124, 12 };
int len = sizeof(arr) / sizeof(arr[0]);
MergeSort(arr, len);
return 0;
}
<4> 归并的时间复杂度
在归并中我们需要将两个相邻的有序序列进行两两归并,这需要将待排序序列中的所有记录扫描一遍,因此耗费O(n)的时间,而由完全二叉树的深度可知,整个归并排序需要进行log2n次,因此总的时间复杂度为O(nlogn),而且这是归并排序算法中最好,最坏、平均的时间性能。