排序算法(上)

算法里面最简单的就是排序算法,这节课主要讲选择排序。
算法入门:四种排序算法(选择、归并、快速、技术)和对应的结构。

实现minOf2:2个数找出较小的那个
[图片上传失败...(image-257150-1652091073113)]

再优化

析构赋值:把结构拆开,依次复制
let minOf2=([a,b]) => a < b ? a : b 
//调用
minOf2([1,2]) //小白调用法
minOf2.call(null,[1,2]) //高手调用法

现成API
JS内置了Math.min
Math.min(1,2)
Math.min.call(null,1,2)
Math.min.apply(null,[1,2])
关于Math
看起来Math像Object一样是构造函数
实际上Math只是普通对象,唯一一个首字母大写的对象,对象一般首字母小写

实现minOf3:3个数找出最小的那个
[图片上传失败...(image-937285-1652091073113)]

推广,任意长度数组求最小值
[图片上传失败...(image-f37544-1652091073113)]

递归
特点
函数不停调用自己,每次调用的参数略有不同
当满足某个简单条件时,则实现一个简单的调用
最终算出结果
理解
可以用代入法快速理解递归
可以用调用栈快速理解递归
[图片上传失败...(image-ca9d77-1652091073113)]

解析 代入法,先递进后回归
[图片上传失败...(image-f898cb-1652091073113)]

知识点
1.numbers.slice(1) 选中从下标1开始的所有数据
2.Math.min.apply(null,numbers)
apply就是把numbers一个个展开调用。call就是把numbers作为一项。

var arr = [1,3,6,8,2,10];
var minNum = Math.min.apply(null,arr);
console.log(minNum);  //1

Math.min 可以实现得到数组中最小的一项
Math.min.apply(null,arr)其中第一个参数null,这个是因为没有对象去调用这个方法,所以直接传递null过去。同理,Math.max.apply可以获得数组里面最大的值。

实现sort排序(将正整数数组从小到大排序)

排序算法
思路: 1'用递归实现、2'用循环实现

递归思路

选择排序
例1.将长度为2的数组排序
[图片上传失败...(image-506564-1652091073113)]

例2.将长度为3的数组排序
思路:先求最小值,把最小值放前面。
然后将后面2个数字进行"2个数的排序"。
[图片上传失败...(image-307739-1652091073113)]

let minIndex = (numbers) => numbers.indexOf(min(numbers)) 
//取巧:如果有2个最小数,只会返回第1个最小数的下标。

let sort3 = (numbers) => {
//获取最小数字的下标
  let index = minIndex(numbers) //minIndex函数
  let min = numbers[index]
//获取最小数下标后再将其删掉,返回被保留的数字
  numbers.splice(index, 1) 
  return [min].concat(sort2(numders))
}

知识点
1.JS中concat用于2个数组的相加,拼成一个数组
2.sort2(numders)得到的是排好序的2个数
3.numbers.indexOf求出某个数字的下标

例3.将长度为4的数组排序
[图片上传失败...(image-8d82f5-1652091073113)]

推广,任意长度的数组排序
死循环,到2个数时不会断。

[图片上传失败...(image-912c9a-1652091073113)]
[图片上传失败...(image-5c265e-1652091073113)]
要理解递归,必须用代入法

选择排序:每次找到最小的数放前面,然后对后面的数做同样的事情。

例子:假设我没理解splice,于是我写了rest,实际上splice会返回被删除部分而不是被余下部分。

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

分析报错
当前代码属于匿名的函数,调用了sort,sort调用了minIndex,minIndex调用了min,并发现min不存在。
这个就叫做调用栈,函数调了函数,前面的函数就要压到栈里面。
它说没有定义那就一定没有定义,找原因。
1.<anonymous>,当前代码属于匿名的函数
2.at sort,调用了sort
[图片上传失败...(image-d2568c-1652091073113)]

结果不符合预期,把每一步的结果打出来
[图片上传失败...(image-7896b9-1652091073113)]

推断出rest有问题
那怎么拿到剩余的数呢?
[图片上传失败...(image-dbef1e-1652091073113)]

总结
1.求最小值: 2个数、3个数、N个数
2.排序: 2个数、3个数、N个数
用到的东西: 数组(数据结构)、递归
1.请写一个min函数,要求min(numbers)能返回数组numbers中的最小数字。

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

2.请写出一个sort函数,要求sort(numbers)能返回一个把numbers 从小到大排列的数组

let minIndex = (numbers) => numbers.indexOf(min(numbers))
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()
  }
}
sort([21,8,44,92])
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容