PHP算法之四大基礎算法

page_img_url

前言

雖然工作中,你覺得自己並沒有涉及到算法這方面的東西,但是算法是程序的核心,一個程序的好與差,關鍵是這個程序算法的優劣,所以對於冒泡排序、插入排序、選擇排序、快速排序這四種基本算法,我想還是要掌握的。

冒泡排序法

冒泡排序大概的意思是依次比較相鄰的兩個數,然後根據大小做出排序,直至最後兩位數。由於在排序過程中總是小數往前放,大數往後放,相當於氣泡往上升,所以稱作冒泡排序。

冒泡是從前往後冒,所以,每輪比較的次數也是逐漸減少的,最後一個數不用比較,其時間複雜度爲O(n²),算法如下:

/**
 * 冒泡排序算法
 * @param array $arr
 * @return array
 */
function bubble_sort($arr) {
    // 判斷參數是否爲數組,且不爲空
    if (!is_array($arr) || empty($arr)) {
        return $arr;
    }
    // 循環需要冒泡的輪數
    for ($i = 1, $len = count($arr); $i < $len; $i++) {
        // 循環每輪需要比較的次數
        for ($j = 0; $j < $len - $i; $j++) {
            // 大的數,交換位置,往後挪
            if ($arr[$j] > $arr[$j + 1]) {
                $temp = $arr[$j];
                $arr[$j + 1] = $arr[$j];
                $arr[$j] = $temp;
            }
        }
    }
    return $arr;
}

選擇排序法

選擇排序的原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾;以此類推,直到所有元素均排序完畢。

選擇是每一次從假定一個最小值的位置,然後用假定最小值和後面的值依次比較,找到實際的最小值來放到假定最小值的位置上,其時間複雜度也爲O(n²),算法如下:

/**
 * 選擇排序法
 * @param array $arr
 * @return array
 */
function select_sort($arr) {
    // 判斷參數是否爲數組,且不爲空
    if (!is_array($arr) || empty($arr)) {
        return $arr;
    }
    $len = count($arr);
    for ($i = 0; $i < $len - 1; $i++) {
        // 假設最小數的位置
        $min = $i;
        // 用假設的最小數和$i後面的數循環比較,找到實際的最小數
        for ($j = $i + 1; $j < $len; $j++) {
            // 後面的數比假設的最小數小,替換最小數
            if ($arr[$min] > $arr[$j]) {
                $min = $j;
            }
        }
        // 假設的最小數和實際不符,交換位置
        if ($min != $i) {
            $temp = $arr[$min];
            $arr[$min] = $arr[$i];
            $arr[$i] = $temp;
        }
    }
    return $arr;
}

插入排序法

插入排序的原理:每次將一個待排序的記錄,按其關鍵字大小插入到前面已經排好序的子序列中的適當位置,直到全部記錄插入完成爲止。

插入排序法是先將排序元素的前兩個元素排序,然後將第三個元素插入已經排序好的兩個元素中,所以這三個元素仍然是從小到大排序,接着將第四個元素插入,重複操作直到所有元素都排序好;其時間複雜度同樣爲O(n²),算法如下:

/**
 * 插入排序法
 * @param array $arr
 * @return array
 */
function insert_sort($arr) {
    // 判斷參數是否爲數組,且不爲空
    if (!is_array($arr) || empty($arr)) {
        return $arr;
    }
    $len = count($arr);
    for ($i = 1; $i < $len; $i++) {
        // 當前需要比較的臨時數
        $tmp = $arr[$i];
        // 循環比較臨時數所在位置前面的數
        for ($j = $i - 1; $j >= 0; $j--) {
            // 前面的數比臨時數大,則交換位置
            if ($arr[$j] > $tmp) {
                $arr[$j + 1] = $arr[$j];
                $arr[$j] = $tmp;
            }
        }
    }
    return $arr;
}

快速排序法

快速排序法是對冒泡排序的一種改進。他的基本原理是:通過一趟排序將待排記錄分割成獨立的兩部分,其中一部分的關鍵字均比另一部分記錄的關鍵字小,則可分別對這兩部分記錄繼續進行快速排序,整個排序過程可以遞歸進行,以達到整個序列有序的目的。

快速排序法是從數列中挑出第一個數(最後一個數)作爲基準元素,然後循環所有數,和基準書比較分爲左右兩列,然後重複這樣的步驟繼續劃分爲左右兩列,算法如下:

/**
 * 快速排序法
 * @param array $arr
 * @return array
 */
function quick_sort($arr) {
    // 判斷參數是否爲數組,且不爲空
    if (!is_array($arr) || empty($arr)) {
        return $arr;
    }
    // 數組長度爲1停止排序
    $len = count($arr);
    if ($len == 1) {
        return $arr;
    }
    // 聲明左右兩個空數組
    $left = $right = [];
    // 循環遍歷,把第一個元素當做基準數
    for ($i = 1; $i < $len; $i++) {
        // 比較當前數的大小,並放入對應的左右數組
        if ($arr[$i] > $arr[0]) {
            $right[] = $arr[$i];
        } else {
            $left[] = $arr[$i];
        }
    }
    // 遞歸比較
    $left = quick_sort($left);
    $right = quick_sort($right);
    // 左右兩列以及基準數合併
    return array_merge($left, [$arr[0]], $right);
}

使用方法

聲明一個待排序的數組,然後調用對應的排序方法即可得到返回的排序好的數組;說明一下,我這裏的排序設計都是遞增的,如果需要遞減,需要修改一下排序算法的比較替換符就行。

// 待排序數組
$arr = [1, 4, 5, 9, 3, 8, 6];
// 調用排序方法
$sort_arr = bubble_sort($arr);
// 輸出打印
print_r($sort_arr);

分析算法

通常,對於一個給定的算法,我們要做兩項分析:第一是從數學上證明算法的正確性,這一步主要用到形式化證明的方法及相關推理模式,如循環不變式、數學歸納法等。而在證明算法是正確的基礎上,第二步就是分析算法的時間複雜度。算法的時間複雜度反映了程序執行時間隨輸入規模增長而增長的量級,在很大程度上能很好反映出算法的優劣與否。還有我們通常說的:算法優化無非就是以時間換空間,以空間換時間,一般這兩者是不可兼得。

結束語

實現一個程序,肯定是有多種算法的,大家有其他想說的,都可以留言和我交流,謝謝!如有問題,也歡迎指出,我會及時改正,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章