5-2 算法与数据结构(找最小值、选择排序的递归写法) 算法入门1.如何找到两个数中较小的数字数据结构用数组[a,b]表示两个数字编程知识问号冒号表达式 ?:代码letminOf2numbers//定义numbers是一个长度为2的数组numbers[0]numbers[1]?numbers[0]:numbers[1]代码优化析构赋值将结构拆开分开赋值直接将数组放入括号中数组第一项命名为a第二项命名为bletminOf2([a,b])ab?a:b调用minOf([1,2])minOf.call(null,[1,2])推荐这个第一个参数是this没有就写null算法就是把你解决问题的思路表示出来1.1 现成API函数JS内置了Math.minMath.min(1,2)接收两个数字Math.min.call(null,1,2)不用thiscall调用法Math.min.apply(null,[1,2])和call的唯一区别就是后面是数组注意如果call后面加数组则是把数组当成了一项整体来看而apply是分开来看关于Math看起来像Object一样的构造函数实际上Math只是一个普通对象这是唯一的特例首字母大写是构造函数1.2 三个数字找出最小的那个代码调用两次minOf注意不是递归因为minOf3调用的是minOf2不是自身letminOf3([a,b,c]){returnminOf([minOf2([a,b]),c])}或者letminOf3([a,b,c]){returnminOf([a,minOf2([b,c])])//推荐这种结构看起来更美观}推理任意长度数组求最小值都可以通过minOf2实现letminOf4([a,b,c,d]){returnminOf([a,minOf3([b,c,d])])//推荐这种结构看起来更美观}1.3 推广求任意长度数组的最小值代码自己调用自己这就是递归letmin(numbers){if(numbers.length2){returnmin([numbers[0],min(numbers.slice(1))]//slice把第一个单独拿出来和后面的一堆求最小值)}else{returnMath.min.apply(null,numbers)//apply是把后面的数组展开}}1.4 递归特点1.函数不停调用自己每次调用的参数略有不同每次min时形式完全一样但参数不一样2.当满足某个简单条件时则实现一个简单的调用3.最终算出结果理解可以用代入法快速理解递归可以用调用栈快速理解递归进入下一行就是压栈每次缩回来就是弹栈2.选择排序将正整数数组从小到大排序不断选择最小的进行排序2.1思路用递归更容易写出来不能理解就用带入法用循环2.2 递归思路——选择排序长度为2的数组从小到大排序let sort2 ([a,b]) a b ? [a,b] : [b,a]长度为3的数组从小到大排序letsort3([a,b,c]){letindexminIndex([a,b,c])//minIndex返回最小值的下标letminnumbers[index]numbers.splice(index,1)//从numbers里面删掉最小值return[min].concat(sort2(numbers))//两个数字连接起来}minIndex取巧代码后续会教其他的let minIndex (numbers) numbers.indexOf(min(numbers))有bug如果有两个最小值就只会返回第一个最小值的下标长度为4的数组排序letsort4(numbers){letindexminIndex(numbers)letminnumbers(index)numbers.splice(index,1)return[min].concat(sort3(numbers))}2.3 推广任意长度的数组排序letsort(numbers){if(numbers.length2){letindexminIndex(numbers)letminnumbers[index]numbers.splice(index,1)//会返回被删除的部分return[min].concat(sort(numbers))}else{returnnumbers[0]numbers[1]?numbers:numbers.revers()}}递归要用带入法3.代码会错——如何调试用console.log调试调用栈函数调用了函数前面一个函数就会被压到栈里去下图就是压栈的过程当代码运行结果出现错误就把每一步的结果用console.log打出来看哪一步结果开始不对注意括号里是反引号console.log(min:${min})