news 2026/5/9 3:45:16

JavaScript (Implement Quicksort with first element as pivot)以第一个元素为枢轴元素实现快速排序

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaScript (Implement Quicksort with first element as pivot)以第一个元素为枢轴元素实现快速排序

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

快速排序是一种分治算法。它选择一个元素作为枢轴,并围绕该枢轴对给定数组进行分区。快速排序有很多不同的版本,它们选择枢轴的方式各不相同。

·始终选择第一个元素作为枢轴。
·始终选择最后一个元素作为枢轴点。
·随机选择一个元素作为枢轴。
·选择中位数作为枢轴点。

注意:这里我们将通过选择第一个元素作为枢轴来实现快速排序。

选择第一个元素作为枢轴进行快速排序:

快速排序的关键功能是分区。分区的目标是在数组已排序的情况下,将枢轴元素放置在正确的位置,并将较小的(或相等的)元素放在其左侧,较大的元素放在其右侧,并且所有这些都要在线性时间内完成。

分区算法:

分区的方法有很多种,以下伪代码采用了 CLRS 书中给出的方法。

我们从最左边的元素开始,并将较小(或相等)元素的索引记为i。
在遍历过程中,如果我们找到一个更小(或相等)的元素,我们将当前元素与 arr[i] 交换。
否则,我们将忽略当前元素。

递归快速排序函数的伪代码:

// low –> Starting index, high –> Ending index

quickSort(arr[], low, high) {
if (low < high) {

// pi is partitioning index, arr[pi] is now at right place
pi = partition(arr, low, high);
quickSort(arr, low, pi – 1); // Before pi
quickSort(arr, pi + 1, high); // After pi
}
}

partition() 函数的伪代码

/* 此函数以数组首元素为基准元素,将基准元素放置在排序数组中的正确位置,并将所有小于或等于基准元素的元素放置在基准元素的左侧,所有大于基准元素的元素放置在基准元素的右侧。*/

partition(arr[], low, high) {
// 第一个元素作为枢轴
pivot = arr[low]
k = high
for (i = high; i > low; i--) {
if (arr[i] > pivot){
swap arr[i] and arr[k];
k--;
}
}
swap arr[k] and arr[low]
return k;
}

分区的图示 partition() :

Consider: arr[] = { 7, 6, 10, 5, 9, 2, 1, 15, 7 }

第一次分区: low = 0,high = 8,pivot = arr[low] = 7
初始化最右边元素的索引 k = high = 8。

·从 i = 高处到低处横移:
如果 arr[i] 大于 pivot:
交换 arr[i] 和 arr[k]。
减去 k;

·最后交换 arr[low] 和 arr[k]。

现在枢轴的正确位置是索引5。

第二次分区: low = 0,high = 4,pivot = arr[low] = 2
类似地初始化 k = high = 4;

2 的正确位置变为索引 1。左侧部分只有一个元素,右侧部分有 {6, 5, 7}。

另一方面,划分发生在段 [6, 8] 上,即数组 {10, 9, 15}。
这里 low = 6,high = 8,pivot = 10,k = 8。

10 的正确位置变为索引 7,左右两部分都只有一个元素。

第三划分: 这里划分线段 {6, 5, 7}。低位 = 2,高位 = 4,枢轴 = 6,k = 4。
如果应用相同的过程,我们将得到 6 的正确位置,即索引 3,并且左右两部分都只有一个元素。

这样一来,整个数组就排序完成了。请查看下图了解递归树。

请按照以下步骤实施该方法。

  • 使用递归函数(例如快速排序)来初始化该函数。
  • 调用分区函数对数组进行分区,并在分区函数内部执行以下操作:
    • 以第一个元素为枢轴并初始化迭代器k = high
    • 使用 for 循环从i = high 到 low+1 迭代:
      • 如果 arr[i] 大于 pivot,则交换arr[i]arr[k]并将 k 减 1。
    • 迭代后,将枢轴与arr[k]交换。
    • 返回 k-1 作为分割点。
  • 现在递归地对分区索引的左半部分和右半部分调用快速排序。

上述方法的代码示例:

