基于Javascript,实现快速排序

最近不忙,了解下前端数据结构和算法,因看到不同的实现方法,故单独写一篇记录快速排序,便于日后回顾。

参考书籍:《学习JavaScript数据结构与算法》第2版; 《数据结构与算法JavaScript描述》第1版

方法一:

《学习JavaScript数据结构与算法》

(1) 首先,从数组中选择中间一项作为主元。 (取数组中间项)

(2) 创建两个指针,左边一个指向数组第一个项,右边一个指向数组后一个项。移动左指 针直到我们找到一个比主元大的元素,接着,移动右指针直到找到一个比主元小的元素,然后交 换它们,重复这个过程,直到左指针超过了右指针。这个过程将使得比主元小的值都排在主元之 前,而比主元大的值都排在主元之后。这一步叫作划分操作。

(3) 接着,算法对划分后的小数组(较主元小的值组成的子数组,以及较主元大的值组成的 子数组)重复之前的两个步骤,直至数组已完全排

 代码实现:

function quickSort(arr) {
  // arr 数组,left 左指针,right 右指针
  function sort(arr, left, right) {
    if (arr.length == 0) {
      return []
    }

    // 获取主元,并划分
    var index = partition(arr, left, right);

    // 左侧重新划分,递归调用
    if (left < index - 1) {
      sort(arr, left, index - 1)
    }
    // 右侧重新划分,递归调用
    if (right > index) {
      sort(arr, index, right)
    }
  }

  //划分过程,取一个数据中间值,使左边的值都小于它,右边的值都大于它
  function partition(arr, left, right) {
    // 取中间值
    var pivot = arr[Math.floor((left + right) / 2)];

    while (left <= right) {
      // 循环找到左边大于pivot的值的索引
      while (arr[left] < pivot) {
        left++
      }
      // 循环找到右边小于pivot的值的索引
      while (arr[right] > pivot) {
        right--
      }
      // 交换位置,左指针右移,右指针左移
      if (left <= right) {
        [arr[left], arr[right]] = [arr[right], arr[left]];
        left++;
        right--;
      }
    }
    // 
    return left;
  }

  // 调用
  sort(arr, 0, arr.length - 1);
  return arr;
}

方法二:

《数据结构与算法JavaScript描述》

(1) 选择一个基准元素,将列表分隔成两个子序列;(取数组第一项)

(2)  对列表重新排序,将所有小于基准值的元素放在基准值的前面,所有大于基准值的元 素放在基准值的后面;

(3) 分别对较小元素的子序列和较大元素的子序列重复步骤 1 和 2

代码实现:

function quickSort2(list) {
  if (list.length == 0) {
    return [];
  }
  var lesser = []; // 小于基准的数组
  var greater = []; // 大于基准的数组
  var pivot = list[0]; // 取第一个值为基准
  for (var i = 1; i < list.length; i++) {
    if (list[i] < pivot) {
      lesser.push(list[i]);
    } else {
      greater.push(list[i]);
    }
  }
  return quickSort2(lesser).concat(pivot, quickSort2(greater));
}

测试代码:

// 先生成一个随机数组
function getRandomArr(n) {
  var arr = [];
  for (var i = 0; i < n; i++) {
    arr.push(Math.floor(Math.random() * (n + 1)))
  }
  return arr;
}
var randomArr = getRandomArr(100000);

// 调用方法一
let randomArr1 = JSON.parse(JSON.stringify(randomArr));
console.log(`排序前`);
console.log(randomArr1);
console.log(`排序后`);
let startTime = new Date();
console.log(quickSort(randomArr1));
console.log(`耗时: ${new Date() - startTime}ms`)


// 调用方法二
let randomArr2 = JSON.parse(JSON.stringify(randomArr));
console.log(`排序前`);
console.log(randomArr2);
console.log(`排序后`);
let startTime2 = new Date();
console.log(quickSort2(randomArr2));
console.log(`耗时: ${new Date() - startTime2}ms`)

结果发现,当数组长度为1,000时,两种方法耗时均为10ms左右,没有明显差异;当数组长度为10,000+时,方法一比方法二耗时更短;当数组长度100,000时,两种方法的耗时差更明显。因此选择数组中间项作比直接选择数组第一项为pivot,效率更高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值