归并排序
16lz
2021-03-30
归并排序
归并排序的时间复杂度任何情况下都是 O(nlogn),看起来非常优秀。(即便是快速排序,最坏情况下,时间复杂度也是 O(n2)。)
但是,归并排序并没有像快排那样,应用广泛,这是为什么呢?因为它有一个致命的“弱点”,那就是归并排序不是原地排序算法。
这是因为归并排序的合并函数,在合并两个有序数组为一个有序数组时,需要借助额外的存储空间。这一点你应该很容易理解。那我现在问你,归并排序的空间复杂度到底是多少呢?是 O(n),还是 O(nlogn),应该如何分析呢?
实际上,递归代码的空间复杂度并不能像时间复杂度那样累加。刚刚我们忘记了最重要的一点,那就是,尽管每次合并操作都需要申请额外的内存空间,但在合并完成之后,临时开辟的内存空间就被释放掉了。在任意时刻,CPU 只会有一个函数在执行,也就只会有一个临时的内存空间在使用。临时内存空间最大也不会超过 n 个数据的大小,所以空间复杂度是 O(n)。
4 | 2 | 5 | 1 | 6 | 3 |
4 | 2 | 5 | 1 | 6 | 3 |
4 | 2 | 5 | 1 | 6 | 3 |
4 | 2 | 1 | 6 |
左右2个有序数组开始并成一个新的有序数组
2 | 4 | 1 | 6 |
2 | 4 | 5 | 1 | 3 | 6 |
1 | 2 | 3 | 4 | 5 | 6 |
code
//有序数组的合并void merge(int arr[],int m,int n){ int len=n-m+1; int i=m; int mid=(m+n)/2; int j=mid+1; int *tmparr=malloc(sizeof(int)*len); int index=0; while(i<=mid && j<=n){ if(arr[i]<arr[j]){ tmparr[index++]=arr[i++]; } else if(arr[j]<arr[i]){ tmparr[index++]=arr[j++]; }else{ tmparr[index++]=arr[i++]; tmparr[index++]=arr[j++]; } } while(i<=mid){ tmparr[index++]=arr[i++]; } while(j<=n){ tmparr[index++]=arr[j++]; } int k=0; for(;k<index;k++){ arr[m+k]=tmparr[k]; } free(tmparr);}//归并排序void mergeSort(int arr[],int m,int n){ if(m>=n){ return; } int mid=(m+n)/2; mergeSort(arr,m,mid); mergeSort(arr,mid+1,n); merge(arr,m,n);}©著作权归作者所有:来自51CTO博客作者hkui2010的原创作品,如需转载,请注明出处,否则将追究法律责任
更多相关文章
- 插入排序和归并排序
- 3-18(排序的完结)
- 3-17(排序)
- 2021-03-16:手写代码:单链表归并排序。
- BAT iOS算法面试题(汇总)
- 114. 二叉树展开为链表
- 3-3
- 从数组中移除元素,要求时间复杂度为O(N)空间复杂度为O(1)
- 数据结构与算法专题——第三题 最长公共子序列