“快速排序”
2023-12-21 17:17:39
在我们写算法中,如果需要高效的、原地的排序算法,这时候我们就可以用到快速排序
概念
快速排序(Quick Sort)是一种常用的排序算法,用于将一组数据按照一定的顺序进行排列。它的 基本思想 是通过分治的策略将原始数组分割成较小的子数组,然后递归地对子数组进行排序,最终将这些子数组合并起来得到有序数组。
这个算法的 “快速” 体现在以下几个方面:
- 快速的平均时间复杂度: 在平均情况下,快速排序的时间复杂度为O(nlogn),性能非常优秀。
- 快速的排序过程: 快速排序采用了分而治之的策略,通过不断地分割和排序来实现快速排序,因此排序的过程相对较快。
- 快速的原地排序: 快速排序通常是原地排序的,不需要额外的存储空间。
总的来说,快速排序是一种高效的、原地的排序算法,虽然在最坏情况下时间复杂度可能较高,但在实际应用中,它的性能仍然非常出色。
那么它排序的步骤呢 (算法描述)
选择一个基准值(pivot),通常选择第一个元素作为基准值
。将数组中小于等于基准值的元素放到基准值的左边,大于基准值的元素放到右边,基准值所在的位置通常称为分区点(pivot position)
。递归地对基准值左右两侧的子数组进行快速排序
。重复上述步骤,直到所有的子数组都变得很小,排序完成
。
快速排序的关键在于分区操作,即如何将小于等于基准值和大于基准值的元素分开。一般情况下,可以使用双指针法或者递归实现来进行分区操作。
快速排序的时间复杂度为O(nlogn),
在平均情况下性能很好,
但最坏情况下可能达到O(n^2)。
然而,由于其原地排序和非稳定性,快速排序在实际应用中仍然被广泛使用。
function quickSort(arr, left, right):
if left < right:
pivotIndex = partition(arr, left, right) // 获取基准值的位置
quickSort(arr, left, pivotIndex - 1) // 对基准值左边的子数组进行快速排序
quickSort(arr, pivotIndex + 1, right) // 对基准值右边的子数组进行快速排序
function partition(arr, left, right):
pivot = arr[left] // 选择第一个元素作为基准值
i = left + 1
j = right
while i <= j:
// 找到左边第一个比基准值大的元素
while i <= j and arr[i] <= pivot:
i = i + 1
// 找到右边第一个比基准值小的元素
while i <= j and arr[j] > pivot:
j = j - 1
if i <= j:
swap(arr, i, j) // 交换左右两个元素
swap(arr, left, j) // 将基准值放到正确的位置上
return j // 返回基准值的位置
function swap(arr, i, j):
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
这个伪代码描述了快速排序的基本思想和分区操作。你可以根据这个描述来实现快速排序算法。
实现
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
const pivot = arr[0]; // 选择第一个元素作为基准值
const left = [];
const right = [];
for (let i = 1; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]); // 比基准值小的放在左边
} else {
right.push(arr[i]); // 比基准值大的放在右边
}
}
return [...quickSort(left), pivot, ...quickSort(right)]; // 递归处理左右两部分,并将结果合并
}
// 测试
const arr = [3, 6, 8, 10, 1, 2, 1];
const sortedArr = quickSort(arr);
console.log(sortedArr); // 输出排序后的数组
这段代码实现了快速排序算法。在这个示例中,我们选择数组中的第一个元素作为基准值(pivot),然后将数组中比基准值小的元素放到左边,比基准值大的元素放到右边,最后递归地对左右两部分进行排序,直到每个子数组的长度都不大于1。
function quickSort(arr, left = 0, right = arr.length - 1) {
if (left >= right) {
return;
}
const pivot = partition(arr, left, right); // 找到基准值的位置
quickSort(arr, left, pivot - 1); // 递归处理左边的子数组
quickSort(arr, pivot + 1, right); // 递归处理右边的子数组
}
function partition(arr, left, right) {
const pivotValue = arr[left]; // 选择第一个元素作为基准值
let i = left + 1;
let j = right;
while (i <= j) {
while (i <= j && arr[i] < pivotValue) {
i++; // 找到左边第一个比基准值大的元素
}
while (i <= j && arr[j] > pivotValue) {
j--; // 找到右边第一个比基准值小的元素
}
if (i <= j) {
[arr[i], arr[j]] = [arr[j], arr[i]]; // 交换左右两个元素
i++;
j--;
}
}
[arr[left], arr[j]] = [arr[j], arr[left]]; // 将基准值放到正确的位置上
return j; // 返回基准值的位置
}
// 测试
const arr = [3, 6, 8, 10, 1, 2, 1];
quickSort(arr);
console.log(arr); // 输出排序后的数组
这种实现方式与上面的示例有所不同,它使用了双指针的方式来找到基准值的位置,并且是在原数组上进行操作的。
无论哪种实现方式,快速排序算法的核心思想都是通过分治的策略将问题规模逐步缩小,最终得到一个有序的结果。希望这能帮助你更好地理解快速排序算法的实现过程。
文章来源:https://blog.csdn.net/He_9a9/article/details/135130416
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!