教朋友学算法-Js快速排序

152 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情
背景引入:我有个朋友,自认为掌握了快速排序,可每次写的时候都会有一点小瑕疵。我看的出来,他很困扰啊。我作为他的好兄弟、正义的伙伴自然是见不得朋友烦恼的。这一次我要让他再也不会写错快速排序。

算法思想

  • 快排的核心是确认一个基准点(通常是数组的第一个)。
  • 将数组中小于基准点的数放到基准点(下文用flag表示)的左边。大于flag的数放到右边。
  • 这时候我们有了两个新的数组,即 小于基准点的数组 和 大于基准点的数组
  • 对这两个数组重复前两步的操作,如此递归下去,直到数组长度 <= 1
  • (我兄弟很聪明哇,我一说他就懂了。我好有面子嘻嘻)

给朋友展示了一下代码
show code

//解法1
let quick_sort = function (nums, start, end){
    if(start >= end) return          //递归结束的条件
    let left = start, right = end
    let flag = nums[start]          //确认基准点
    while(left < right){
        while(nums[right] >= flag && left < right){   //数组从后往前查找小于flag的位置
            right --
        }
        while(nums[left] <= flag && left < right){    //数组从前往后查找大于flag的位置
            left ++
        }
        if(left < right){          //一定需要对left和right的大小进行判断
            [nums[left], nums[right]] = [nums[right], nums[left]]  //交换位置
        }
    }
    nums[start] = nums[left]     //将第一个点的值和循环结束的位置的值进行交换
    nums[left] = flag            //循环结束的位置放入flag
    quick_sort(nums, left + 1, end) 
    quick_sort(nums, start , left - 1)
}

如果只是单单展示了算法,我并不觉得我那位朋友可以掌握下来
于是我给朋友总结了几点:

  1. 注意递归结束的条件
  2. 时刻注意left < right, 重要的事情要注意三次
  3. 退出循环时即(left == start时) left的值放到start的位置上,flag的值放到left。
    此时flag左边的值就都是小于它的,右边都是大于它的

复杂度:提一嘴,快排的平均时间复杂度O(nlogn)

快排不难理解,但是刚开始写可能会比较难写。朋友回去练了几遍后跟我说:“快排也不过如此”
感谢观看到这里。如果这篇文章让你觉得快排不过如此的话,点个小小的赞吧。
兄弟每次都给我点赞,我很有面子