思想:
对数组循环,第一次循环,找到所有元素中的最小值,把它和下标为0的元素交换,这样,i=0位置的元素就是所有元素的最小值。
第二次循环,令i=1,因为此时i=0位置已经定死了,所以,找剩余所有元素的最小值,也就是从i=1往后的元素,找到最小值后,和i=1位置的元素交换,这样,i=1位置的元素就是第二小的。
以此类推,即,每次循环,目的是找到从i往后的剩余元素的最小值,然后把这个最小值放到当前i的位置。
细节:
- 找到最小值并且交换时,可以使用if...else,判断,如果我找到的最小值的下标和i不一样时,才交换,如果一样(i就是最小值)那就什么都不做,直接进入下一次循环。
- i循环的范围,i取到倒数第二个下标就可以。因为,把倒数第二个位置的值定好,那最后一个位置的就自动定好了。
- 每一次进入新的循环时,由于前边的位置都定好了,所以,在找最小值时,要排除前边那些值,直接从i往后的数组元素中找。
- 可以使用两个子函数,swap()交换两个下标处的元素。minIndex()返回数组中最小值的下标。
let swap=(array,i,j) =>{
let temp=array[i]
array[i]=array[j]
array[j]=temp
} //数组做形参,在传实参时是复制数组的地址,在函数中做的操作也会改变实参。
let minIndex=numbers =>{
let minindex=0
for(let i=1;i<numbers.length;i++){
if (numbers[i]<numbers[minindex]){
minindex=i
}
}
return minindex
}
let sort=numbers =>{
for (let i=0;i<numbers.length-1;i++){
let min_index=minIndex(numbers.slice(i))+i
if (i!==min_index){
swap(numbers,i,min_index)
}
}
return numbers
}
下边是不用子函数的代码:
let sort=numbers =>{
for(let i=0;i<numbers.length-1;i++){
temp=numbers.slice(i)
let min=0
for(let j=1;j<temp.length;j++){
if (temp[j]<temp[min]){
min=j
}
}
min=min+i //找到从i往后所有元素的最小值的下标min
if(i!==min){
temp2=numbers[i]
numbers[i]=numbers[min]
numbers[min]=temp2
} //如果min和当前等着被放元素的位置i不一样,就交换
}
return numbers
}
以前学排序算法的时候总是很懵,可能是因为没有写子函数的原因吧。。。所以写的乱七八糟的。用了两个子函数之后,代码就很清晰易懂了。
每次循环就做两件事情:
-
找到从i往后元素的最小值的下标,记为min
-
交换min和i处的元素
第一步就可以抽象出一个函数,找任意长度的数组中的最小值下标。
时间复杂度:n*n