数据结构排序算法演示系统_【算法与数据结构】排序算法(下)

排序(冒泡排序, 选择排序, 插入排序, 归并排序, 快速排序, 计数排序, 基数排序)算法入门---细心和耐心

  • 说起来容易做起来难
  • 拿起键盘干
  • 运行,发现写,用log调试
  • 再运行,再写,再调试
  • 再运行,再写,再调试
  • 运行,没有错!
  • 继续想更好的写法(循环)
  • 动手最重要
  • 就算你看了正确答案,你自己写也会错
  • 没有人可以帮你完成这个过程

minIndex

  • 你永远都有两种写法
  • 递归和循环
  • 目前的minIndex
  • let minIndex =(numbers)=>
    numbers.indexof(min(numbers))
    let min =(numbers)=>{
    return min(
    [numbers[0],min(numbers.slice(1))]
    )
    }
  • 缺点:看着就繁琐
  • 重写
  • let minIndex =(numbers) =>
  • let index =0
  • for(let i=1;i<numbers.length;i++){
    if(numbers[i]<numbers[index]){
    index =i
    }
    }
    return index
    }
  • 分析
  • 一目了然,一听就会,一写就错
  • 写错记得测试几次

所有的递归都可以改写成循环---这是真的

把sort改写一下

复习递归

  • let sort = (numbers) =>{
    if(numbers.length>2){
    let index =minIndex(numbers)
    let min =numbers[index]
    numbers.splice(index,1)
    return [min].concat(sort(numbers))
    }else{
    return numbers[0]<numbers[1]?numbers:
    numbers.reverse()
    }
    }
    思路不变:
    每次找到最小的数字放前面,然后i++
  • 循环
  • let sort = (numbers) =>{
    for(let i=0;i<???;i++){
    let index = minIndex(numbers)
    // index是当前最小数的下标
    // index 对应的数应该放到 i 处
    swap(numbers,index,i) //swap 还没实现
    // index i 都是 index 的意思,建议i改名
    }
    }
  • 分析
  • 怎么知道i<??? 处应该写什么
  • 提前写好 minIndex 能有效简化问题
  • 用 swap 占位有效简化问题

实现 swao

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

125c492dd5be58750145d5788d9b9e00.png

d3dfe00f8495dba5dc1baafc73a3b7cd.png
错误的实现 swap

错误的实现swap

let swap =(a,b) =>{

let temp = a
a = b
b = temp
}
swap(number[1],number[2])

你会发现,number[1]和number[2]的值原封不动
因为 a b 是简单类型,传参时候会复制
而正常的 numbers是对象,传参复制地址传值 v.s 传址

  • 循环
  • let sort = (numbers) =>{ for(let i=0;i<???;i++){
    let index = minIndex(numbers)
    // index是当前最小数的下标
    // index 对应的数应该放到 i 处
    swap(numbers,index,i)//swap 还没实现
    // index i 都是 index 的意思,建议i改名
    } }
  • 分析
  • 怎么知道i<??? 处应该写什么
  • 分析代码
    let sort =(numbers) =>{
    for let (i=0; i<???;i++){
    let index =minIndex(numbers)
    swap(number,index,i)
    }
    }
  • 假设 numbers 的长度为n

3bb2e54f45c4da0737b5c3f16f99058f.png
  • 发现了问题
  • minIndex 查找范围有问题
  • let index =minIndex(numbers)
    这句话有问题,如果上次循环已经找到了第一个最小的数字,那么之后找到最小数字的时候,就可以忽略第一个
  • let index = minIndex(numbers.slice(i))+i

0aba41ccef489063f1acce2c6a8a1c9b.png
  • 为什么要+i
  • 如果不加,那么index总是从0数起

e41ff88fc5cde5ddb76c8047405a3856.png

a2fa6d19ea1c1707ce1c8123db51e452.png

230581ff8e579f48c100f75f9a7d3a9f.png

总结

  • 所有递归都能改成循环
  • 循环的时候有很多细节
  • 这些细节很难想清楚
  • 要手动练出表格找规律
  • 尤其是边界条件很难确定
  • 我们没有处理长度为0和1的数组
  • 如果debug
  • 学会看控制台
  • 学会打log
  • 打log的时候注意加标记

选择排序搞定每次选择最小/大的,选完就排完

快速排序

  • 以某某为基准
  • 相信你是一个体育委员
  • 你面对的同学为[12,3,,7,21,5,94,6]
  • [以某某为基准,小的去前面,大的去后面]
  • 你只需要重复说这句话,就能排序

d4fc8ea10614a3a04685eb82e7059565.png

958367625f3a2e1a9bdad98e83fa3426.png

ae139889b337f4cae6da4a5f6bba9183.png

递归思路

  • 不易某某为基准
  • 想象你是一个体育委员
  • 你对面的同学[12,3,7,21,5,94,6]
  • 然后把左右两边合并(merge)起来

571942f20fcf76fb89a63f111315b369.png

0f39c8a6964ca71fd7c9afe5c86bc419.png
merge

01dcfc5b693583a808550b5d4b6ad229.png

c1c1ee9ed5a61eaf94663ba227fa732f.png

计数排序

  • 思路
  • 用一个哈希表记录
  • 发现数字n就记N:1,如果再发现N就加1
  • 最后把哈希表的key全部打出来,假设n:m,那么n需要打印m次
  • 画图演示

81cbc1b91f8ee915e32abdbeeac17dab.png

566affc68056ca6df5d8c91e580096f8.png

b4feee08377f211fee0b03e61df5c666.png
12出现了两次就要push两次

计数排序的特点

  • 数据结构不同
  • 使用了额外的hashTable
  • 只遍历数组一遍(不过还要遍历一次hashTable)
  • 这叫做[空间换时间]
  • 时间复杂对比度
  • 选择排序o(n^2)
  • 快速排序o(n log2n)
  • 归并排序o(n log2n)
  • 计数排序o(n+max )

算法学习总结

  • 心法
  • 战略上藐视敌人,战术上重视敌人
  • 特点
  • 思路都很简单
  • 细节很多
  • 多画图表,多log
  • 如果实在不想陷入js细节,可以用伪代码

还有哪些排序算法:

  • 冒泡排序
  • 插入排序
  • 希尔排序
  • 基数排序
排序(冒泡排序, 选择排序, 插入排序, 归并排序, 快速排序, 计数排序, 基数排序)​visualgo.net
c21960fd3d9ef0af8365810f7cd24008.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值