前端排序算法彙總

冒泡排序

冒泡排序的原理如下,從第一個元素開始,把當前元素和下一個索引元素進行比較。如果當前元素大,那麼就交換位置,重複操作直到比較到最後一個元素,那麼此時最後一個元素就是該數組中最大的數。下一輪重複以上操作,但是此時最後一個元素已經是最大數了,所以不需要再比較最後一個元素,只需要比較到 length - 1 的位置。以此類推,每一次最外層循環都會將後面的數排好序,因此裏面的循環可以減少i次循環.

冒泡排序算法時間複雜度爲O(n*n)

bubble.gif

//算法實現
function bubble(array){
   let len = array.length;
   if(len <= 0){return false;}
   for(let i = 0;i < len;i++){
       //由於後面的數已經排好序了,因此第二次沒必要再循環len次,而是len-i次
       for(let j = 0; j < len - 1 - i;j++){  
           if(array[j] > array[j+1]){
               [array[j], array[j+1]] = [array[j+1], array[j]];
           }
       }
   }
}

選擇排序

選擇排序的原理如下:先將一個值的索引設置爲最小索引minIndex,通常設置是第一個值,然後將最小索引的值與其他值進行比較,若最小索引值比其他的值要大,則將最小索引設置爲該值的下標,然後最小索引的值與該值交換。

選擇排序的時間複雜度是O(n*n)

selection.gif

function selection(array){
    let len = array.length;
    if(len <= 0){return false;}
    for(let i = 0; i < len; i++){
        let minIndex = i;
        for(let j = i + 1;j < len;j++){
            //索引的互換,minIndex可能會多次變化
            minIndex = array[j] < array[minIndex] ? j : minIndex;
        }
        //值的互換
        [array[i], array[minIndex]]  = [array[minIndex], array[i]];
    }
}

插入排序

插入排序的原理:默認第一個元素已經排好序,外層從第二個元素開始循環,裏層循環從第一個元素開始,若裏層循環滿足條件,則交換值。裏層循環將會進行多次比較

插入排序的時間複雜度爲O(n*n)

insert.gif

function insert(array){
    let len = array.length;
    if(len<=0){return false;}
    for(let i = 1; i < len; i++){
        for(let j = i - 1; j >= 0 && array[j] > array[j+1]; j--){
            [array[j], array[j+1]]  = [array[j+1], array[j]];
        }
    }
}

歸併排序

歸併排序的原理如下。遞歸的將數組兩兩分開直到最多包含兩個元素,然後將數組排序合併,最終合併爲排序好的數組。假設我有一組數組 [2,7,5,6,1,4,3],中間數索引是 3,先排序數組 [2,7,5,6] 。在這個左邊數組上,繼續拆分直到變成數組包含兩個元素(如果數組長度是奇數的話,會有一個拆分數組只包含一個元素)。然後排序數組 [2,7][5,6] ,然後再排序數組 [2,7,5,6] ,這樣左邊數組就排序完成,然後按照以上思路排序右邊數組,最後將數組 [2, 7, 5, 6][1, 3, 4] 排序。

歸併排序的時間複雜度爲O(N*logN)

guibing.gif

function sort(array){
    let len = array.length;
    if(len <=0){return;}
    mergeSort(array, 0, len - 1);
}
function mergeSort(array, left, right){
    if(left === right) {return;}
    //位運算更安全,不會溢出,相當於left+(right-left)/2
    let mid = parseInt(left + ((right - left) >> 1));
    mergeSort(array, left, mid);
    mergeSort(array, mid+1, right);
    let temp = [], i = 0, p1 = left, p2 = mid+1;
    while(p1 <= mid && p2 <= right){
        temp[i++] = array[p1] < array[p2] ? array[p1++] : array[p2++];
    }
    while(p1 <= mid){
        temp[i++] = array[p1++];
    }
    while(p2 <= right){
        temp[i++] = array[p2++];
    }
    for(let i = 0; i < temp.length; i++){
        array[left + i] = temp[i];
    }
    return array;
}

快速排序

快排的原理如下。隨機選取一個數組中的值作爲基準值,如最右側的值,從左至右取值與基準值對比大小。比基準值小的放數組左邊,大的放右邊,對比完成後將基準值和第一個比基準值大的值交換位置。然後將數組以基準值的位置分爲兩部分,繼續遞歸以上操作

快速排序的時間複雜度爲O(N*logN)

quite.gif

function quickSort(array){
     let len = array.length;
     if(len < 0){return;}
     quick(array, 0, array.length-1);
}
 function quick(array, left, right){
     let index;
     if(array.length > 1){
         index = partition(array, left, right);
         if(left < index - 1){
             quick(array, left, index - 1);
         }
         if(index < right){
             quick(array, index, right);
         }
     }
 }
function partition(array, left, right){
     let pivot = array[Math.floor((right + left) / 2)];  //選取中間的元素作爲主元
     let i = left, j = right;
     while(i <= j){
         while(array[i] < pivot){
             i++;
         }
         while(array[j] > pivot){
             j--;
         }
         if(i <= j){
             [array[i], array[j]] = [array[j], array[i]];
             i++;
             j--;
         }
     }
     return i;
 }

堆排序

堆也可以作爲一種 數據結構,通常情況下,堆被嵌入到儲存數列的排序中,並且只通過交換數字來完成排序

dui0.gif

堆排序利用了二叉堆的特性來做,二叉堆通常用數組表示,並且二叉堆是一顆完全二叉樹(所有葉節點(最底層的節點)都是從左往右順序排序,並且其他層的節點都是滿的)

dui.gif

function heapSort(array) {
   function maxHeapify(array, index, heapSize) {
       let iMax, iLeft, iRight;
       while (true) {
           iMax = index;
           iLeft = 2 * index + 1;
           iRight = 2 * (index + 1);
           if (iLeft < heapSize && array[index] < array[iLeft]) {
               iMax = iLeft;
           }
           if (iRight < heapSize && array[iMax] < array[iRight]) {
               iMax = iRight;
           }
           if (iMax !== index) {
               //swap(array, iMax, index);
               [array[iMax], array[index]] = [array[index], array[iMax]];
               index = iMax;
           } else {
               break;
           }
       }
   }
   function buildMaxHeap(array) {
       let i, iParent = Math.floor(array.length / 2) - 1;
       for (i = iParent; i >= 0; i--) {
           maxHeapify(array, i, array.length);
       }
   }
   function sort(array) {
       buildMaxHeap(array);
       for (let i = array.length - 1; i > 0; i--) {
           //swap(array, 0, i);
           [array[0], array[i]] = [array[i], array[0]];
           maxHeapify(array, 0, i);
       }
       return array;
   }
   return sort(array);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章