minIndex 循环写法
let minIndex = (numbers) =>{
let index = 0;
for(let i = 1; i<numbers.length; i++){
if(numbers[i]< numbers[index]){
index = i
}
}
return index
}
每个数和下标[0]的数比,比下标[0]小的就记录下来为新的最小的数
选择排序 sort
循环写法思路
1)找到当前最小数的下标
2)最小数的下标和当前下标的数交换位置
3)swap(换位) JS析构赋值,可以交换数组的位置
let sort = (numbers) => {
for(let i=0; i< numbers.length -1; i++){
let index = minIndex(numbers.slice(i))+ i
if(index!==i){swap(numbers, index, i)}
}
return numbers
}
let swap = (array, i, j) => {
let temp = array[i]
array[i] = array[j]
array[j] = temp
}
let minIndex = (numbers) => {
let index = 0
for(let i=1; i<numbers.length; i++){
if(numbers[i] < numbers[index]){
index = i
}
}
return index
}
选择排序,每次选最小或最大的,选完就排完
所有的递归都能写成循环,循环的边界条件不好确定,边界是length还是length-1
快速排序 quickSort
递归思路,以某某为基准
数组[12,3,7,21,5,9,4,6]
以21为基准,比它小的去左面,大的去右面;只需要重复这句话,就完成排序
let quickSort = arr =>{
if(arr.length<=1){
return arr;
}
let pivotIndex = Math.floor(arr.length/2);
let pivot = arr.splice(pivotIndex,1)[0];
let left =[];
let right = [];
for(let i=0; i<arr.length; i++){
if(arr[i]<pivot){
left.push(arr[i])
}else{
right.push(arr[i])
}
}
return quickSort(left).concat([pivot],quickSort(right))
}
quickSort快速排序,接收一个数组
如果这个数组长度小于1,直接返回这个数组
pivotIndex基准的索引,等于数组的长度除以2
floor地板(7除以2等于3.5,地板是3向下去最近的整数)
pivot把基准单独拿出来,删除1项,返回删除的项是一个数组,加[0]会把第0项单独返回,不是数组
声明2个空数组,左边和右边
遍历删除基准之后的数组
如果arr[i]小于基准,把它放到左边数组,否则放在右边数组
左边进行快速排序concat(连接)基准,右边进行快速排序
归并排序 mergeSort
递归思路:不以某某为基准
数组[12,3,7,21,5,9,4,6]
左边一半排好序,右边一半排好序,然后把两边合并起来,就完成排序
把数组分成单个数字的数组,然后把每个数组合起来,就排好序了,因为单个数组默认是排好序的
let mergeSort = arr =>{
let k = arr.length
if(k === 1){
return ar
}
let left = arr.slice(0,Math.floor(k/2)
let right = arr.slice(Math.floor(k/2)
return merge(mergeSort(left),mergeSort(right))
}
let merge = (a,b) =>{
if(a.length === 0) return b
if(b.length === 0) return a
return a[0] > b[0] ?
[b[0]].concat(merge(a,b.slice(1))) :
[a[0]].concat(merge(a.slice(1),b))
}
mergeSort接收一个数组
k等于数组的长度
如果k等于1,直接返回这个数组
左边等于arr.slice(0,Math.floor(k/2))从arr的第0项开始,到2分之1
右边等于数组的另外2分之1
左边进行当前操作,右边进行当前操作,把数组分成单个数字的数组
左边排好序,右边排好序(实际上通过length=1,让数组变成单个数组,假装排好序,然后进行合并)
merge接收2个数组(a,b)(对每一项进行对比大小)
如果a的长度为0,数组为空,返回b
如果b的长度为0,数组为空,返回a
找出a,b数组中谁的第一位最小,如果a[0]>b[0],b[0]最小
那么就用b[0] 连接 a和b的其它部分的merge
a小的话,就a[0]连接 a除了0的其它部分,加数组b的merge
计数排序 countSort
思路:用一个哈希表做记录
发现数字N,就记做N:1,如果再次发现N就加1
最后把哈希表的key全部打出来,假设N:M,那么N就打印M次
let countSort = arr =>{
let hashTable = {}, max = 0, result = []
for(let i = 0; i<arr.length; i++){
if(!(arr[i] in hashTable)){
hashTable[arr[i]] = 1
}else{
hashTable[arr[i]] += 1
}
if(arr[i] > max){
max = arr[i]
}
}
for(let j=0; j<max; j++){
if(j in hashTable){
for(let i=0; i<hashTable[j]; i++){
result.push(j)
}
}
}
return result
}
计数排序函数,接收一个数组
声明一个哈希表为空{},最大值为0,result为空数组
遍历数组
如果i不在哈希表里(!不在)
哈希表的第i个数=1
在进入一次数组,如果arr[i]在哈希表里,arr[i]=i+1
如果i>max,max等于i(记录最大的数,收集max)
遍历哈希表
如果j在哈希表里,就把j放到result里,返回result
如果j出现2次,在遍历一遍哈希表,拿到j的value,j的值是几,就push几次
计数排序特点,使用了额外的数据结构hashTable,只遍历一遍数组,不过还要遍历一遍hashTable
用空间换时间