排序算法总结

排序算法 平均时间复杂度 最好时间复杂度 最坏时间复杂度 空间复杂度 稳定性
冒泡排序 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(nlogn) O(n^2) 逆序,有序都会最差 平均O(logn) 最差O(n) 即栈的深度 不稳定
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定
希尔排序 O(n^1.3) - O(n^2) O(1) 不稳定
基数排序 O(d*(n+r)) O(d*(n+r)) O(d*(n+r)) O(r) 稳定
计数排序 O(n + k) O(n + k) O(n + k) O(n + k) 稳定

冒泡排序

public function bubbleSort($nums){
    $len = count($nums);
    $turn = 0;
    $flag = false;
    for($i = 0; !$flag && $i < $len; $i-){
        $flag = true;
        for($j = $len - 1; $j > $i; $j--){
            if($nums[$j] < $nums[$j - 1]){
                $temp = $nums[$j];
                $nums[$j] = $nums[$j - 1];
                $nums[$j - 1] = $temp;
                $flag = true;
            }
        }
    }
}   

选择排序

2,2,1 => 1,2,2 不稳定

public function selectPop($nums){
    $len = count($nums);
    for($i = 1; $i < $len; $i++){
        $min = $i;
        for($j = $i; $j < $len; $j++){
            if($nums[j] < $nums[min])
                $min = $j;
        }
        $temp = $nums[$i];
        $nums[$i] = $nums[$min];
        $nums[$min] = $temp;
    }
}

插入排序

public function insertSort($nums){
    $len = count($nums);
    for($i = 1; $i < $len; $i++){
        if($nums[$i] < $nums[$i - 1]){
            $temp = $nums[$i];
            $j = $i - 1;
            for(; $temp < $nums[$j] && $j >= 0; $j--)
                $nums[$j + 1] = $nums[$j];
            $nums[$j + 1] = $temp;
        }
    }
}

快速排序

public function quickSort($nums, $start, $end){
    if($start < $end){
        $pivotPos = partition($nums, $start, $end);
        quickSort($nums, $start, $pivotPos - 1);
        quickSort($nums, $pivotPos + 1, $high)
    }
}

public function partition($nums, $start, $end){
    $temp = $nums[$start];
    while($start < $end){
        while($start < $end && $nums[$end] >= $temp) $end--;
        $nums[$start] = $nums[$end];
        while($start < $end && $nums[$start] <= $temp) $start++;
        $nums[$end] = $num[$start];
    }
    $nums[$start] = $temp;
    return $start;
}

归并排序

public function mergeSort($nums, $start, $end){
    if($start < $end){
        $mid = ($start + $end) / 2;
        mergeSort($nums, $start, $mid);
        mergeSort($nums, $mid + 1, $end);
        merge($nums, $start, $mid, $end);
    }
}

public function merge($nums, $start, $mid, $end){
    $temp = [];
    for($i = $start; $i < $end; $i++)
        $temp[] = $nums[$i];
    $i = 0;
    $j = $mid - $start;
    for($k = $start; $i <= $mid - $start && $j < count($temp); $k++)
        $nums[$k] = $temp[$i] > $temp[$j] ? $temp[$i++] : $temp[$j++];
    while($i <= $mid - $start) $nums[$k++] = $temp[$i++];
    while($j < count($temp))  $nums[$k++] = $temp[$j++];
}

堆排序

nums[0]处不存储数据,当作哨兵位,用来存储中间值。还有个好处是可以让数据从1开始算起,这样算左右节点的时候比较方便

public function heapSort($nums, $len){
    buildMaxHeap($nums, $len);
    for($i = $len, $i > 1; $i--){
        $temp = $nums[1];//堆顶下标为1
        $nums[1] = $nums[$i];
        $nums[$i] = $temp;//将最大元素放到最后,整理前面i - 1个元素,使之形成新的堆
        adjustDown($nums, 1, $i - 1);
    }
}

public function buildMaxHeap($nums, $len){
    for($i = $len / 2; $i > 0; $i--)
        adjustDown($nums, $i, $len);
}

public function adjustDown($nums, $k, $len){
    $nums[0] = $nums[$k];
    for($i = 2 * $k; $i < $len; $i *= 2){//$i * 2向下调整
        if($i < $len && $nums[$i] < $nums[$i + 1])//因为从1开始算数据,所以下标为2的一定为左节点
            $i++;
        if($nums[0] >= $nums[i]) break;
        else{
            $nums[$k] = $nums[$i];
            $k = $i;
        }
    }
    $nums[$k] = $nums[0];
}

//插入新元素的时候,将新元素放在堆底,然后向上调整
public function adjustUp($nums, $k){
    $nums[0] = $nums[$k];
    $i = $k / 2;
    while($i > 0 && $nums[i] < $nums[0]){
        $nums[$k] = $nums[i];
        $k = $i;
        $i = $k / 2;
    }
    $nums[$k] = $nums[0];
}

希尔排序

3,2,2 => 2,2,3 不稳定

public function shellSort($nums, $len, $n){
    for($dk = $len / 2; $dk >= 1; $dk /= 2)
        for($i = $dk + 1; $i <= 2*$dk; $i++)
            if($nums[$i] < $nums[$i - $dk]){
                $nums[0] = $nums[$i];
                $j = $i - $dk;
                for(; $j > 0 && $nums[0] < $nums[$j]; $j -= $dk)
                    $nums[$j + $dk] = $nums[$j];
                $nums[$j + $dk] = $nums[0];
            }
}

你可能感兴趣的:(排序算法总结)