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

本文详细介绍了两种时间复杂度为O(nlogn)的排序算法——归并排序和快速排序。归并排序通过递归将数组分解并合并,快速排序则依赖于选取分区点进行数据划分。尽管两者在最坏情况下时间复杂度相同,但快速排序在实际应用中更广泛,因其平均时间复杂度稳定在O(nlogn)且实现更为简洁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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],步骤图解如下图:
在这里插入图片描述
伪代码如下:


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++] = A[j++]
    }
  <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值