基本算法學習之(二)快速排序與歸併排序

快速排序(Quick Sort)

看名字知特色,就是快,效率高.它是處理大數據最快的排序算法之一.
奇妙的記憶點:javascript

  • 內排序java

  • 不穩定算法

基本思想

經過一趟排序把待排序記錄分爲獨立的兩部分,其中一部分記錄的關鍵字都比另外一部分的關鍵字笑,則分別對兩部分繼續進行排序,以達到整個序列有序.
本身的理解:
其實就是用分治法的思路,將一個數組分爲兩半,進行無線分割排序.
首先在數列中取一個值,成爲"關鍵字/基準"(pivot);
而後比它小的放前面,大的放後面,相同的話隨便放.
遞歸的把咱們分爲兩半的數組再次分半排序.數組

快速排序(代碼)

//方法一
function quickSort(array, left, right) {//傳入參數爲數組,left,right爲排序區域下標
    console.time('1.快速排序耗時');
    if (Object.prototype.toString.call(array).slice(8, -1) === 'Array' && typeof left === 'number' && typeof right === 'number') {//判斷傳入參數的正確性
        if (left < right) { //正確性判斷
            var x = array[right], i = left - 1, temp;//x變量爲待排序數組末尾
            for (var j = left; j <= right; j++) {    //從左到右
                if (array[j] <= x) {
                    i++;//注意i先增在交換
                    temp = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                }
            }
            quickSort(array, left, i - 1);
            quickSort(array, i + 1, right);
        }
        console.timeEnd('1.快速排序耗時');
        return array;
    } else {
        return 'array is not an Array or left or right is not a number!';
    }
}

//方法二
var quickSort2 = function(arr) {
    console.time('2.快速排序耗時');
  if (arr.length <= 1) { return arr; }
  var pivotIndex = Math.floor(arr.length / 2);
  var pivot = arr.splice(pivotIndex, 1)[0];
  var left = [];
  var right = [];
  for (var i = 0; i < arr.length; i++){
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
console.timeEnd('2.快速排序耗時');
  return quickSort2(left).concat([pivot], quickSort2(right));
};

var arr=[3,49,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(quickSort(arr,0,arr.length-1));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
console.log(quickSort2(arr));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
記憶點
  • best condition: T(n) = O(nlog n)ide

  • baddest condition: T(n) = O(n^2)函數

  • average condition: T(n) = O(nlog n)大數據

歸併排序(Merge Sort)

不受輸入數據影響,可是表現比選擇排序好.代價是須要額外的內存空間.
奇妙的記憶點:ui

  • 外排序(須要額外的內存空間)prototype

  • 穩定的排序算法(排序後元素原始順序不會變化)code

基本思想:

分治法(Divide and Conquer)

將已有序的子序列合併,從而獲得徹底有序的序列.也稱爲2-路歸併.

歸併排序:代碼

function mergeSort(arr) {  //採用自上而下的遞歸方法
    var len = arr.length; //獲取傳入數組的長度
    if(len < 2) {   //若是爲單個元素則直接返回
        return arr;
    }
    var middle = Math.floor(len / 2),//取中點
        left = arr.slice(0, middle), //取左邊區間
        right = arr.slice(middle);   //取右邊區間
    return merge(mergeSort(left), mergeSort(right));//調用歸併函數
}

function merge(left, right)//傳入兩個區間
{
    var result = [];//新建變量用於保存結果
    console.time('歸併排序耗時');
    while (left.length && right.length) { //當左區間右區間存在時
        if (left[0] <= right[0]) {  //將區間中較小的一位從區間數組中放到結果數組中.
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }
    //下面兩個while是爲了解決遺留元素問題
    while (left.length) 
        result.push(left.shift());

    while (right.length)
        result.push(right.shift());
    console.timeEnd('歸併排序耗時');
    return result;//返回結果
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(mergeSort(arr));
/*10次歸併
歸併排序耗時: 0ms
歸併排序耗時: 0ms
歸併排序耗時: 0ms
歸併排序耗時: 0ms
歸併排序耗時: 0ms
歸併排序耗時: 0ms
歸併排序耗時: 0ms
歸併排序耗時: 0ms
歸併排序耗時: 0ms
歸併排序耗時: 0ms
[ 2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50 ]      */
記憶點
  • best condition: T(n) = O(n)

  • baddest condition: T(n) = O(nlog n)

  • average condition: T(n) = O(nlog n)

相關文章
相關標籤/搜索