插入排序的新视角

很久以前就实现过插入排序,基本是照着书上的标准过程实现的。这个算法的思想也很简单。以从小到大排序为例,就是从第一个元素开始,往后依次选择一个元素插入到合适的位置。算法时间复杂度为 O ( N 2 ) O(N^2) O(N2)

例如排序这几个数字: 3 → 2 → 1 → 5 → 4 3 \rightarrow 2 \rightarrow 1 \rightarrow 5 \rightarrow 4 32154
首先选择3,确定其位置 : 3 → 3 \rightarrow 3
然后选择2,确定其位置,因为2比3小,所以应该放在3的前面: 2 → 3 → 2 \rightarrow 3 \rightarrow 23
然后选择1,确定其位置,因为1比2小,所以应该放在2的前面: 1 → 2 → 3 → 1 \rightarrow 2 \rightarrow 3 \rightarrow 123
然后选择5,确定其位置,因为5比3大,所以应该放在3的后面: 1 → 2 → 3 → 5 → 1 \rightarrow 2 \rightarrow 3 \rightarrow 5 \rightarrow 1235
然后选择4,确定其位置,因为4比5小,比3大,所以应该放在3和5之间,5往后挪一个位置,得到: 1 → 2 → 3 → 4 → 5 1 \rightarrow 2 \rightarrow 3 \rightarrow 4 \rightarrow 5 12345

实现代码:

function insertSort(numbers){
    for(let i = 0; i < numbers.length; i++){
        for(let j = 0; j < i; j ++){
            // 如果找到一个比当前数字numbers[i]大的数字numbers[j],则:
            // 1. 备份numbers[i]
            // 2. 先j之后数字的往后移动一个位置
            // 3. 把当前数学放到刚刚腾出的位置上
            if(numbers[i] < numbers[j]){
                let backup = numbers[i];
                for(let k = i; k > j; k--){
                    numbers[k] = numbers[k - 1];
                }
                numbers[j] = backup;
                break;
            }
        }
    }
}

今天上了卜东波的算法课,知道了原来从分治的角度来理解更加合适。对一个长度为 n n n的数组排序问题变成了先对前面长度为 n − 1 n-1 n1部分排序再确定最后一个元素位置的问题。实际上就是变成了递归的写法。代码如下。这种写法仅用于理解,实际使用会因为递归深度太大而导致栈溢出从而不能在实际项目使用。

/**
 * 插入排序
 * @param {Array} numbers 数组
 * @param {number} start  排序开始位置
 * @param {number} end  排序结束位置的下一位
 */
function insertSort(numbers, start, end){
    if(start < end){
        // 先把前面的排好
        insertSort(numbers, start, end - 1);
        // 再确定最后一个元素的位置
        for(let j = start; j < end - 1; j++){
            // 如果找到一个比当前数字numbers[end - 1]大的数字numbers[j],则:
            // 1. 备份numbers[end - 1]
            // 2. 先j之后数字的往后移动一个位置
            // 3. 把当前数学放到刚刚腾出的位置上
            let current = numbers[end - 1];
            if(current < numbers[j]){
                for(let k = end - 1; k > j; k--){
                    numbers[k] = numbers[k - 1];
                }
                numbers[j] = current;
            	break;
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值