參加百度前端的課程真的是好多知識點不知道。邊學邊作題,在問題中學習,知識點從點到面,可是要善於總結記錄才行。加油吧,騷年!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.排序算法——快速排序