当前位置: 代码迷 >> 综合 >> js排序上篇(冒泡排序、选择排序、插入排序、希尔排序、快速排序)
  详细解决方案

js排序上篇(冒泡排序、选择排序、插入排序、希尔排序、快速排序)

热度:25   发布时间:2023-10-08 15:36:39.0

冒泡排序

工作原理

重复遍历序列,比较相邻的两个元素,如果这两个元素顺序不正确,则交换。重复以上步骤直到排序完成。

js代码实现 + 效率测试

运算10次,平均耗时1018 ms

// 创建 20000 个随机数,数值范围:1 - 100000
let ary = [];
for (let i = 0; i < 20000; i++) {
    ary.push( Math.floor( Math.random()*99999 + 1 ) );
}// 冒泡排序
console.time( '冒泡排序' );
let len = ary.length;
while (len > 0) {
    for (let i = 0; i < len; i++) {
    if (ary[i] > ary[i+1]) {
    let temp = ary[i];ary[i] = ary[i+1];ary[i+1] = temp;}}len--;
}
console.timeEnd( '冒泡排序' );

选择排序

工作原理

首先在未排序的序列中找到最小(或最大)的元素。然后将其与未排序的序列中最左侧的元素进行交换。以此类推,直到排序完成。

js代码实现 + 效率测试

运算10次,平均耗时344 ms

// 创建 20000 个随机数,数值范围:1 - 100000
let ary = [];
for (let i = 0; i < 20000; i++) {
    ary.push( Math.floor( Math.random()*99999 + 1 ) );
}// 选择排序 以每次找到最小的元素为例
console.time( '选择排序' );
let start = 0, len = ary.length;
while (start < len - 1) {
    let minIdx = start, min = ary[start];for (let i = start; i < len; i++) {
    if (ary[i] < min) {
    minIdx = i;min = ary[i];}}if (minIdx !== start) {
    let temp = ary[start];ary[start] = ary[minIdx];ary[minIdx] = temp;}start++;
}
console.timeEnd( '选择排序' );

插入排序

工作原理

通过构建有序序列,对未排序的数据,在已排序序列中从后向前扫描,找到相应位置并插入。

js代码实现 + 效率测试

运算10次,平均耗时121 ms

// 创建 20000 个随机数,数值范围:1 - 100000
let ary = [];
for (let i = 0; i < 20000; i++) {
    ary.push( Math.floor( Math.random()*99999 + 1 ) );
}// 插入排序
console.time( '插入排序' );
let len = ary.length;
for (let i = 1; i < len; i++) {
    let curr = ary[i],j = i - 1;while (j >= 0) {
    if (ary[j] > curr) {
    ary[j+1] = ary[j];}else {
    break;}j -= 1;}ary[j+1] = curr;
}
console.timeEnd( '插入排序' );

希尔排序

工作原理

希尔排序,是插入排序的一种更高效的改进版本。
它是基于插入排序的以下两点性质而提出改进方法的:

  1. 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
  2. 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。希尔排序通过将序列分为几个区域来提升插入排序的性能,这样可以让一个元素一次性地朝最终位置前进一大步。然后再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序。但是到了这步,需排序的数据几乎是已排好 的了(此时插入排序较快)。
js代码实现 + 效率测试

运算10次,平均耗时16.79 ms

// 创建 20000 个随机数,数值范围:1 - 100000
let ary = [];
for (let i = 0; i < 20000; i++) {
    ary.push( Math.floor( Math.random()*99999 + 1 ) );
}// 希尔排序
console.time( '希尔排序' );
let len = ary.length,step = Math.floor(len / 2 );
while (step > 0) {
    for (let i = 0; i < len; i++) {
    let curr = ary[i];let j = i;while (j >= step && ary[j - step] > curr) {
    ary[j] = ary[j - step];j -= step;}ary[j] = curr;}step = Math.floor(step / 2);
}
console.timeEnd( '希尔排序' );

快速排序(应用最为广泛)

工作原理

使用分治法来把一个序列分为两个子序列,然后递归地排序这两个子序列。
快速排序步骤为:

  1. 挑选基准值:从数列中挑出一个元素,称为“基准”。
  2. 分割:重新排序数列,所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准后面。在这个分割结束之后,对基准值的排序就已经完成。
  3. 递归排序子序列:分别递归地将小于和大于基准值元素的子序列排序。
js代码实现 + 效率测试

运算10次,平均耗时19.58 ms

// 创建 20000 个随机数,数值范围:1 - 100000
let ary = [];
for (let i = 0; i < 20000; i++) {
    ary.push( Math.floor( Math.random()*99999 + 1 ) );
}// 快速排序 基准默认总是取当前区间的最后一个元素
function quickSort(ary, start, end) {
    let _quickSort = function(ary, start, end) {
    if (end <= start) {
    return ;}let pivot = ary[end],left = start,right = end - 1;while (left < right) {
    while (ary[left] < pivot && left < right) left++;while (ary[right] >= pivot && left < right) right--;[ary[left], ary[right]] = [ary[right], ary[left]];}if (ary[left] >= pivot) {
    [ary[left], ary[end]] = [ary[end], ary[left]];}else {
    left++;}_quickSort(ary, start, left - 1);_quickSort(ary, left + 1, end);}_quickSort(ary, start, end);
}
console.time( '快速排序' );
quickSort(ary, 0, ary.length - 1);
console.timeEnd( '快速排序' );
V8引擎的内置函数Array.prototype.sort就是用快速排序实现的,有兴趣的朋友可以自行搜索一下,本文章只是基于20000个元素的序列进行测试,大家可自行测试更大或者更小的序列,对比使用哪个排序方法效率更高呢?
预告:下周六更新另外五种排序方法…
  相关解决方案