排序算法之选择排序

在开始之前,我们同样来看一下选择排序的过程:

从图中我们可以得出:

  1. 选择排序是将数组分成了两部分,一部分是已排序,一部分是未排序;

  1. 遍历未排序数组,从中选择最小/最大的元素,将其放在已排序数组的末尾。或者也可以说是把未排序数组中的最小/最大的元素跟未排序中的第一位交换位置;

  1. 循环执行第二步,直到所有数字都完成排序。

我们以数组[5,15,12,3,19,4,22]为例,看一下每一轮的变化:

let arr = [5,15,12,3,19,4,22]
let min    // 每一轮未排序数组最小值的下标
let notSortFirst    // 每一轮中未排序数组的第一个的下标
// 第一轮:
    // 未排序数组的第一个数字为5,下标为0
    notSortFirst = 0
    // 未排序数组中最小值为3,下标为3
    min = 3
    // 交换两个下标数字的位置 swap(0,3),数组变成:
    [3,15,12,5,19,4,22]
// 第二轮
    // 未排序数组的第一个数字为15,下标为1
    notSortFirst = 1
    // 未排序数组中最小值为4,下标为5
    min = 5
    // 交换两个下标数字的位置 swap(1,5),数组变成:
    [3,4,12,5,19,15,22]
// 第三轮
    // 未排序数组的第一个数字为12,下标为2
    notSortFirst = 2
    // 未排序数组中最小值为5,下标为3
    min = 3
    // 交换两个下标数字的位置 swap(2,3),数组变成:
    [3,4,5,12,19,15,22]
// 第四轮
    // 未排序数组的第一个数字为12,下标为3
    notSortFirst = 3
    // 未排序数组中最小值为12,下标为3
    min = 3
    // 交换两个下标数字的位置 swap(3,3),数组变成:
    [3,4,5,12,19,15,22]
// 第五轮
    // 未排序数组的第一个数字为19,下标为4
    notSortFirst = 4
    // 未排序数组中最小值为15,下标为5
    min = 5
    // 交换两个下标数字的位置 swap(4,5),数组变成:
    [3,4,5,12,15,19,22]
// 第六轮
    // 未排序数组的第一个数字为19,下标为5
    notSortFirst = 5
    // 未排序数组中最小值为19,下标为5
    min = 5
    // 交换两个下标数字的位置 swap(5,5),数组变成:
    [3,4,5,12,15,19,22]
// 第七轮
    // 未排序数组的第一个数字为22,下标为6
    notSortFirst = 6
    // 未排序数组中最小值为22,下标为6
    min = 6
    // 交换两个下标数字的位置 swap(6,6),数组变成:
    [3,4,5,12,15,19,22]
// 数组排序完成

从上面步可以看出,每一轮中未排序数组的第一项是从0一直增加到数组的最后一项的,而找最小值也是可以直接从未排序数组第一项的后一个开始找起,所以双重for循环可以这样写:

let arr = [5,15,12,3,19,4,22]
let min    // 每一轮未排序数组最小值的下标
let notSortFirst    // 每一轮中未排序数组的第一个的下标
for(let i = 0;i<arr.length;i++){
    notSortFirst = i
    for(let j = i+1;j<arr.length;j++){
        // 在这个循环里面找到最小值,存储它的下标
    }
    // 在这里将找到的最小值与未排序的第一个进行交换
    swap(notSortFirst,min)
}

我们发现notSortFirst就是每一轮中的i,所以可以直接使用i进行交换;而最后一轮只剩下一个数字,是可以不用排序的,所以外层循环可以只到length-1:

let arr = [5,15,12,3,19,4,22]
let min    // 每一轮未排序数组最小值的下标
for(let i = 0;i<arr.length-1;i++){
    for(let j = i+1;j<arr.length;j++){
        // 在这个循环里面找到最小值,存储它的下标
    }
    // 在这里将找到的最小值与未排序的第一个进行交换
    swap(i,min)
}

我们在找最小值的时候是需要有一个值进行对比才行,也就是min需要有一个默认值,在内层循环中将每一项与min进行比较,如果比min对应的值小,就给min重新赋值。那min的默认值我们就可以设置成未排序数组的第一项:

let arr = [5,15,12,3,19,4,22]
let min    // 每一轮未排序数组最小值的下标
for(let i = 0;i<arr.length-1;i++){
    min = i
    for(let j = i+1;j<arr.length;j++){
        // 在这个循环里面找到最小值,存储它的下标
        if(arr[j] < arr[min]){
            min = j
        }
    }
    // 在这里将找到的最小值与未排序的第一个进行交换
    swap(i,min)
}
console.log(arr)

现在就是要实现数字的交换,我们可以像上一张冒泡排序一样直接在for循环里面写,但是在排序中我们很多地方都会用到数组的交换,可以提取成一个方法放到数组的原型上:

Array.prototype.swap = function(originIndex,targetIndex){
    let temp = this[originIndex]
    this[originIndex] = this[targetIndex]
    this[targetIndex] = temp
}
let arr = [5,15,12,3,19,4,22]
let min    // 每一轮未排序数组最小值的下标
for(let i = 0;i<arr.length-1;i++){
    min = i
    for(let j = i+1;j<arr.length;j++){
        // 在这个循环里面找到最小值,存储它的下标
        if(arr[j] < arr[min]){
            min = j
        }
    }
    // 在这里将找到的最小值与未排序的第一个进行交换
    // 只有当i与min值不同的时候才交换
    i!==min && arr.swap(i,min)
}
console.log(arr)    // [3, 4, 5, 12, 15, 19, 22]

以上就是选择排序的实现了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值