首頁  >  文章  >  後端開發  >  PHP怎麼實作快速排序的非遞歸演算法

PHP怎麼實作快速排序的非遞歸演算法

PHPz
PHPz原創
2023-04-05 14:38:031477瀏覽

介紹

快速排序是一種高效的排序演算法,它透過不斷地將一個陣列分成兩個子數組來實現排序。在快速排序演算法中,一個基準值(pivot)被選出並所有小於基準值的元素放在其左側,而所有大於基準值的元素放在其右側。然後,這個過程被遞歸地應用在左右兩側的子數組中,直到整個數組有序為止。

快速排序是一個遞歸函數,因為它需要將原問題拆解成兩個更小的子問題,然後透過遞歸地求解這些子問題來求解原問題。雖然這種方法在某些情況下可以很有效地工作,但它也有一些限制。具體來說,在處理大型數組時,遞歸演算法可能會耗盡電腦的堆疊空間,從而引發棧溢位異常。此外,遞歸函數呼叫的額外開銷也可能導致演算法的效能下降。

因此,在某些情況下,使用非遞迴的實作方法可能更為適當。在本文中,我們將介紹一種使用PHP實作快速排序的非遞歸演算法。

演算法實作

我們先定義一個輔助函數partition,用來將一個陣列分成兩個子陣列:一個包含所有小於基準值的元素,一個包含所有大於基準值的元素。

function partition(&$arr, $left, $right) {
    $pivot = $arr[$right]; // 选择最后一个元素作为基准值
    $i = $left - 1;
    for ($j = $left; $j < $right; $j++) {
        if ($arr[$j] < $pivot) {
            $i++;
            list($arr[$i], $arr[$j]) = array($arr[$j], $arr[$i]); // 交换i和j处的元素
        }
    }
    list($arr[$i + 1], $arr[$right]) = array($arr[$right], $arr[$i + 1]); // 将基准值放到正确的位置
    return $i + 1;
}

此函數從陣列中選擇最後一個元素作為基準值,並透過交換陣列元素將所有小於基準值的元素放到陣列的左邊。在這個過程中,我們用變數 $i 來記錄目前處理的子數組的下標,$j 用來遍歷整個數組。當我們找到一個小於基準值的元素時,我們將 $i 向右移動一位,並將這個元素放到 $i 的位置。最後,我們將基準值放到最終的位置 $i 1 上。

有了 partition 函數,我們現在可以實作快速排序演算法的非遞迴版本。在該版本中,我們使用一個堆疊來儲存待處理的子數組。當我們處理一個子數組時,我們首先在堆疊中記錄該子數組的左右邊界,然後不斷將它劃分成兩個更小的子數組,直到所有子數組都已有序為止。

function quick_sort(&$arr) {
    $stack = new SplStack(); // 使用SplStack实现栈
    $stack->push(count($arr) - 1); // 将整个数组的下标压入栈
    $stack->push(0);
    while (!$stack->isEmpty()) {
        $left = $stack->pop();
        $right = $stack->pop();
        $pivotIndex = partition($arr, $left, $right);
        if ($left < $pivotIndex - 1) {
            $stack->push($pivotIndex - 1);
            $stack->push($left);
        }
        if ($pivotIndex + 1 < $right) {
            $stack->push($right);
            $stack->push($pivotIndex + 1);
        }
    }
}

在這個版本的程式碼中,我們使用 SplStack 類別來實作堆疊。我們首先將整個陣列的左右邊界壓入堆疊中,然後不斷從堆疊中取出左右邊界,並將它們傳遞給 partition 函數來進行子數組的劃分。如果 left < pivotIndex - 1,則表示左側子數組尚未有序,將其壓入堆疊中等待處理。同樣地,如果 pivotIndex 1 < right,則表示右側子數組尚未有序,將其壓入堆疊中等待處理。

此演算法的時間複雜度為 O(nlogn)。雖然它不如遞歸版快速排序在所有情況下都快,但它可以顯著降低演算法的空間複雜度,並避免了遞歸函數呼叫的開銷。如果您需要在PHP中快速排序一個大型數組,這種演算法可能比遞歸版的快速排序更適合您的需求。

以上是PHP怎麼實作快速排序的非遞歸演算法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn