算法:排序算法總結(JavaScript描述)

排序算法 平均狀況 最好狀況 最壞狀況 輔助空間 穩定性
冒泡排序 O(n^2) O(n) O(n^2) O(1) 穩定
簡單選擇排序 O(n^2) O(n^2) O(n^2) O(1) 穩定
直接插入排序 O(n^2) O(n) O(n^2) O(1) 穩定
希爾排序 O(nlogn)~O(n^2) O(n^1.3) O(n^2) O(1) 不穩定
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不穩定
歸併排序 O(nlogn) O(nlogn) O(nlogn) O(n) 穩定
快速排序 O(nlogn) O(nlogn) O(n^2) O(nlogn)~O(n) 不穩定

簡單算法:冒泡、簡單選擇、直接插入
改進算法:希爾、堆、歸併、快速javascript

後三種改進算法比希爾算法效率高,但最好的狀況下,冒泡和直接插入最有效,所以若是數組基本有序,則須要考慮簡單算法java

1. 冒泡排序

1、分析算法

  1. 冒泡arr.length-1趟;
  2. 第i趟,比較arr.length-i-1次,兩兩比較,反序則交換位置。

改進:爲了不已經有序的狀況下進行無心義的兩兩比較,用flag標誌上一趟是否有交換,沒有交換則已是有序數組,退出循環。shell

2、代碼數組

function bubbleSort(arr){
        var flag=true;
        for(let i=0;i<arr.length&&flag;i++){
            flag=false;
            for(let j=0;j<arr.length-i-1;j++){
                if(arr[j]>arr[j+1]){
                    [arr[j],arr[j+1]]=[arr[j+1],arr[j]];
                    flag=true;
                }
            }
        }
        return arr;
    }

2. 簡單選擇排序

1、分析code

  1. 循環arr.length-1次,每一次的當前項與其以後的項做比較,找出其中最小的那個,與當前項交換。

2、代碼排序

function selectSort(arr){
        var min=0;
        for(let i=0;i<arr.length-1;i++){
            for(let j=i+1;j<arr.length;j++){
                if(arr[j]<arr[min]){
                    min=j;
                }
            }
            if(i!=min){
            [arr[i],arr[min]]=[arr[min],arr[i]];
            }
        }
        return arr;
    }

3. 直接插入排序

1、分析遞歸

  1. 從數組的第二項開始,循環arr.length-1次;
  2. 將當前項的值賦值給臨時變量:(留出一個「坑」)爲了前面大於當前項的項可以後移;
  3. 當前項與其前面的項比較,若是大於當前項後移,直到找到小於當前項的那個,將當前項插入其後;
  4. 若是前面沒有小於當前項的,前面項所有後移覺得,當前項就插入位置0處。

2、代碼ip

function insertSort(arr){
        for(let i=1;i<arr.length;i++){
            let temp=arr[i];
            let j=i-1;
            while(j>=0&&arr[j]>temp){
                arr[j+1]=arr[j];
                j--;
            }
            arr[j+1]=temp;
        }
        return arr;
    }

4. 希爾排序

  是一種改進版的插入排序,「縮小增量排序」。
1、分析rem

  1. 經過增量將待排序列分割成若干個子序列,每一個子序列進行插入排序;
  2. 縮小增量,重複步驟1,直到增量不大於0;
  3. ps:增量等於1時,進行了一次全排的直接插入排序。這樣作的目的是由於,直接插入排序在序列基本有序時效率最高。

2、代碼

function shellSort(arr){
        for(let increment=Math.floor(arr.length/2);increment>0;increment=Math.floor(increment/2)){
            for(let i=increment;i<arr.length;i++){
                let temp=arr[i];
                let j=i-increment;
                while(j>=0&&arr[j]>temp){
                    arr[j+increment]=arr[j];
                    j-=increment;
                }
                arr[j+increment]=temp;
            }
        }
        return arr;
    }

5. 堆排序

1、分析

  1. 將待排序列構形成一個大頂堆(位置0處,也就是堆頂,爲最大數);
  2. 將arr[0]與arr[arr.length-1]進行交換,此時數組尾爲最大值;
  3. 調整0~arr.length-2成一個大頂堆,繼續2,直到所有排完。

2、代碼

function heapSort(arr){
        //1. 構造大頂堆
        //2. 頂值最大,交換到最末尾
        //3. 調整大頂堆
        var len=arr.length;
        for(let i=Math.floor(len/2)-1;i>=0;i--){
            heapAdjust(arr,i,len);
        }
        for(let i=arr.length-1;i>0;i--){
            [arr[0],arr[i]]=[arr[i],arr[0]];
            heapAdjust(arr,0,i);
        }
        return arr;
    }
    function heapAdjust(arr,pos,len){
        var root=pos;
        for(let i=2*pos+1;i<len;i=2*i+1){
            if(i+1<len&&arr[i]<arr[i+1]){
                i++;
            }
            if(arr[temp]<arr[i]){
                [arr[temp],arr[i]]=[arr[i],arr[temp]];
            }
            root=i;
        }
        // return arr;
    }

6. 歸併排序

1、分析

  1. 將兩個有序數組合成一個有序數組:歸併。
  2. 將一個數組分割成長度爲1的數組,就能夠當作它是一個有序數組,兩兩合併,就成了一個長度爲2的有序數組,再兩兩合併,直到排序完成。

2、代碼

function mergeSort(arr){
        if(arr.length<=1){return arr};

        let mid=Math.floor(arr.length/2);
        let left=arr.slice(0,mid);
        let right=arr.slice(mid);
        // console.log(left+"+"+right);
        return merge(mergeSort(left),mergeSort(right));
    }
    function merge(left,right){
        var result=[];
        while(left.length>0&&right.length>0){
            if(left[0]<right[0]){
                result.push(left.shift());
            }
            else{
                result.push(right.shift());
            }
        }
        return result.concat(left,right);
    }

7. 快速排序

1、分析

  1. 找基準
  2. 小於基準的放左邊,大於基準的放右邊;
  3. 遞歸基準左、右無序序列找基準;
  4. 直到輸入數組長度爲1,跳出遞歸。

2、代碼

function qSort1(arr){
        if(arr.length<=1){return arr;}

        let pivot=arr[0];
        let left=[];let right=[];
        for(let i=1;i<arr.length;i++){
            if(arr[i]<pivot){
                left.push(arr[i]);
            }
            else{
                right.push(arr[i]);
            }
        }
        return qSort1(left).concat(pivot,qSort1(right));
    }
    function qSort2(arr,low,high){
        if(low<high){
            var pivot=partition(arr,low,high);
            qSort2(arr,pivot+1,high);
            qSort2(arr,low,pivot-1);
        }
        // return arr;
    }
    function partition(arr,low,high){
        var pivot=arr[low];
        while(low<high){
            while(low<high&&pivot<=arr[high]){
                high--;
            }
            [arr[low],arr[high]]=[arr[high],arr[low]];
            while(low<high&&pivot>=arr[low]){
                low++
            }
            [arr[low],arr[high]]=[arr[high],arr[low]];
        }

        return low;
    }
相關文章
相關標籤/搜索