排序思路:
分治:将长度为len的数组array分为[0, len/2],[len/2+1, len-1],直到无法继续划分为止。
合并:将子数组逐级合并,合并过程中进行排序——申请与len相当大小的空间tmp[],比较当前要合并的2个数组的元素,从小到大,排入到tmp。排序好的tmp复写array对应的索引位置。
举例:
{22,35,16,9,5,20}
1)分治
{22,35,16} {9,5,20}
{22,35} {16} {9,5} {20}
2)排序
{22,35} {16} {5,9} {20}
3)合并
{16,22,35} {5,9,20}
4)合并
{5,9,16,20,22,35}
总结:分治后的数组从最底层开始排序,每排好一层,上移一层继续排序。降低了上层排序的比较次数,归并排序是稳定的排序算法。
{22,35,16,9,5,20} |
{22,35,16} {9,5,20} | -->>逐层拆分过程
{22,35} {16} {9,5} {20} |
{22,35} {16} {5,9} {20} |
{16,22,35} {5,9,20} | -->>逐层排序过程
{5,9,16,20,22,35} |
c实现
/* * 合并子数组并进行排序 */
void merge(int array[], int tmp[], int start, int mid, int end) {
int i = start;
int j = mid + 1;
int k = start;
while (i <= mid && j <= end) {
if (array[i] > array[j])
tmp[k++] = array[j++];
if (array[i] < array[j])
tmp[k++] = array[i++];
}
while(i<mid+1)
tmp[k++]=array[i++];
while(j<end+1)
tmp[k++]=array[j++];
//元素在tmp排好后,复写其在array中对应的位置
for(k=start; k<=end; k++)
array[k]=tmp[k];
}
/* * 拆分数组到最细,然后逐级合并 */
void mergeSort(int array[], int tmp[], int start, int end){
if(start>=end)
return;
int mid = (start + end) / 2;
mergeSort(array, tmp, start, mid);
mergeSort(array, tmp, mid+1, end);
merge(array, tmp, start, mid, end);
}
时间复杂度为O(nlogn)