排序算法學習筆記

排序算法

穩定性:若是a本來在b前面且a=b,排序以後a仍然在b前面,則穩定;若是排序以後a可能會在b後,則不穩定。html

非線性時間比較類排序

經過比較來決定元素間的相對次序,時間複雜度不能突破O(nlogn)。算法

交換排序

冒泡排序(bubble sort)

一次比較兩個元素,若是順序不對則交換過來。shell

時間複雜度:O(n^2),優化後最好時間複雜度可爲O(n)。
空間複雜度:O(1)。
穩定性:穩定。數組

示例代碼:數據結構

//普通
function srotfunction($a){
    $count = count($a);
    for($i=$count-1; $i>0; $i--){
        for($j=0;$j<$i;$j++){
            if($a[$j] > $a[$j+1]){
                $tmp = $a[$j];
                $a[$j] = $a[$j+1];
                $a[$j+1] = $tmp;
            }
        }
        
    }
    return $a;
}
//優化後,用 didswap 標記是否有交換動做。若是自己有序,則執行一次。
function srotfunction($a){
    boolean $didswap;
    
    $count = count($a);
    for($i=$count-1; $i>0; $i--){
        $didswap = false;
        for($j=0;$j<$i;$j++){
            if($a[$j] > $a[$j+1]){
                $tmp = $a[$j];
                $a[$j] = $a[$j+1];
                $a[$j+1] = $tmp;
                
                $didswap = true;
            }
        }
        
        if($didswap == false){
            break;
        }
    }
    return $a;
}

快速排序(quick sort)

經過基準元素,分爲兩組子串,繼續對字段分組,以達到整個序列有序。基準元素通常選擇第一個元素或最後一個元素。函數

時間複雜度:O(nlogn)。
空間複雜度:O(nlogn)。
穩定性:不穩定。優化

代碼示例:ui

function partition(&$a, $low, $high){
    $privotKey = $a[$low];
    
    while($low<$high){
        //大於的部分
        while($low<$high && $a[$high]>$privotKey){
            --$high;
        }
        swap($a, $low, $high);
        while($low<$high && $a[$low]<$privotKey){
            ++$low;
        }
        swap($a, $low, $high);
    }
    
    return $low;
}

function quicksort(&$a, $low, $high){
    if($low < $high){
        $privotloc = partition($a, $low, $high);
        quicksort($a, $low, $privotloc-1);
        quicksort($a, $privotloc+1, $high);
    }
}

$b = quicksort($a, 0, count($a)-1);

插入排序

簡單插入排序(insertion sort)

構建有序序列,對未排序單元,在已排序序列中從後向前掃描,找到相應位置並插入。spa

時間複雜度:O(n^2),已有序只比較一次,複雜度爲O(n)。
空間複雜度:O(1)。
穩定性:穩定。code

代碼示例:

function srotfunction($a){
    $len = count($a);
    
    for($i=1; $i<$len; $i++){
        $current = $a[$i];
        $preIndex = $i - 1;

        while($preIndex >=0 && $a[$preIndex] > $current){
            $a[$preIndex+1] = $a[$preIndex];
            $preIndex--;
        }
        
        $a[$preIndex + 1] = $current;
    }
    
    return $a;
}

希爾排序(shell sort)

把數據按下標增量分爲多個分組,每組內用插入排序。希爾增量序列{n/2, (n/2)/2, ..., 1}。

時間複雜度:O(n^2)。一些優化的增量序列能夠爲O(n^3/2)。已經有序的爲O(n)。
空間複雜度:O(1)。
穩定性:不穩定。

代碼示例:

function srotfunction($a){
    $len = count($a);
    $gap = intval($len / 2);

    for(;$gap>0;$gap=intval($gap/2)){
        for($i=$gap;$i<$len;$i++){
            $j = $i;
            $tmp = $a[$i];

            if($a[$j] < $a[$j-$gap]){
                while($j-$gap>=0 && $a[$j-$gap]>$tmp){
                    $a[$j] = $a[$j-$gap];
                    $j-=$gap;
                }
                $a[$j] = $tmp;
            }
        }
    }
    
    return $a;
}

選擇排序

簡單選擇排序(selection sort)

從未排序字段中找到最小(最大)的元素,放入已排序字段中。

時間複雜度:O(n^2)。
空間複雜度:O(1)。

代碼示例:

function srotfunction($a){
    $len = count($a);
    
    for($i=0; $i<$len-1; $i++){
        $min = $i;
        for($j=$i+1; $j<$len; $j++){
            if( $a[$min] > $a[$j]){
                $min = $j;
            }
        }
        
        if($min != $i){
            $tmp = $a[$min];
            $a[$min] = $a[$i];
            $a[$i] = $tmp;
        }
    }
    
    return $a;
}

堆排序(heap sort)

利用堆的數據結構,反覆調整結構以使其知足堆定義。
堆:徹底二叉樹,每一個節點的值都大於或等於其左右孩子節點的值(大頂堆),同理小頂堆。

時間複雜度:O(nlogn)。
空間複雜度:O(1)。

基本思路:

  1. 將無序序列構造爲一個堆(大頂堆-升序,小頂堆-降序);
  2. 將堆頂元素與末尾元素交換,使最大(最小)元素到數組末尾;
  3. 從新調整結構,使其知足堆定義;
  4. 繼續交換堆頂元素與當前末尾元素,反覆調整交換,使序列有序。

歸併排序(merge sort)

分治法,將已有有序子序列合併得到有序序列。二路歸併排序、多路歸併排序。

時間複雜度:O(nlogn)。
空間複雜度:O(n)。
穩定性:穩定。

代碼示例:

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 = [];
 
    while (left.length>0 && right.length>0) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }
 
    while (left.length)
        result.push(left.shift());
 
    while (right.length)
        result.push(right.shift());
 
    return result;
}

線性時間非比較類排序

不經過比較來決定次序,能夠以線性時間運行。

計數排序(counting sort)

將輸入的數據值轉化爲鍵,存儲在額外的數組空間中。要求輸入的數據必須是有肯定範圍的整數,k不是很大且序列比較集中時。

時間複雜度:O(n+k) //輸入元素是n個0~k之間的整數
空間複雜度:O(n+k)
穩定性:穩定

算法描述:

  1. 找到數組中最大、最小的值,構建新數組c[min, max];
  2. 統計數組中值爲i的元素,放入c[i],並累加次數;
  3. 統計完後,將c中元素根據i和值放入新數組。

桶排序(bucket sort)

利用函數的映射關係,計數排序的升級版。

算法描述:

  1. 假設數據服從均勻分佈,將數據分到有限數量的桶裏;
  2. 對每一個桶分別排序(使用其餘排序算法或者桶排序);
  3. 將非空桶數據拼接起來。

基數排序(radix sort)

先按低位優先級排序、收集,再按高位優先級排序、收集,以此類推。

算法複雜度圖表

圖片描述

相關資料

十大經典排序算法(動圖演示)

相關文章
相關標籤/搜索