首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

排序——归并排序(Merge sort)

  • 25-03-04 09:02
  • 2504
  • 5193
blog.csdn.net

1945年,约翰·冯·诺依曼(John von Neumann)发明了归并排序,这是典型的分治算法的应用。

定义

归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

算法思路

归并排序算法有两个基本的操作,一个是分,也就是把原数组划分成两个子数组的过程。另一个是治,它将两个有序数组合并成一个更大的有序数组。

  1. 将待排序的线性表不断地切分成若干个子表,直到每个子表只包含一个元素,这时,可以认为只包含一个元素的子表是有序表。
  2. 将子表两两合并,每合并一次,就会产生一个新的且更长的有序表,重复这一步骤,直到最后只剩下一个子表,这个子表就是排好序的线性表。

图解算法

假设我们有一个初始数列为{8, 4, 5, 7, 1, 3, 6, 2},整个归并排序的过程如下图所示。

分而治之

可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。分阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n。

合并两个有序数组流程

再来看看治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。

动画展示

算法性能

速度仅次于快速排序。

时间复杂度

O(nlogn)。

空间复杂度

O(N),归并排序需要一个与原数组相同长度的数组做辅助来排序。

稳定性

稳定。

代码实现

C和C++

  1. void Merge(int sourceArr[],int tempArr[], int startIndex, int midIndex, int endIndex){
  2. int i = startIndex, j=midIndex+1, k = startIndex;
  3. while(i!=midIndex+1 && j!=endIndex+1) {
  4. if(sourceArr[i] > sourceArr[j])
  5. tempArr[k++] = sourceArr[j++];
  6. else
  7. tempArr[k++] = sourceArr[i++];
  8. }
  9. while(i != midIndex+1)
  10. tempArr[k++] = sourceArr[i++];
  11. while(j != endIndex+1)
  12. tempArr[k++] = sourceArr[j++];
  13. for(i=startIndex; i<=endIndex; i++)
  14. sourceArr[i] = tempArr[i];
  15. }
  16. //内部使用递归
  17. void MergeSort(int sourceArr[], int tempArr[], int startIndex, int endIndex) {
  18. int midIndex;
  19. if(startIndex < endIndex) {
  20. midIndex = startIndex + (endIndex-startIndex) / 2;//避免溢出int
  21. MergeSort(sourceArr, tempArr, startIndex, midIndex);
  22. MergeSort(sourceArr, tempArr, midIndex+1, endIndex);
  23. Merge(sourceArr, tempArr, startIndex, midIndex, endIndex);
  24. }
  25. }
  26. int main(int argc, char * argv[]) {
  27. int a[8] = {50, 10, 20, 30, 70, 40, 80, 60};
  28. int i, b[8];
  29. MergeSort(a, b, 0, 7);
  30. for(i=0; i<8; i++)
  31. printf("%d ", a[i]);
  32. printf("\n");
  33. return 0;
  34. }

Java

  1. package MergeSort;
  2. public class MergeSort {
  3. public static int[] mergeSort(int[] nums, int l, int h) {
  4. if (l == h)
  5. return new int[] { nums[l] };
  6. int mid = l + (h - l) / 2;
  7. int[] leftArr = mergeSort(nums, l, mid); //左有序数组
  8. int[] rightArr = mergeSort(nums, mid + 1, h); //右有序数组
  9. int[] newNum = new int[leftArr.length + rightArr.length]; //新有序数组
  10. int m = 0, i = 0, j = 0;
  11. while (i < leftArr.length && j < rightArr.length) {
  12. newNum[m++] = leftArr[i] < rightArr[j] ? leftArr[i++] : rightArr[j++];
  13. }
  14. while (i < leftArr.length)
  15. newNum[m++] = leftArr[i++];
  16. while (j < rightArr.length)
  17. newNum[m++] = rightArr[j++];
  18. return newNum;
  19. }
  20. public static void main(String[] args) {
  21. int[] nums = new int[] { 9, 8, 7, 6, 5, 4, 3, 2, 10 };
  22. int[] newNums = mergeSort(nums, 0, nums.length - 1);
  23. for (int x : newNums) {
  24. System.out.println(x);
  25. }
  26. }
  27. }

Python

  1. def MergeSort(lists):
  2. if len(lists) <= 1:
  3. return lists
  4. num = int( len(lists) / 2 )
  5. left = MergeSort(lists[:num])
  6. right = MergeSort(lists[num:])
  7. return Merge(left, right)
  8. def Merge(left,right):
  9. r, l=0, 0
  10. result=[]
  11. while l<len(left) and r<len(right):
  12. if left[l] <= right[r]:
  13. result.append(left[l])
  14. l += 1
  15. else:
  16. result.append(right[r])
  17. r += 1
  18. result += list(left[l:])
  19. result += list(right[r:])
  20. return result
  21. print MergeSort([1, 2, 3, 4, 5, 6, 7, 90, 21, 23, 45])

 

注:本文转载自blog.csdn.net的努力的老周的文章"https://blog.csdn.net/justidle/article/details/104203958"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top