likes
comments
collection
share

Rust:快速排序

作者站长头像
站长
· 阅读数 49

快速排序是一种高效的排序算法。它采用了分治法(Divide and Conquer)的思想,把一个序列分成两个子序列,然后递归地对子序列进行快速排序。

原理

快速排序的基本思想是:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

快速排序采用了分治法的思想。分治法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。

快速排序的具体过程为:在待排序序列中选择一个元素作为基准元素(pivot),然后将所有比基准元素小的元素放到基准元素的左边,所有比基准元素大的元素放到基准元素的右边。这样,基准元素左边的元素都比基准元素小,基准元素右边的元素都比基准元素大。然后对基准元素左右两边的子序列递归进行上述操作,直到序列有序。

步骤

下面是快速排序算法的具体步骤:

  1. 选择基准元素:从待排序序列中选择一个元素作为基准元素。通常选择第一个元素或最后一个元素作为基准元素。
  2. 划分子序列:将所有比基准元素小的元素放到基准元素的左边,所有比基准元素大的元素放到基准元素的右边。
  3. 递归排序:对基准元素左右两边的子序列递归进行上述操作,直到序列有序。

下面是一个快速排序算法在Rust语言中的实现:

 
fn quick_sort(arr: &mut [i32]) {
    if arr.len() <= 1 { // 如果数组长度小于等于1,直接返回
        return;
    }

    let pivot_index = partition(arr); // 对数组进行分区

    let (left, right) = arr.split_at_mut(pivot_index); // 将数组分成两部分
    quick_sort(left); // 对左半部分进行快速排序
    quick_sort(&mut right[1..]); // 对右半部分进行快速排序
}

fn partition(arr: &mut [i32]) -> usize {
    let pivot = arr[arr.len() - 1]; // 选择最后一个元素作为枢轴
    let mut i = 0;

    for j in 0..arr.len() - 1 { // 遍历数组中除了最后一个元素以外的所有元素
        if arr[j] < pivot { // 如果当前元素小于枢轴,将它与arr[i]交换位置,并将i加1
            arr.swap(i, j);
            i += 1;
        }
    }

    arr.swap(i, arr.len() - 1); // 将枢轴与arr[i]交换位置
    i // 返回枢轴的下标
}

上面代码中,quick_sort函数是快速排序算法的主函数。它首先判断待排序序列是否为空或只有一个元素,如果是,则直接返回。然后调用partition函数对待排序序列进行划分,并得到划分后基准元素所在位置pivot_index。接着对划分后得到的两个子序列递归调用quick_sort函数进行排序。

partition函数是快速排序算法中用于划分子序列的函数。它首先选择最后一个元素作为基准元素,并定义一个变量i用于记录比基准元素小的元素个数。然后遍历待划分序列中除最后一个元素外其他所有元素,如果当前遍历到的元素比基准元素小,则将其与第i个位置上的元素交换位置,并将i加1。遍历完成后,将最后一个位置上(即基准元素所在位置)与第i个位置上的元素交换位置。此时,第i个位置上即为划分后基准元素所在位置。

复杂度分析

快速排序算法时间复杂度为O(nlogn),空间复杂度为O(logn)。

快速排序的适用情况

快速排序是一种高效的排序算法,它适用于数据杂乱无章的场景,而且越乱,快速排序的效率越体现的淋漓尽致 。

时间复杂度为O(nlogn)。虽然快速排序的最坏时间复杂度能达到O(n^2),但在实际使用中可以用各种技巧把最坏情况优化掉,使算法在各种情况的排序中令时间复杂度接近O(nlogn)

应用实例

下面是一个使用快速排序算法对整数数组进行升序排列的示例:

fn main() {
    let mut arr = [8, 5, 2, 9, 7, 6, 3];
    println!("Before: {:?}", arr);

    quick_sort(&mut arr);
    println!("After: {:?}", arr);
}

运行上面代码,可以得到如下输出结果:

Before: [8, 5, 2, 9, 7, 6, 3]
After: [2, 3, 5, 6, 7, 8, 9]

快速排序的优缺点

快速排序是一种高效的排序算法,它具有排序速度快,而且是就地排序等优点,使得在许多编程语言的内部元素排序实现中采用的就是快速排序

但是,快速排序也有一些缺点。首先,它是一种不稳定排序,比如基准值的前后都存在与基准值相同的元素,那么相同值就会被放在一边,这样就打乱了之前的相对顺序 。

其次,每次选择的关键值可以把数组分为两个子数组的时候,快速排序算法的速度最快,当数组已经是正序或逆序时速度最慢 from刘金,转载请注明原文链接。感谢!

转载自:https://juejin.cn/post/7234088398021328955
评论
请登录