function partition(function partition(array, low, high) {
// First Element as pivot
let pivot = array[low];

// st points to the starting of array
let start = low + 1;

// end points to the ending of the array
let end = high;

while (true) {
// It indicates we have already moved all the elements to their correct side of the pivot
while (start <= end && array[end] >= pivot) {
end--;
}

// Opposite process
while (start <= end && array[start] <= pivot) {
start++;
}

// Case in which we will exit the loop
if (start <= end) {
[array[start], array[end]] = [array[end], array[start]];
// The loop continues
} else {
// We exit out of the loop
break;
}
}

[array[low], array[end]] = [array[end], array[low]];
// As we got pivot element index is end
// now pivot element is at its sorted position
// return pivot element index (end)
return end;
}

function quick_sort(array, start, end) {
// If low is lesser than high
if (start < end) {
// idx is index of pivot element which is at its
// sorted position
let idx = partition(array, start, end);

// Separately sort elements before
// partition and after partition
quick_sort(array, start, idx - 1);
quick_sort(array, idx + 1, end);
}
}

function print_arr(arr) {
console.log(arr.join(" "));
}

// Driver Code
let arr1 = [7, 6, 10, 5, 9, 2, 1, 15, 7];
quick_sort(arr1, 0, arr1.length - 1);
console.log("Sorted array: ");
print_arr(arr1);


//contributed by Aditya Sharma

输出

已排序数组: 1 2 5 6 7 7 9 10 15

复杂性分析:

  • 时间复杂度:
    • 平均情况:O(N * logN),其中 N 是数组的长度。
    • 最佳情况:O(N * logN)
    • 最坏情况:O(N 2 )
  • 辅助空间:O(1)

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 16:22:11

使用Alpine配置WSL ssh门户栽

1. 哑铃图是什么&#xff1f; 哑铃图&#xff08;Dumbbell Plot&#xff09;&#xff0c;有时也称为DNA图或杠铃图&#xff0c;是一种用于比较两个相关数据点的可视化图表。 它源于人们对更有效数据比较方式的持续探索。 在传统的时间序列比较中&#xff0c;我们通常使用两条折…

作者头像 李华
网站建设 2026/4/16 2:42:05

用于尺寸标注函数 UF_DRF_object_s 结构体的详细说明

UF_DRF_object_s数据结构 该结构用于尺寸标注数据成员 ———————————————————————————— object_tag tag_t object_tag 标签相关的对象取决于object_assoc_type, 对象可能是一个点,线,弧,圆锥,三次样条曲线,曲线,模式,坚实的曲线,实用符号(中心线),注…

作者头像 李华
网站建设 2026/4/19 15:49:42

从付费软件到自主开发:我用AI和FFmpeg实现了一个录屏工具淌

我为什么会发出这个疑问呢&#xff1f;是因为我研究Web开发中的一个问题时&#xff0c;HTTP请求体在 Filter&#xff08;过滤器&#xff09;处被读取了之后&#xff0c;在 Controller&#xff08;控制层&#xff09;就读不到值了&#xff0c;使用 RequestBody 的时候。 无论是字…

作者头像 李华
网站建设 2026/4/20 14:57:43

个人知识库助手:OpenClaw+Qwen3-14B构建智能检索系统

个人知识库助手&#xff1a;OpenClawQwen3-14B构建智能检索系统 1. 为什么需要本地化知识库助手 去年我整理技术文档时&#xff0c;发现一个痛点&#xff1a;电脑里积累了上千份Markdown笔记、PDF论文和网页存档&#xff0c;但每次查找特定信息都要靠记忆中的文件名关键词。传…

作者头像 李华
网站建设 2026/4/20 18:40:20

AI面传统Java问题

Redis SDS相对C字符串优势 Dict触发hash扩容的两个条件 String三种底层编码是什么&#xff0c;什么区别 触发List底层结构由ziplist转向双向链表的两个阈值条件 Redis 3.2 版本前后&#xff0c;List 类型的底层编码分别是什么&#xff1f; ZSet 的 dict 和 zskiplist 如何配合&…

作者头像 李华
网站建设 2026/4/24 3:53:55

需求用例的写法

一、为什么写需求用例 流程图为需求用例提供了关键路径&#xff0c;而需求用例则是对业务场景的全面还原。本文将从以下四个方面阐述用例的信息&#xff1a; 用例的定义用例的粒度用例的例子用例的关键点解释 我写需求文档有几大准则&#xff0c;是需要时刻铭记和实践的&…

作者头像 李华