Rust:快速排序
快速排序是一种高效的排序算法。它采用了分治法(Divide and Conquer)的思想,把一个序列分成两个子序列,然后递归地对子序列进行快速排序。
原理
快速排序的基本思想是:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
快速排序采用了分治法的思想。分治法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。
快速排序的具体过程为:在待排序序列中选择一个元素作为基准元素(pivot),然后将所有比基准元素小的元素放到基准元素的左边,所有比基准元素大的元素放到基准元素的右边。这样,基准元素左边的元素都比基准元素小,基准元素右边的元素都比基准元素大。然后对基准元素左右两边的子序列递归进行上述操作,直到序列有序。
步骤
下面是快速排序算法的具体步骤:
- 选择基准元素:从待排序序列中选择一个元素作为基准元素。通常选择第一个元素或最后一个元素作为基准元素。
- 划分子序列:将所有比基准元素小的元素放到基准元素的左边,所有比基准元素大的元素放到基准元素的右边。
- 递归排序:对基准元素左右两边的子序列递归进行上述操作,直到序列有序。
下面是一个快速排序算法在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