赞
踩
其他排序
基数排序
堆排序
插入排序和希尔排序
快速排序
冒泡排序和选择排序
前备知识:如果数组中只有一个数,那么这个数组一定是有序的!
核心思想
:将两个有序的数组合并为一个有序的数组(运用了分组的思想:递归)
实现过程
:对于如下数组进行归并排序,过程如下:
如上所示,由于归并排序是将两个
有序
的数组合并为一个有序的数组,因此我们首先是对上述数组进行拆分,数组长度为nLen = 9
,因此将数组均分为nLen/2 = 4
,拆分后如下图所示:
如上图所示,经过一次折半将数组拆分为了两个数组,由于归并排序的思想是将两个有序的数组进行合并,因此我们需要继续对数组进行拆分,拆分后如下图所示:
如上图所示,数组基于上次两个数组拆分为了4个数组,下面四个数组中有的有两个元素,有的有三个元素,而且有些数组我们看起来他们已经是有序的,但是计算机并不知道他们是否有序,只有遍历一遍才会知道,但是遍历数组显然不是我们排序的目的,因此我们需要进一步拆分,最终将数组拆分后的图如下:
我们知道,当数组只有一个元素时,一定是有序的,而归并排序就是将两个有序的数组合并成一个有序的数组。因此,我们将拆分后的数组进行合并,如下图所示:
如上所示,我们将最后一层的数进行了合并,之后再对上一层合并,依次进行,如下图所示:
继续回溯上一层合并
继续回溯上一层合并…
如上图所示,当返回第一层的时候,数组已经排好序。我们从归并的过程可以看出,归并的过程就是一个递归的过程,先递归将数组拆分,拆分到最小后将数组合并,合并后回溯。
代码实现
#include <stdio.h> #include <stdlib.h> void Print(int arr[],int nLen) { if(arr == NULL || nLen <= 0) return; for(int i = 0;i < nLen;i++) { printf("%d\t",arr[i]); } printf("\n"); } void Merge(int arr[],int nBegin1,int nEnd1,int nBegin2,int nEnd2) { if(arr == NULL || nBegin1 > nEnd1 || nBegin2 > nEnd2) return; int nLen = nEnd2 - nBegin1 + 1; int *parr = (int *)malloc(sizeof(int)*nLen); int nIndex = nBegin1; int i = 0; //合并 while(nBegin1 <= nEnd1 && nBegin2 <= nEnd2) { if(arr[nBegin1] <= arr[nBegin2]) { parr[i++] = arr[nBegin1++]; } else { parr[i++] = arr[nBegin2++]; } } while(nBegin1 <= nEnd1) { parr[i++] = arr[nBegin1++]; } while(nBegin2 <= nEnd2) { parr[i++] = arr[nBegin2++]; } for(i = 0;i < nLen;i++) { arr[nIndex++] = parr[i]; } free(parr); parr = NULL; } void MergeSort(int arr[],int nBegin,int nEnd) { if(arr == NULL || nBegin >= nEnd) return ; int nMid = nBegin + (nEnd - nBegin)/2;//折半 //左 MergeSort(arr,nBegin,nMid); //右 MergeSort(arr,nMid+1,nEnd); //合并 Merge(arr,nBegin,nMid,nMid+1,nEnd); } int main() { int arr[] = {3,67,287,9,3,9,23,56,7}; MergeSort(arr,0,sizeof(arr)/sizeof(arr[0])-1); Print(arr,sizeof(arr)/sizeof(*arr)); return 0 ; }
最好时间复杂度
:O(nlogn)
最坏时间复杂度
:O(nlogn)
平均时间复杂度
:O( nlogn)
空间复杂度
:O(n)
稳定性
:稳定
适用场合
:数组量大且较无序
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。