作为一名程序员,算法是一个没法回避的话题,因为它可以说是专业与不专业的一条分界线。想要在未来有更高的技术造诣,学会数据结构算法知识是必须的。互联网技术发展到今天,已经有很多算法了,而排序算法算是最好的入门算法,因为它比较简单,而且能让你迅速了解计算机的计算思维方式。学习了常用排序算法之后,我决定做个总结。
0.算法的特性
输入:一个算法必须有零个或以上输入量。
输出:一个算法应有一个或以上输出量。
明确性:算法的描叙必须无歧义,实际运行结果是确定的
有限性:必须在有限个步骤内结束
有效性: 又称可行性,能够被执行者实现
————高德纳《计算机程序设计艺术》
算法的学习最重要的是学会计算机的思维方式,这是精髓也是难点。
- 当你遇到思路障碍怎么办?
- 将抽象的问题转化为具体的问题
- 将没见过的问题转化为见过的问题
本人的学习方法是先用伪代码实现或者画流程图梳理一遍思路,再用JS实现具体细节。
算法流程图.jpg1. 冒泡算法(BUBBLE)
冒泡算法用通俗一点的话说,可以理解为“一个教官(计算机)伸出双手,从头开始,按顺序依次选择两个人排列站位”。
专业的理解应该是,计算机遍历整个数组,每次选择两个数进行排序,小的放前面大的往后放,重复这个步骤直到不再需要交换了,也就是说数组已经排列完成。每比较一轮,都会选出最大的一个放到当前排列数组的最后。
1.首选选中两个数,准备进行比较
冒泡1.PNG2. 7>3,所以7往后放,再往后选择7和30比较
冒泡2.PNG3. 以此类推比较完第一轮,最大的40被放到了最后
冒泡3.PNG
4. 重复进行前三个步骤,最后就会得到一组从小到大排列的数组。
冒泡4.PNG
实现代码
function sort(array){
for(i=0;i<array.length;i++){
for(j=0;j<array.length-1;j++){
if(array[j]<=array[j+1]){
}else{
swap(array,j,j+1)
}
}
}
return array
}
function swap(array,a,b){
var temp=array[a]
array[a]=array[b]
array[b]=temp
}
console.log(sort([3,5,2,21,1]))
console.log(sort([1,3,3,1,1]))
console.log(sort([1]))
console.log(sort([]))
2选择排序(SELECT)
选择排序可以通俗理解为第一个人指着后面的人说,你们中最小的站在我前面来。
专业的理解:每一次标记待排序数据元素的第一个元素为被比较元素,然后往后遍历,选出最小的存放在序列的起始位置,直到全部待排序的数据元素排完。每一轮遍历完,都会选出当前数组里最小的放在最前面。
-
标记第一个元素,拿后面的元素与它比较
选择1.PNG2. 选出了当前待排数组里最小的元素
选择2.PNG 3. 将最初标记的元素与最小元素交换位置,一轮遍历结束。下一轮标记21。
选择3.PNG4. 重复以上步骤,经过多轮比较得到一组从小到大排列的数组。
选择4.PNG
实现代码
function sort(array) {
var indexofMin,i,j
for(i=0;i<array.length;i++){
indexofMin=i
for(j=i+1;j<array.length;j++){
if(array[j]<array[indexofMin]){
indexofMin=j
}if(indexofMin!==i){
swap(array,i,indexofMin)
}
}
}
return array
}
function swap(array,a,b){
var temp=array[a]
array[a]=array[b]
array[b]=temp
}
console.log(sort([3,5,2,21,1]))
console.log(sort([1,3,3,1,1]))
console.log(sort([1]))
console.log(sort([]))
3. 插入排序(INSERT)
插入排序通俗理解:“起牌算法”,和打扑克牌时起牌方法基本一样。我们手里已经有一副牌,然后选择一张牌找到它应该放的位置,放入,这样就能将一张张牌都放到正确的位置了。
专业理解:将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序。是稳定的排序方法。
-
第一轮标记48,往前看14与48比较
插入1.PNG2. ,48>14,不需要变换位置
插入2.PNG 3.第二轮标记25,往前看与25比较
插入3.PNG4.48>25,把它们俩换位置,25继续与前面的14比较
插入4.PNG 5. 25>14,不用交换,此时25在前两个元素中应该放的位置已经确定,放入此位置。第三轮标记24
插入5.PNG 6. 24分别与前三个元素比较,比25和48小,所以预备放在它们之前
插入6.PNG 7. 25与剩下的14比较,大于14,所以确定最终位置之后,插入。
插入7.PNG 8. 重复以上步骤,经过多轮比较得到一组从小到大排列的数组。
插入8.PNG
实现代码
var numbers = [21,34,1,3,53,2]
var temp,i,j
for(i=1;i<numbers.length;i++){
temp=numbers[i]
for(j=i-1;j>=0&&temp<numbers[j];j--){
numbers[j+1]=numbers[j]
}
numbers[j+1]=temp
}
console.log(numbers)
快速排序(QUICK)
快速排序,它又称为自私算法,它优先让每个元素找到自己所在的位置,每次排序都实现“比我大的都在我右边,比我小的都在我左边”而不去计较它们的位置关系。
-
第一轮选择第一个元素,然后依次拿后面的元素与它比较
快速1.PNG2. 在比较的过程中,将后面的元素分成两部分放置,比34大的放一边,比34小的放另一边
快速2.PNG 3. 都比较完之后,将34放到中间
快速3.PNG4. 第二轮选择11
快速4.PNG 5. 将34之前的元素与11进行比较,然后重复比较步骤,把11放到它的位置
快速6.PNG 6. 重复以上步骤,经过多轮比较得到一组从小到大排列的数组。
快速7.PNG
实现代码
function sort(array){
if(array.length<=1){
return array;
}
var len = Math.floor(array.length/2);
var cur = array.splice(len,1);
var left = [];
var right = [];
for(var i=0;i<array.length;i++){
if(cur>array[i]){
left.push(array[i]);
}else{
right.push(array[i]);
}
}
return sort(left).concat(cur,sort(right));
}
时间复杂度
- 选择排序、冒泡排序和插入
n+(n-1)+(n-2)+(n-3)···=n^2
- 快速排序
nlog2n
- 快速排序有个缺点,如果给定的数组是已经排好的或者是反序的就不能造成达到快速的目的了,那么此时它的时间复杂度跟前三种一样。解决方案是使用随机快速排序,即
不从第一个开始标记
。
其它排序
除了以上几种排序之外,还有归并排序(MERGE)、统计排序(COUNT)、基数排序(RADIX)等。了解详情请点击:[visualgo]
网友评论