记录一下三种排序方法:冒泡、插排、快排

记录一下三种排序方法。

一、冒泡排序

想象下水里的气泡,小的泡泡在下面,大的泡泡在上面。若给定nums数组使其从小到大排序,冒泡的关键点在于,相邻的两个元素 nums[ j ] 和 nums[ j + 1] 比较,需要把大的往后放。

冒泡排序代码:

/**
 * 冒泡排序,从小到大
 * @param {Array} ary 要排序的数组
 * @return {Array} 排序后的数组
 */
function buble(ary){
    // 外层循环,表示比较多少轮,每轮找出一个最大的数,当找出length-1个最大的数时就排完了
    for(let i=0; i<ary.length-1; i++){
        // 内层循环,表示剩余的数需要比较多少次
        // 第一轮(i=0)还没比,找出了0个最大的数,需要比较 length-1-0 次
        // 第二轮(i=1),找出了1个最大的数,需要比较 length-1-1 次
        // 第i+1轮(i),找出了i个最大的数,需要比较 length-1-i 次
        for(let j=0; j<ary.length-1 -i; j++){
            // 如果ary[j]大于ary[j+1],交换
            if(ary[j]>ary[j+1]){
                [ary[j], ary[j+1]] = [ary[j+1], ary[j]]
            }
        }
    }
    return ary
}

效果图示:

冒泡排序效果图示

二、插入排序

想象抓扑克牌,准备一个空的左手,抓第一张牌,以后抓的每张牌,从后往前插入。抓到的 牌A 和 手中的 牌B 比较,插入规则是:,若A比B大,则将A插入到B后并停止比较;若A比B小,则再往前找,当还是比第一张牌小时,则插入到最前面。

插入排序代码:

/**
 * 插入排序,从小到大
 * @param {Array} ary 要排序的数组
 * @return {Array} 排序后的数组
 */
 function insert(ary){
    // 准备的左手,并先插入第一张牌
    let handle = [ary[0]]
    // 循环剩下的牌,设其为抓到的牌A
    for(let i=1; i<ary.length; i++){
        let A = ary[i]
        // 循环手中的牌,从后往前插,设其为手中的牌B
        for(let j=handle.length-1; j>=0; j--){
            let B = handle[j]
            // 若A大于B,则插入到B的后面
            if(A>B){
                handle.splice(j+1, 0, A) // splice方法是插入到j+1的前面,即B索引位置j的后面
                break // 找到插入位置了,需要结束往前插入
            }
            // 若比第一个元素都小,则插入到最前面
            if(j==0){
                handle.unshift(A) // 此时使用,handle.splice(0, 0, A)也可以实现相同效果
            }
        }
    }
    return handle
}

效果图示:

快速排序效果图示

三、快速排序

需要用到递归,递归就是在函数中自己调用自己。

一个简单的递归例子:

// 求1-10的和,最简单的方式是写个循环,也可以使用递归
function fn(n){
    if(n>10) return 0
    return n + fn(n+1)
    // 1+fn(2)
    // 1+2+fn(3)
    // 1+2+3+fn(4)
    // 1+2+3+4+5+6+7+8+9+10+fn(11)
    // 1+2+3+4+5+6+7+8+9+10+0
}
fn(1)

快速排序代码:

/**
 * 快速排序,从小到大
 * @param {Array} ary 要排序的数组
 * @return {Array} 排序后的数组
 */
 function quick(ary){
    // 4.递归终止条件:当数组没有元素或者只有一个元素时,就没必要再排序了
    if(ary.length<=1){
        return ary
    }

    // 1.先挑出中间位置的元素,并从原来数组中删除
    let middleIndex = Math.floor(ary.length/2)
    let middleValue = ary.splice(middleIndex, 1)[0]
    // 2.准备左右两个新数组,循环原数组,比中间元素小的放左边数组,比中间元素大的放右边数组
    let leftAry = [], rightAry = []
    for(let i=0; i<ary.length; i++){
        let item = ary[i]
        if(item<middleValue){
            leftAry.push(item)
        }else{
            rightAry.push(item)
        }
    }
    // 3.递归对左右两个数组排序,将结果拼接成:左边数组+中间元素+右边数组,并返回
    return quick(leftAry).concat(middleValue, quick(rightAry))
}

效果图示:

快速排序效果图示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值