将两个有序数组合并成一个有序数组
-
将数组进行分解,直到分解为单个元素时,因为最开始无法得到有序数组,而是把只有一个元素的单个数组,看成有序数组
-
依次将两两有序数组进行有序合并,直至排序完成
-
合并的步骤:先申请两数组合并后所需要的空间大小,然后将两个排序好的数组逐一进行比较,往申请的空间里
void merge(int a[], int l, int mid, int r) { int *help = new int[r - l + 1];//申请两个数组合并后所需的空间 //i代表第一个有序数组的开头,j代表第二个有序数组的开头,index代表新申请的数组的下标 int i = l, j = mid + 1,index = 0; while (i<=mid&&j<=r)//判断i,j不要越界 { if (a[i] <= a[j]) { help[index++] = a[i++]; } else { help[index++] = a[j++]; } } while (i <= mid) {//此种情况,说明第二个有序数组的元素已经全部放入help中了,所以把第一个有序数组中没放入help中的元素全部放入help中 help[index++] = a[i++]; } while (j <= r) { help[index++] = a[j++]; } //将help中的元素,再全部放入原数组中 index = l; for (int i = 0; i <= r - l; i++) { a[index++] = help[i]; } delete[] help;//释放空间 } void mergeSort(int a[], int l, int r) { if (l >= r) { return; } int mid = (l + r) / 2; mergeSort(a, l, mid);//递归 mergeSort(a, mid + 1, r); merge(a, l, mid, r); } int main() { int a[]= {1,5,3,2,4}; //sizeof(a)代表a数组字节,sizeof(a[0])代表a中一个元素的字节,所以二者相除就是数组a的元素个数 mergeSort(a, 0, sizeof(a) / sizeof(a[0]) - 1); for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) { cout << a[i] << " "; } cout << endl;//此种方法实现数组的空格输出,并是释放了资源 }
归并排序
分到最后剩一个元素为止,分log2n层
n为每一层比较的次数
时间复杂度nlog2n空间复杂度:O(n)因为栈区局部变量,空间用完就被释放
稳定
归并排序是一种基于分治思想的排序。
先将序列分为长度相等的两个子序列,对子序列排好序以后,再合并。
对子序列的排序,则调用递归实现。是稳定的
时间复杂度:
最优:O(nlogn)
最差:O(nlogn)
平均:O(nlogn)
归并排序的时间复杂度是稳定的,不管数据类型如何,对于n个数据,需要分成logn层,而合并每一层的数据,都需要O(n)的时间,所以时间复杂度稳定为O(nlogn)。
空间复杂度:
归并排序需要额外的空间占用,也算是他的缺点吧,空间占用为O(n)。
稳定性:
归并排序的出口只有1个元素,或者2个元素的时候,我们都可以在这里保证他们的稳定性,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。