参加百度前端的课程真的是好多知识点不知道。边学边作题,在问题中学习,知识点从点到面,可是要善于总结记录才行。加油吧,骚年!javascript
时间复杂度是衡量一个算法效率的基本方法
咱们把它记做:O(n)
html
大白话介绍:比较相邻的两个数,若是后面的比前面的小,把小的放在前面。
时间复杂度: O(n2)
动画演示:冒泡算法
实际代码:前端
(优化算法:若是数组已是有序了,就不必再比较了): var arr=[5,3,2,4,1,0]; function bubbleSort(arr){ var flag = false; // 定义一个变量为false,未交换位置 for(var i=0;i<arr.length-1;i++){ for(var j=0;j<arr.length-1;j++){ if(arr[j+1]<arr[j]){ temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; flag = true; //true,已交换位置 } } if(flag){ flag = false; //若是交换了位置,将flag从新设为false }else{ break; //若是未交换,则跳出循环 } } return arr; } document.write(bubbleSort(arr)); //0,1,2,3,4,5
优化方法设置一个中断标志位,在条件测试中若是发生了交换就将中断位屏蔽,而后在外层循环中检查中断位,若是中断位没有被屏蔽,将结束循环。每次开始内层循环以前重置中断位。这样就能够在已是正序排列时不继续进行循环,达到最优的复杂度.java
计算时间复杂度主要是看这几个指标:
1 input size(输入)linux
2 basic operation/most costly operation(基本操做)
3 determine average cases(决定最坏和平均的时间)
4 sove it(计算)
在冒泡排序中的核心部分是
for(i=0;i<n-1;i++)
for(j=0;j<n-1-i;j++)
if(a[j+1]<a[j]) swap(a[j],a[j+1]);web
根据上面的步骤
1 size = n
2 basic operation = key comparison(比较)
由于比较是每次都要作的,而交换不必定每次都要作
3 average case = worst case
4 solve it
就是计算一共进行多少次比较这里就是用数学里的求和公式sigma求出来
最内层循环key comparison的次数是从0到n-i-1,外层循环i从0到n-1
因此总数是对(n-1-i)求和,i从0到n-1
(n-1)*n - (1+2+3+4+…+n-1)= n(n-1)/2 = O(n^2)
因此时间复杂度是n的平方算法
大白话介绍:先从原始数组中选择一个最小的数据,和第一个位置1的数据交换。再从剩下的n-1个数据中选择次小的数据,将其和第二个位置的数据交换。不断重复,知道最后两个数据完成交换。能够很清楚的发现,选择排序是固定位置,找元素.
时间复杂度:O(n2)
动画演示:选择排序
实际代码:数组
var arr=[5,3,2,4,1,0]; function selectionSort(array){ var min,temp; for(var i=0; i<array.length-1; i++){ min=i; for(var j=i+1; j<array.length; j++){ if(array[j]<array[min]){ min=j; } } swap(array,min,i); } return array; }//选择排序 function swap(array,i,j){ var temp =array[i]; array[i]=array[j]; array[j]=temp; }//两个数字交换 document.write(selectionSort(arr)); //0,1,2,3,4,5
分析:
从选择排序的思想或者是上面的代码中,咱们都不难看出,寻找最小的元素须要一个循环的过程,而排序又是须要一个循环的过程。所以显而易见,这个算法的时间复杂度也是O(n*n)的。这就意味值在n比较小的状况下,算法能够保证必定的速度,当n足够大时,算法的效率会下降。而且随着n的增大,算法的时间增加很快。所以使用时须要特别注意。性能
也是在实际中最经常使用的一种排序算法,速度快,效率高。就像名字同样,快速排序是最优秀的一种排序算法。
大白话:学习
(1)在数据集之中,选择一个元素做为"基准"(pivot)。
(2)全部小于"基准"的元素,都移到"基准"的左边;全部大于"基准"的元素,都移到"基准"的右边。
(3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到全部子集只剩下一个元素为止。
代码:
var arr=[77,-33,22,32,0,2,11]; function quickSort(arr){ if(arr.length<=1){ //若是数组中只有一位数,返回数组 return arr; } var mNumIndex = Math.floor(arr.length/2); //取基准值的下标 var mNum = arr.splice([mNumIndex],1)[0]; //取基准值 var left = []; //左边数组 var right = []; //右边数组 for(var i=0;i<arr.length;i++){ if(arr[i]<mNum){ //若是数组小于基准值,放在左边数组 left.push(arr[i]); }else{ ///不然 right.push(arr[i]); } } return quickSort(left).concat([mNum],quickSort(right)); //返回左边数组+基准值+右边数组 } document.write(quickSort(arr));//-33,0,2,11,22,32,77
分析
快速排序的时间主要耗费在划分操做上,对长度为k的区间进行划分,共需k-1次关键字的比较。
最坏状况是每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录,划分的结果是基准左边的子区间为空(或右边的子区间为空),而划分所得的另外一个非空的子区间中记录数目,仅仅比划分前的无序区中记录个数减小一个。时间复杂度为O(n*n)
在最好状况下,每次划分所取的基准都是当前无序区的"中值"记录,划分的结果是基准的左、右两个无序子区间的长度大体相等。总的关键字比较次数:O(nlgn)
尽管快速排序的最坏时间为O(n2),但就平均性能而言,它是基于关键字比较的内部排序算法中速度最快者,快速排序亦所以而得名。它的平均时间复杂度为O(nlgn)。
大白话:首先对前两个数据从小到大比较。接着将第三个数据与排好的前两个数据比较,将第三个数据插入合适的位置。以此类推。(插入排序有两个循环,外循环将数组挨个移动,内循环将对外循环选中的元素及他前面的数进行比较。)
时间复杂度:O(n^2)
代码:
var arr=[5,3,2,4,1,0]; function insertSort(arr){ var temp, j; for(var i=1; i<arr.length; i++){ temp =arr[i]; j=i; while(j>0 && arr[j-1]>temp){ arr[j]=arr[j-1]; j--; } arr[j]=temp; } return arr; } document.write(insertSort(arr)); //0,1,2,3,4,5
分析
(插入排序有两个循环,外循环将数组挨个移动,内循环将对外循环选中的元素及他前面的数进行比较。)
插入排序的思路很简单,很清晰,是一种最多见最简单的排序方法,。可是能够看出,因为须要两层循环,外层循环n-1次,内层循环每次递增一次。当输入彻底从小到大有序时,只须要常数的时间,这固然是最好的状况。可是咱们不能指望输入,当输入彻底逆序时,最坏的状况就出现了,显然时间复杂度是O(n*n)的。咱们都很清楚,这个时间复杂度在排序中并不能算好的。这也是为何插入排序虽然简单,但并无被普遍应用的缘由所在。
大白话介绍: 把一个数组分为两个数组,左边排好序,右边排好序,而后合并到一块儿排序
专业性介绍: 归并排序是分治法的典型实例,指的是将两个已经排序的序列合并成一个序列的操做
时间复杂度: O(nlogn)
实际代码:
var arr=[-11,17,12,19,0,-222]; function mergeSort(arr,s,e){ if(s>e){ //起始位置大于终点位置,返回空数组 return []; }else if(s==e){ return [arr[s]]; //起始位置等于终点位置,说明数组里只有一个数字,返回只含一个数字的数组 } var mIndex = Math.floor((s+e)/2); //中间位置的Index var arrL = mergeSort(arr,s,mIndex); //将左边的数组排序 var arrR = mergeSort(arr,mIndex+1,e); //将右边的数组排序 var resultArr = []; //结果数组 while(arrL.length>0 || arrR.length>0){ //当左右两个数组都不为空时 if(arrL[0]<arrR[0]){ resultArr.push(arrL.shift()); }else{ resultArr.push(arrR.shift()); } if(arrL.length==0){ //当左边的数组为空时 resultArr = resultArr.concat(arrR); break; }else if(arrR.length==0){ resultArr = resultArr.concat(arrL); break; } } return resultArr; } document.write(mergeSort(arr,0,arr.length-1))
参考资料:
1.算法的时间复杂度
2.算法的时间复杂度分析
3.如何计算时间复杂度
4.js算法之最经常使用的排序
5.快速排序(Quicksort)的Javascript实现
6.排序算法——快速排序