排序算法(2)-时间复杂度为O(nlogn)的排序算法(归并排序、快速排序)

1、归并排序
归并排序算法的核心思想:把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。具体过程如下图所示:
排序算法(2)-时间复杂度为O(nlogn)的排序算法(归并排序、快速排序)_第1张图片
归并排序使用的就是分治思想。分治,顾名思义,就是分而治之,将一个大问题分解成小的子问题来解决。小的子问题解决了,大问题也就解决了。分治算法一般都是用递归来实现的,所以归并排序我们首先考虑用递归实现。
写递归代码的技巧就是,分析得出递推公式,然后找到终止条件,最后将递推公式翻译成递归代码。所以,要想写出归并排序的代码,我们先写出归并排序的递推公式。
递推公式:merge_sort(p…r) = merge(merge_sort(p…q), merge_sort(q+1…r))
终止条件:p >= r 不用再继续分解

merge_sort(p…r) 表示,给下标从 p 到 r 之间的数组排序。我们将这个排序问题转化为了两个子问题,merge_sort(p…q) 和 merge_sort(q+1…r),其中下标 q 等于 p 和 r 的中间位置,也就是 (p+r)/2。当下标从 p 到 q 和从 q+1 到 r 这两个子数组都排好序之后,我们再将两个有序的子数组合并在一起,这样下标从 p 到 r 之间的数据就也排好序了。
由递推公式可进一步写出伪代码

// 归并排序算法, A是数组,n表示数组大小
merge_sort(A, n) {
    
merge_sort_c(A, 0, n-1)
}
// 递归调用函数
merge_sort_c(A, p, r) {
    
// 递归终止条件 
if p >= r then return 
// 取p到r之间的中间位置q 
q = (p+r) / 2 
// 分治递归 
merge_sort_c(A, p, q) 
merge_sort_c(A, q+1, r) 
// 将A[p...q]和A[q+1...r]合并为A[p...r] 
merge(A[p...r], A[p...q], A[q+1...r])
}

merge(A[p…r], A[p…q], A[q+1…r])这个函数的作用就是,将已经有序的 A[p…q]和 A[q+1…r]合并成一个有序的数组,并且放入 A[p…r],步骤图解如下图:
排序算法(2)-时间复杂度为O(nlogn)的排序算法(归并排序、快速排序)_第2张图片
伪代码如下:


merge(A[p...r], A[p...q], A[q+1...r]) {
   
  var i := p,j := q+1,k := 0 // 初始化变量i, j, k
  var tmp := new array[0...r-p] // 申请一个大小跟A[p...r]一样的临时数组
  while i<=q AND j<=r do {
   
    if A[i] <= A[j] {
   
      tmp[k++] = A[i++] // i++等于i:=i+1
    } else {
   
      tmp[k++

你可能感兴趣的:(数据结构与算法,算法,数据结构,排序算法,快速排序,java)