算法设计与分析——快速排序

本文详细介绍了快速排序算法,包括其分治法的算法思想、JavaScript和C语言的实现代码,以及算法效率分析。通过实际测试示例展示了快速排序的工作过程,探讨了优化策略,如选择中位数作为基准元素。
摘要由CSDN通过智能技术生成

前言

快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为较小和较大的2个子序列,然后递归地排序两个子序列。
——维基百科

快速排序与归并排序相同,都是使用了分治法的思想,分而治之,只是两个算法的进行的思想不同,并且,快速排序不存在的操作,没有数组的合并,只是在原有数组基础上进行划分。在我们进行到最后一个步骤时(划分内只有一个元素时),其实就已经结束了。

算法分析

算法思想

官方的讲法,或许是有些抽象的。简单来说,快速排序,通过一个基准元素(用于和其他元素比较),将一段数组划为两个部分,左半部分的比该基准元素小,右半部分的比该基准元素大(至于等于?那就看设计者了,你可以将等于部分归到左半部分,或是归到右半部分,这并不重要,重要的是你考虑了等于的部分就行! )。典型的递归思想,显然,在完成一次排序后,基准元素已经回到它该回去的位置,而左半部分的和右半部分的再进行同样的操作,直到划分组内元素只剩一个(下面的left<right条件这样来)。

快速排序思想图

  • 1.这里我们以第一个元素为基准元素,那么我们扫描开始时,左边只需要从第二个开始扫描。
  • 2.i记录左边扫描到的数组下标j记录右边扫描到的数组下标,以此双向扫描,直到左边扫描的元素比基准大时停下,右边扫描元素比基准小或等于(这个等于,前提是我们想让左边的元素小于等于基准元素,这个以具体算法为准)记录当前下标i,j,交换两个位置元素,** i++,j-- **,继续下一次扫描,直到我们扫描完。
  • 3.如何算扫描完?这需要考虑好。当i==j或i>j时,显然,全部元素我们已经扫描一遍,本次划分已完成。
  • 4.直到某次划分时,元素只剩一个/或者没有时,变不再划分,直接返回,这里需要明确的是,我们并没有开新的数组,而是在原来数组的基础上进行划分!。

代码分析

JavaScript代码

需要说明的是,上次归并排序用的结构有点小傻(说我自己,当时写的时候不知道在想啥。。。),本次JavaScript代码使用的是原型链编程,直接在原型上进行函数书写,至于好处?我提一下,this因指向问题可以直接改变数组数据,无需开辟数组接收再来返回。具体的原因,有空的话专门去写一篇说明。

准备代码

利用原型,直接将数组内指定两个元素交换。

/**
 * JS原型编程 交换数组中的两个指定元素 i j为下标
 */
Array.prototype.swap = function (i, j) {
   
  var t = this[i];
  this[i] = this[j];
  this[j] = t;
}

普通版

代码分析
/**
   * QuickSort1函数
   * 通过Partition1函数获取到当前已归为的数据的下标
   * 将数组进行分割 分为归位的左半部分和归为的右半部分
   */
Array.prototype.QuickSort1 = function (left, right) {
    // 传参 (首下标,尾下标) 这里是第一次传参
  if (left < right) {
   
    s = this.Partition1(left, right); // 当前已经排序好的一个元素的数组下标
    this.QuickSort1(left, s - 1);
    this
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值