排序算法-选择排序

117 阅读3分钟

排序算法是基础的算法,也是每个前端人员需要掌握的基础,下面就让我们一起去实现一下这些JS的排序

一,用递归实现排序

1.第一步,我们首先来想一下如何找出一个数组中的最小值

(1)先从两个数中找出最小的数 [a,b]

let minOf2 = (numbers) => {
    return numbers[0] < numbers[1] ? numbers[0] : numbers[1]
}

通过一个三元表达式就可以实现,当然我们可以优化一下代码,用析构赋值实现

let minOf2 = ([a, b]) => a < b ? a : b

调用:

minOf2.call(null, [1,2]) 

JS也有现成的API,内置了Math.min

Math.min(1,2)//1
Math.min.call(null,1,2)//1
Math.min.apply(null,[1,2])

(2)下面我们想一下,从三个数中找出最小值

let minOf3 = (numbers) => {
    return minOf2([a, minOf2([b, c])])
};

我们可以使用递归的方法,调用minOf2函数,可以从三个数里面找出最小值

(3)四个数呢?

let minOf4 = (numbers) => {
    return minOf2([a, minOf3([b, c, d])])
};

所以我们可以得出结论:求任意长度数组的最小值都可以通过minOf2实现

(4)不同数组长度,我们要反复声明,那么我们能不能用一个函数来实现呢?

let min = (numbers) => {
        return min([numbers[0], min(numbers.slice(1))])
    }

这是一个递归函数,每调用一次,就从数组中删除第一个元素

但是没有结束条件会陷入死循环,下面我们加入退出条件

let min = (numbers) => {
    if (numbers.length > 2) {
        return min([numbers[0], min(numbers.slice(1))])
    } else {
        return Math.min.apply(null, numbers)
    }
}

这样我们就用递归的方法,找出了最小值

2.第二步,我们试一下利用上面的函数,把一个数组用递归的方式从小到大排列一下

(1)和找最小数一样,我们先从两个数开始

let sort2 = (numbers) => {
    return numbers[0] < numbers[1] ? [numbers[0], numbers[1]] : [numbers[1], numbers[0]]
};

也是一个三元表达式就可以做到

(2)下面三个数排序

let sort3 = ([a,b,c])=>{
    return [min([a,b,c]),sort2([?,?])
}

通过min函数找出最小值放在前面,然后后面两个进行比较,但是我们不知道a,b,c哪一个最小,所以后面的sort2里面的参数无法确定

这时,需要我们把最小的值从数组里面删去,然后进行后面两个数的排序

首先我们需要先创造一个函数,来求出最小值的下标

let minIndex = (numbers) =>
    let intIndex = 0
for (let i = 1; i < numbers.length; i++) {
    if (numbers[i] < numbers[index]) {
        intIndex = i
    }
}
return intIndex
}

这时我们可以得到最小值的下标,下面来修改我们的代码

let sort3 = (numbers) => {
    let index = minIndex(numbers)
    let minNum = numbers[index]
    numbers.split(index, 1)
    return [minNum].concat(sort2(numbers))
};

(3)接着四个数

let sort4 = (numbers) => {
    let index = minIndex(numbers)
    let minNum = numbers[index]
    numbers.split(index, 1)
    return [minNum].concat(sort3(numbers))
};

我们只要找出最小值,每递归一次,就把最小值从数组中删去,然后对新数组进行递归,最后将他们用concat链接起来,就实现了。

(4)下面我们还是想办法用一个函数实现

let sort = (numbers) => {
    let index = minIndex(numbers)
    let minNum = numbers[index]
    numbers.split(index, 1)
    return [minNum].concat(sort(numbers))
}; 

又是一个死循环,继续改进

let sort = (numbers) => {
    if (numbers.length > 2) {
        let index = minIndex(numbers)
        let minNum = numbers[index]
        numbers.splice(index, 1)
        return [minNum].concat(sort(numbers))
    } else {
        return numbers[0] < numbers[1] ? numbers : numbers.reverse()
    }
};

这样就可以实现了用递归进行数组排序。

二,用for循环实现排序(冒泡排序)

1,用冒泡排序实现,首先我们要先实现一下,两个变量如何进行交换

let swap = (array, i, j) => {
let temp = array[i]
array[i] = array[j]
array[j] = temp
}

这样我们就简单的实现了交换两个变量

下面用for循环实现一下排序

let sort = (arr) => {
            for (var i = 0; i <= arr.length - 1; i++) { // 外层循环管趟数 
                for (var j = 0; j <= arr.length - i - 1; j++) { // 里面的循环管 每一趟的交换次数
                    // 内部交换2个变量的值 前一个和后面一个数组元素相比较
                    if (arr[j] < arr[j + 1]) {
                        var temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }

                }
            }
        }

这样就利用for循环实现了排序