排序算法大比拼(2.2)——时间O(n log2n)篇之快速排序(左右指针法)

概述

快速排序是对冒泡排序的一种改进,也是当前人们认为综合效率最好的排序算法。
下面,让我们一起来学习最基本的快速排序叭~
建议大家先看看第一篇第二篇

算法思路

在这里插入图片描述

我们需要先找一个基准数k。在最基本的快速排序中,k可以是序列中的第一个数。

在这里插入图片描述

对于左指针,一个元素合法的定义是:这个数≤k。
左指针向后遍历不停地向后遍历,寻找第一个不合法的数。
3, 7, 1 ≤ 8,
10 ≥ 8。
左指针第一个不合法的数就是a[4] = 10。

对于右指针,一个元素合法的定义是:这个数≥k(和k值相等的数在那边都可以)。
在右指针那里,第一个数6就 < 8,不合法。

在这里插入图片描述

为了使得这两个数合法,我们把它们交换一下~

在这里插入图片描述

我们按照刚才的步骤再操作一次,又得到了两个不合法的数。

在这里插入图片描述

交换后,整个序列都合法了。
此时的a数组被分成的两个部分:<k,和≥k的。

在这里插入图片描述

我们可以序列分为两部分,每部分继续执行刚才的操作,直到整个序列有序。

动画演示

为方便大家理解,蒟蒻君给大家找了个动画。
这个动画与上述方法唯一不同的就是,基准数放到最后了。但本质还是没变。
在这里插入图片描述

代码实现

void quick_sort(int a[], int l, int r) {	// l, r表示排序范围 
    // 递归终止条件:序列为空
	if (l > r) {
		return;
    }
    int i = l, j = r, k = a[l];
    while (i != j) {
    	// 一定要先确定右指针,因为这样从而就能确定左指针遍历的范围。 
    	while (a[j] >= k && i < j) { // 右指针如果元素合法就一直向左遍历,停下的时候就是第一个不合法的元素
    		--j;
        }
        while (a[i] <= k && i < j) { // 左指针同理 
    		++i;
        }
        swap(a[i], a[j]);	// 即使i == j,交换也不会影响结果 
    }
    // 基准数归位
    a[l] = a[i];
    a[i] = k;
    // 将这一段数分为两段处理
    quick_sort(a, l, i - 1); // 继续处理左边的,这里是一个递归的过程
    quick_sort(a, i + 1, r); // 继续处理右边的 ,这里是一个递归的过程
}

算法特点

  • 每次将序列分成两部分用O(log2n),共分n次,最优/最差/平均时间复杂度O(n log2n)。
  • 原地排序,空间复杂度O(1)。
  • 因为基准数选择较随意,在快速排序里算比较慢的了(所有种类快速排序本质不会差太多,所以时间复杂度都会写成O(n log2n)。
  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蒟蒻一枚

谢谢鸭~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值