JS 这一次彻底理解选择排序

壹 ❀ 引

我在 JS 这一次彻底理解冒泡排序 一文中介绍了十大经典排序中的冒泡排序,所谓冒泡排序就是不断比较相邻的两个元素,让较小的往前浮,较大的往后沉,直到所有元素找到自己对应的位置。那么现在我们接着理解第二种排序--选择排序,每天进步一点点,本文开始。

贰 ❀ 选择排序基本概念

选择排序相对冒泡排序理解起来其实更简单粗暴,首先在未排序的数组中找到最小项,并移动到数组起始位置,之后对其它未排序的元素继续遍历,接着找最小的元素,放在已排序的元素后面,直到所有数组排序完成。

首先第一个问题,怎么知道哪个元素最小呢?有的同学可能想到了Math.min.apply(null,arr)方法,前面我们说了找到最小元素放到数组头部,很明显我们需要知道最小元素的index,这样才能便于利用index交换元素位置。

不卖关子,其实我们可以假设数组的第 i 项最小,遍历并拿 i+1 项与之比较,只要后者比 i 小,将 i 改成当i+1项 的索引即可,例如:

var arr = [4, 2, 1, 3],
    len = arr.length,
    i = 0,
    minIndex = i;
for (; i < len; i++) {
    if (arr[i + 1] < arr[minIndex]) {
        minIndex = i + 1;
    };
};
console.log(minIndex);//2

知道了这一点,我们来简单模拟一次选择排序,假设现在有数组[4,2,1,3];

  • 第一次遍历
    • 找到最小元素1,与4交换位置,得到数组[1,2,4,3];
  • 第二次遍历
    • 找到最小元素2,由于第一项一定是最小,2又在第一项后面,不需要交换。
  • 第三次遍历
    • 找到最小元素3,与4交换位置,得到数组[1,2,3,4]

不知道大家有没有看出这样几个规律:

  • 每次遍历,一定能确认一个最小项,所以下次遍历时可以跳过这一项,遍历次数越多,下次遍历查找的次数就越少。以上面例子来说,第一次遍历从 i=0开始,遍历完成,下次遍历查找就得从i=1开始。
  • 当遍历到length -1次时,剩下的一个元素一定是最大的一个,所以没有再查找的必要。以上面的例子为例,遍历到第三次时,剩下一个4已经是最大,无需下次遍历。

知道了这两个规律,我们来尝试实现选择排序。

叁 ❀ 选择排序实现

function selectionSort(arr) {
    var len = arr.length,
        i = 0,
        minIndex;
    // 定义遍历次数,一共只需要遍历length-1次
    for (; i < len - 1; i++) {
        // 假设的最小项,每遍历一次,假设最小项就会往后推一次,这样就会少查找一次
        minIndex = i;

        // 与假设最小项比较的一项,自然是i+1项
        for (var j = i + 1; j < len; j++) {
            arr[j] < arr[minIndex] ? minIndex = j : null;
        };

        // 确定最小项位置后,把最小项往前排
        arr[i] = [arr[minIndex], arr[minIndex] = arr[i]][0];
    };

    return arr;
};
var arr = [7, 5, 3, 2, 4, 1, 6];
selectionSort(arr); //[1, 2, 3, 4, 5, 6, 7]

需要注意的点已经在代码中通过注释标注了。另外,选择排序无论处理什么样的数据,时间复杂度都是O(n²),所以它只适合处理数据规模不大的场景。

若文中存在描述不当,还望指出,那么到这里,本文结束。

肆 ❀ 参考

选择排序

【图解数据结构】 一组动画彻底理解选择排序

原文地址:https://www.cnblogs.com/echolun/p/12641595.html