快速选择算法

本文介绍了快速选择算法,它是快速排序算法的派生,用于在不完全排序的情况下找到序列中指定相对大小的数值。文章详细讲解了轴值的选取、排序过程以及如何从快速排序中提取快速选择算法。此外,还提供了C语言实现的例子,特别是针对LeetCode第215题的解决方案,即找出序列中第k大的数字。

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

快速选择算法

内容是根据leetcode第215题编写的,并且以下编程语言采用C语言

快速选择算法往往是为了在不将数字序列完整排序的前提下找到指定相对大小的数值(相对大小是指在相对于整个数字序列的大小,如“第3大的数字”,“第4小的数字”,“最大的数字”,“倒数第2个数字”等)

如果学习过快速排序算法,就可以很容易编写出来快速选择算法的内容(在下就是这样~)

快速排序算法

快速排序算法的一个核心是在当前限定的范围内(限定范围为下标leftright),选取一个轴值pivotVal,并根据排序是升序还是降序,将比pivotVal小的值和比pivotVal大的值分别“扔到”pivotVal两侧(升序排序则把比pivotVal小的值扔在左侧,比pivotVal大的值扔到左侧;降序排序反之),这样当前的轴值就会在排序完毕后的正确位置。
接着采用递归的方式,分别在轴值左右两段(left~pivot-1right~pivot+1)的数值选取各自的轴值,重复把数值扔两侧的操作,一直递归到排序完毕为止(即left >= right时,此时已经无法继续分段,之前的数字都已经在正确的位置上)

轴值的选取

轴值的临时存储位置要么选在数组当前分段的最左侧,要么选在最右侧。注意:这里说的是轴值的临时存储位置,这是因为:

  1. 轴值不一定就等于当前位置上的值。这是因为快速排序算法有两种形式,一种是将轴值的值固定为最左(右)侧位置上时直接采用当前位置上的值,一种是选取了位置但是值的选取是在当前分段中随机选取的(这是为了避免当序列为有序时,会发现划分出来的两个子序列一个里面没有元素,而另一个则只比原来少一个元素的情况)。这里我采用随机选取值的做法(快速排序的随机化版本),并且位置我选取了最左侧
  2. 说是临时存储位置是因为轴值的位置需要通过后续的条件判断将比轴值小的值和比轴值大的值各自分成两批之后,其中间值位置才能找到,这时才能确定轴值的位置
// 随机选取当前分段的轴值的值
// 随机选取当前分段一个下标值
srand((unsigned)time(NULL));
int random = left + rand() % (right - left + 1);
// 交换选取到的下标位置的值和最左侧的值的位置
// 这样就选取好了轴值的值并放置在最左侧
swap(&arr[left], &arr[random]);

开始排序

上述操作只是选取了值和临时存储位置,现在则是要找到轴值的正确位置
(采取的是升序排序)

int pivotVal = arr[left]; // 轴值的值,临时放在了最左侧
/* 轴值的当前位置,要在比轴值小的值和比轴值大的值
           各自分成两批之后才能确定轴值的正确位置 */
int pivot = left; 
int pre = pivot + 1; // 当前用于和轴值比较大小的值的下标
/* 当前下标值超出最右侧时则停止,
        	此时比轴值小的值和比轴值大的值已各自分成两批 */
while(pre <= right) {
   
    // 因为是升序排序,当比轴值小时则应该靠左侧放置
    if(arr[pre] < pivotVal) {
   
        // 当前轴值下标位置改变
        pivot ++;
        // 交换当前值和新轴值下标位置的值的位置
        swap(&arr[pre]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值