學(xué)習(xí)PHP中堆排序算法的原理及時(shí)間復(fù)雜度分析
堆排序是一種基于堆數(shù)據(jù)結(jié)構(gòu)的排序算法,它的時(shí)間復(fù)雜度為O(nlogn)。本文將介紹PHP語言中堆排序算法的原理,同時(shí)提供代碼示例。
一、堆的定義和性質(zhì)
在學(xué)習(xí)堆排序之前,首先需要了解堆的定義和性質(zhì)。堆是一種完全二叉樹,其每一個(gè)節(jié)點(diǎn)的值都大于或等于其子節(jié)點(diǎn)的值,我們把這樣的堆稱之為大頂堆。相反,如果每一個(gè)節(jié)點(diǎn)的值都小于或等于其子節(jié)點(diǎn)的值,我們稱之為小頂堆。
由于堆的特性,堆頂元素即為最大或最小值,因此在堆排序中,我們通常將待排序的數(shù)組看作一個(gè)完全二叉樹,并利用堆的特性進(jìn)行排序。
二、堆排序算法的原理
堆排序算法主要分為構(gòu)建堆和調(diào)整堆兩個(gè)步驟。
- 構(gòu)建堆(buildHeap):將待排序的數(shù)組調(diào)整為一個(gè)大頂堆。
步驟如下:
從最后一個(gè)非葉子節(jié)點(diǎn)(即n/2-1)開始逐個(gè)向前遍歷,調(diào)用調(diào)整堆的函數(shù)(adjustHeap)。調(diào)整堆的函數(shù)采用自上而下的方式,對當(dāng)前節(jié)點(diǎn)及其子樹進(jìn)行調(diào)整,保證當(dāng)前節(jié)點(diǎn)大于其子節(jié)點(diǎn)。重復(fù)以上兩個(gè)步驟,直到整個(gè)數(shù)組調(diào)整為一個(gè)大頂堆。
- 調(diào)整堆(adjustHeap):將當(dāng)前節(jié)點(diǎn)及其子樹調(diào)整為一個(gè)大頂堆。
步驟如下:
根據(jù)當(dāng)前節(jié)點(diǎn)的位置計(jì)算其左右子節(jié)點(diǎn)的位置。比較當(dāng)前節(jié)點(diǎn)和其左右子節(jié)點(diǎn)的值,找到最大節(jié)點(diǎn)的位置。如果最大節(jié)點(diǎn)的位置不是當(dāng)前節(jié)點(diǎn)的位置,則交換最大節(jié)點(diǎn)和當(dāng)前節(jié)點(diǎn)的值,并遞歸調(diào)用自身對交換后的子樹進(jìn)行調(diào)整。
- 排序(sortHeap):將堆頂元素(即數(shù)組的第一個(gè)元素)與最后一個(gè)葉子節(jié)點(diǎn)交換,然后對剩余的n-1個(gè)元素進(jìn)行堆調(diào)整。
步驟如下:
將堆頂元素與最后一個(gè)葉子節(jié)點(diǎn)交換。縮小堆的范圍,即忽略已經(jīng)排序好的最后一個(gè)葉子節(jié)點(diǎn)。對縮小范圍的堆進(jìn)行調(diào)整,保持大頂堆的性質(zhì)。重復(fù)以上三個(gè)步驟,直到堆的范圍縮小為1。
三、PHP代碼示例
下面是PHP語言實(shí)現(xiàn)堆排序算法的示例代碼:
function heapSort(&$arr) { $length = count($arr); // 構(gòu)建大頂堆 for ($i = floor($length/2 - 1); $i >= 0; $i--) { adjustHeap($arr, $i, $length); } // 調(diào)整堆并排序 for ($i = $length - 1; $i >= 0; $i--) { // 交換堆頂元素和最后一個(gè)葉子節(jié)點(diǎn) $temp = $arr[0]; $arr[0] = $arr[$i]; $arr[$i] = $temp; // 調(diào)整堆使其保持大頂堆性質(zhì) adjustHeap($arr, 0, $i); } } function adjustHeap(&$arr, $i, $length) { $largest = $i; // 最大值的位置 $left = $i * 2 + 1; // 左子節(jié)點(diǎn)的位置 $right = $i * 2 + 2; // 右子節(jié)點(diǎn)的位置 // 比較當(dāng)前節(jié)點(diǎn)與左右子節(jié)點(diǎn)的值,找到最大值的位置 if ($left < $length && $arr[$left] > $arr[$largest]) { $largest = $left; } if ($right < $length && $arr[$right] > $arr[$largest]) { $largest = $right; } // 如果最大值的位置不是當(dāng)前節(jié)點(diǎn)的位置,則交換兩個(gè)位置的值,并遞歸調(diào)整堆 if ($largest != $i) { $temp = $arr[$i]; $arr[$i] = $arr[$largest]; $arr[$largest] = $temp; adjustHeap($arr, $largest, $length); } } // 測試 $arr = [8, 3, 6, 2, 9, 1]; heapSort($arr); print_r($arr); // 輸出 [1, 2, 3, 6, 8, 9]
登錄后復(fù)制
四、時(shí)間復(fù)雜度分析
堆排序的時(shí)間復(fù)雜度為O(nlogn)。其中,構(gòu)建堆的時(shí)間復(fù)雜度為O(n),調(diào)整堆的時(shí)間復(fù)雜度為O(logn)。由于要對n個(gè)元素進(jìn)行排序,因此總的時(shí)間復(fù)雜度為O(nlogn)。
總結(jié)
本文詳細(xì)介紹了PHP語言中堆排序算法的原理,同時(shí)提供了相應(yīng)的代碼示例。堆排序是一種高效的排序算法,適用于待排序的數(shù)組較大的情況。通過學(xué)習(xí)堆排序算法,可以進(jìn)一步提升對數(shù)據(jù)結(jié)構(gòu)和算法的理解和應(yīng)用能力。
以上就是學(xué)習(xí)PHP中堆排序算法的原理及時(shí)間復(fù)雜度分析。的詳細(xì)內(nèi)容,更多請關(guān)注www.92cms.cn其它相關(guān)文章!