最近整理了常用的排序算法,整理好,留下自己的思考過程。
1、冒泡排序:
(1)平均時間復雜度:O(n2)
(2)最好時間復雜度:O(n)
(3)最壞時間復雜度:O(n2)
(5)空間復雜度:O(1)
(5)穩定性:穩定
(6)JavaScript實現:
function bubble ( arr ) { var len = arr.length; var tmp; // 外層循環負責控制排序的趟數 for(var i = 0; i < len - 1; i++){ // 內層循環負責進行一趟排序 for(var j = 0; j < len - 1 - i; j++){ if(arr[j + 1] < arr[j]){ tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; }; }; }; return arr; };
2、選擇排序:
(1)平均時間復雜度:O(n2)
(2)最好時間復雜度:O(n2)
(3)最壞時間復雜度:O(n2)
(4)空間復雜度:O(1)
(5)穩定性:不穩定
(6)JavaScript實現:
function select( arr ) { var len = arr.length; // 外層循環需要進行len - 1趟排序 for(var i = 0; i < len - 1; i++){ var index = i; var min = arr[i]; var tmp; // 內層循環從未排序的數組元素中比較出最小的一個 for(var j = i + 1; j < len; j++){ if(min > arr[j]){ index = j; min = arr[j]; }; }; // 將其放在排序后的數組元素的最后 tmp = arr[i]; arr[i] = min; arr[index] = tmp; }; };
3、插入排序:
(1)平均時間復雜度:O(n2)
(2)最好時間復雜度:O(n)
(3)平均時間復雜度:O(n2)
(4)空間復雜度:O(1)
(5)穩定性:穩定
(6)JavaScript實現:
function insert ( arr ) { var len = arr.length; var tmp; for(var i = 1; i < len; i++){ // 取出當前的數組元素 tmp = arr[i]; for(var j = i - 1; j >= 0; j--){ if (arr[j] > tmp) { arr[j+1] = arr[j]; } else {
break;
}; }; // 插入取出的數組元素 arr[j+1] = tmp; }; return arr; }
4、希爾排序:
(1)平均時間復雜度:O(nlogn) ~ O(n2)
(2)最好時間復雜度:O(n1.3)
(3)最壞時間復雜度:O(n2)
(4)空間復雜度:O(1)
(5)穩定性:不穩定
(6)JavaScript實現:
// 插入排序 function sort( arr, di ){ for(var i = di; i < arr.length; i++){ var guard = arr[i]; for(var j =i -di; j >= 0 && guard < arr[j]; j -= di){ arr[j+di] = arr[j]; }; arr[j+di] = guard; }; return arr; } // 希爾排序,本質上是以不同的步長多次進行插入排序 // 步長的選擇對希爾排序的效率有顯著影響 function shell ( arr ) { var di = parseInt( arr.length / 2 ); while ( di >= 1) { arr = sort( arr, di); di = parseInt( di / 2 ); }; return arr; };
5、歸並排序:
(1)平均時間復雜度:O(nlogn)
(2)最好時間復雜度:O(nlogn)
(3)最壞時間復雜度:O(nlogn)
(4)空間復雜度:O(n)
(5)穩定性:穩定
(6)JavaScript實現:
// 對被歸並的左右兩個數組進行歸並排序 // 被輸入的左右兩個數組,都是有序的。 function merge (left, right){ var l = 0, r = 0; var result = []; // 對左右兩個數組的首項,進行比較,較小的推入棧中。 while(l < left.length && r < right.length){ if(left[l] < right[r]){ result.push( left[l] ); l += 1; } else { result.push( right[r] ); r += 1; }; }; // 經過上面的比較,左右兩個數組,必定有一個數組比較完畢,一個沒有比較完畢。 // 但是,在不同情況的遞歸層,有不同的表現,故而將二者未比較的元素都連接到result中。 // 由於,左右兩個數組在輸入前就是有序的,剩余未經比較的數組元素也是有序的,且都大於之前經過比較的數組元素,故而可以將其連接到result。 // 下方的代碼,實質上是將左右數組中,未經比較的數組元素連接到result。 result = result.concat( left.slice(l) ); result = result.concat( right.slice(r) ); return result; }; function mergeSort ( arr ){ var len = arr.length; // 結束遞歸 if(len <= 1){ return arr; }; // 切割數組,並對切割后的數組進行遞歸操作 var middle = Math.floor( len/2 ); var left = mergeSort( arr.slice(0, middle) ); var right = mergeSort( arr.slice(middle) ); // 完成遞歸后,進行歸並 return merge(left, right); }
6、快速排序:
(1)平均時間復雜度:O(nlogn)
(2)最好時間復雜度:O(nlogn)
(3)最壞時間復雜度:O(n2)
(4)空間復雜度:O(logn) ~ O(n)
(5)穩定性:不穩定
(6)JavaScript實現:
function quick ( arr ) { var less = [], pivotList = [], more = [], result = [], len = arr.length; // 結束遞歸 if(len <= 1){ return arr; }; // 與基准對比,將數組划分為小,中,大三組 var pivot = arr[0]; for(var i = 0; i <len; i++){ if(arr[i] < pivot){ less.push(arr[i]); } else if(arr[i] > pivot){ more.push(arr[i]); } else { pivotList.push(arr[i]); }; }; // 遞歸地對划分出的小、大兩個組進行快速排序 less = quick(less); more = quick(more); // 將排序好的小,中,大三組連接起來 result = result.concat(less, pivotList, more); return result; }