【递归版】归并排序算法(1)

简介: 【递归版】归并排序算法(1)



MergeSort归并排序

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

归并排序核心步骤:分解+合并

归并排序的特性总结:

1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考是解决在磁盘中的外排序问题。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(N)
4. 稳定性:稳定

对于两端有序序列的合并,在顺序表和链表的OJ题目都学习过了。


整体思想

整体思想

  • 分治的思想(分而治之)分治的思想一般都用递归的方式去完成。
  • 两个有序序列合并任然是有序序列
  • 一段无序序列>>>>>>有序
  • 无序序列一直【递推】分割分割直到一个元素(一个元素肯定有序)
  • 再【回归】的时候合并即可
  • 递归的两部分:子问题&结束条件

整个流程

  • 开辟一个tmp新的数组在外部(不可能每次递归都开辟一个新的数组)
  • 开始分解[begin,mid] [mid+1,end]
  • 分解到不能在分解了(只有一个元素肯定是顺序序列)回归begin = end
  • 合并
  • 两个有序序列数组和链表合并,依旧有序(取小值尾插)
  • 有序序列合并(归并有序序列)
  1. 利用开辟一个tmp新的数组(不能放到MergeSort函数里面,不可能每次递归都开辟一个新的数组)
  2. 选小的尾插直到至少序列begin > end
  3. 若还有序列存在元素直接尾插到tmp后面
  • 拷贝到a数组
  • 最后记住释放free(tmp)❗

重点突破

  • 递归的分解
  • 有序序列的合并
  • tmp数组的开辟

易错点突破

  • 有序序列的合并(&&)
  • 拷贝的起始位置
  • 下标和元素个数和区间问题

图解分析

代码实现

void _MergeSort(int* a, int* tmp,int begin, int end)
{
  if (begin >= end)
  {
    return;
  }
  //分割
  int mid = (begin + end) / 2;
  //[begin,mid] [mid+1 ,end]
  _MergeSort(a, tmp, begin, mid);
  _MergeSort(a, tmp, mid + 1, end);
  //合并
  int begin1 = begin;
  int end1 = mid;
  int begin2 = mid + 1;
  int end2 = end;
  int i = begin;
  //int i = 0;
  while (begin1 <= end1 && begin2 <= end2)
  {
    if (a[begin1] < a[begin2])
    {
      tmp[i++] = a[begin1++];
    }
    else//>
    {
      tmp[i++] = a[begin2++];
    }
  }
  while (begin1 <= end1)//
  {
    tmp[i++] = a[begin1++];
  }
  while (begin2 <= end2)
  {
    tmp[i++] = a[begin2++];
  }
  //合并完成拷贝
  //memcpy(a + begin, tmp, (end - begin + 1) * sizeof(int));
  memcpy(a + begin, tmp+begin, (end - begin + 1) * sizeof(int));
}
void MergeSort(int* a, int n)
{
  int* tmp = (int*)malloc(sizeof(int) * n);
  if (tmp == NULL)
  {
    perror("malloc fail");
    return;
  }
  _MergeSort(a, tmp, 0, n - 1);
  free(tmp);
}

时间复杂度

时间复杂度O(N*logN)

递归&归并排序VS快速排序

  • 快速排序的递归:前序递归
  • 归并排序的递归 :后序递归

🙂感谢大家的阅读,若有错误和不足,欢迎指正。

目录
相关文章
|
30天前
|
算法 搜索推荐 Java
算法实战:手写归并排序,让复杂排序变简单!
归并排序是一种基于“分治法”的经典算法,通过递归分割和合并数组,实现O(n log n)的高效排序。本文将通过Java手写代码,详细讲解归并排序的原理及实现,帮助你快速掌握这一实用算法。
37 0
|
1月前
|
算法
【算法】递归、搜索与回溯——汉诺塔
【算法】递归、搜索与回溯——汉诺塔
|
30天前
|
数据采集 搜索推荐 算法
【高手进阶】Java排序算法:从零到精通——揭秘冒泡、快速、归并排序的原理与实战应用,让你的代码效率飙升!
【8月更文挑战第21天】Java排序算法是编程基础的重要部分,在算法设计与分析及实际开发中不可或缺。本文介绍内部排序算法,包括简单的冒泡排序及其逐步优化至高效的快速排序和稳定的归并排序,并提供了每种算法的Java实现示例。此外,还探讨了排序算法在电子商务、搜索引擎和数据分析等领域的广泛应用,帮助读者更好地理解和应用这些算法。
20 0
|
1月前
|
算法
【算法】递归总结:循环与递归的区别?递归与深搜的关系?
【算法】递归总结:循环与递归的区别?递归与深搜的关系?
|
1月前
|
算法
【算法】递归、搜索与回溯——简介
【算法】递归、搜索与回溯——简介
|
2月前
|
算法 Python
python中算法递归错误(Recursion Errors)
【7月更文挑战第18天】
39 1
|
2月前
|
存储 算法 搜索推荐
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
【7月更文挑战第12天】归并排序是高效稳定的排序算法,采用分治策略。Python 实现包括递归地分割数组及合并已排序部分。示例代码展示了如何将 `[12, 11, 13, 5, 6]` 分割并归并成有序数组 `[5, 6, 11, 12, 13]`。虽然 $O(n log n)$ 时间复杂度优秀,但需额外空间,适合大规模数据排序。对于小规模数据,可考虑其他算法。**
65 4
|
2月前
|
算法 搜索推荐 C#
|
3月前
|
搜索推荐 C语言
【C/排序算法】:快速排序和归并排序的非递归实现
【C/排序算法】:快速排序和归并排序的非递归实现
21 0
|
3月前
|
搜索推荐 算法
【C/排序算法】:归并排序和计数排序
【C/排序算法】:归并排序和计数排序
26 0