資料結構與演算法之PHP排序演算法(堆排序)

2022-03-18 01:02:26 字數 2369 閱讀 6025

一、堆的定義

堆通常是乙個可以被看做一棵樹的陣列物件,其任一非葉節點滿足以下性質:

1)堆中某個節點的值總是不大於或不小於其父節點的值:

每個節點的值都大於或等於其左右子節點的值,稱為大頂堆。即:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]。

或:每個節點的值都小於或等於其左右子節點的值,稱為小頂堆。即:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]。

2)堆總是一棵完全二叉樹。

注:上述公式,根節點從0開始。如果根節點從1開始,則左右子節點分別是2i和2i+1。

由上述性質可知:堆頂元素(或完全二叉樹的根)必定是所有元素中最大值(大頂堆)或最小值(小頂堆)。

二、基本思想

以大頂堆為例,將待排序的序列構造成乙個大根堆,此時,整個序列的最大值就是堆頂的根節點。將它移走(也就是將其與堆陣列的末尾元素交換,此時末尾元素就是最大值),然後將剩餘的n-1個序列重新構造成乙個堆,這樣就會得到n個元素中的次小的值。如此反覆執行,便能得到乙個有序序列了。

三、演算法過程

1)將無序序列構建成乙個堆,根據公升序降序需求選擇大頂堆或小頂堆;

2)將堆頂元素與末尾元素交換,將最大元素"沉"到陣列末端;

3)重新調整結構,使其滿足堆定義,然後繼續交換堆頂元素與當前末尾元素,反覆執行調整+交換步驟,直到整個序列有序。

以大頂堆為例,

建立堆:

1)將n個元素從0到n-1(或從1到n)自頂向下、從左到右編碼,轉換成一棵完全二叉樹;

2)從n/2的非葉節點開始到根節點,逐個掃瞄,如果子節點大於父節點,就交換;

3)直到根節點最大,如果子樹不滿足最大堆的條件,繼續調節,直到所有的父節點都大於子節點為止。

堆排序:

1)排序開始,首先輸出堆頂元素,因為它是最大值;

2)將堆頂元素和最後乙個元素交換;

3)將前面n-1個節點繼續進行堆調整的過程,再將根節點取出,交換堆頂和最後乙個元素;

4)這樣一直到所有節點都取出,則排序完成。

四、演算法**

待排序序列為49、38、65、97、76、13、27、50,其邏輯結構和儲存結構如下:

1)構造大頂堆

① 從最後乙個非葉子節點開始,第乙個非葉子節點 arr.length/2-1=8/2-1=3,也就是97,在[97, 50]這個小堆裡邊,父節點97最大,所以不交換;

② 找到第2個非葉子節點,也就是位置為2的節點65,在[65, 13, 27]這個小堆裡邊,父節點65最大,所以不交換;

③ 找到第3個非葉子節點,也就是位置為1的節點38,在[38, 97, 76]這個小堆裡邊,97最大,38和97交換;

④ 找到第4個非葉子節點,也就是位置為0的節點49,在[49, 97, 65]這個小堆裡邊,97最大,49和97交換;

⑤ 交換導致了子根[49, 38, 76]結構混亂,繼續調整,[49, 38, 76]中76最大,49和76交換;

⑥ 子根[38, 50]結構混亂,繼續調整,[38, 50]中50最大,38和50交換;

至此,乙個無序序列已經構造成乙個大頂堆。

2)堆排序

① 將堆頂元素97和末尾元素38進行交換,得到最大元素97;

② 重新調整結構,使其繼續滿足大頂堆的定義;

③ 再將堆頂元素76與末尾元素27進行交換,得到第二大元素76;

④ 重新調整結構,使其繼續滿足大頂堆的定義;

⑤ 後續過程,繼續進行交換、調整,如此反覆進行,最終使得整個序列有序。

由排序過程可知:若想得到公升序,則建立大頂堆,若想得到降序,則建立小頂堆。

五、php**實現(大頂堆)

<?php

// 堆排序

function heapsort(&$arr)

// 調整堆結構+交換堆頂元素與末尾元素

for ($j = $len - 1; $j > 0; $j--)

}// 調整堆

function adjustheap(&$arr, $i, $length)

if ($temp < $arr[$k]) else

}$arr[$i] = $temp;   // 將temp值放到最終的位置

}// 交換2個值

function swap(&$arr, $a, $b)

// 測試

$arr = array(49, 38, 65, 97, 76, 13, 27, 50);

heapsort($arr);

print_r($arr);

六、效率分析

1、時間複雜度:o(nlogn)

最壞,最好,平均時間複雜度均為o(nlogn)。

2、空間複雜度:堆排序僅需乙個記錄大小的供交換用的輔助儲存空間,因此空間複雜度為o(1),是不穩定排序。

資料結構與演算法之PHP排序演算法(歸併排序)

一 基本思想 歸併排序演算法是將兩個 或兩個以上 有序表合併成乙個新的有序表,即把待排序序列分為若干個子串行,使每個子串行有序,再將已有序的子串行合併,得到完全有序的序列。該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。二 演算法過程 歸併主要做兩件事 1 分解 將...

資料結構與演算法之排序

三 演算法效能 二 七種排序演算法 資料結構之線性表 資料結構之鍊錶 資料結構之串 資料結構之圖 資料結構之排序演算法 對n個資料執行某種操作,使其按照某種規則有序的排列,這樣的操作就是排序。內排序與外排序 按照排序過程中資料是否全放在記憶體中,可以分為內排序和外排序 交插選並 其中內排序又分為插入...

《資料結構與演算法》之排序

資料結構與演算法 之鍊錶 資料結構與演算法 之鏈棧 資料結構與演算法 之佇列 資料結構與演算法 之二分查詢 資料結構與演算法 之二叉樹 如果你是一名程式設計師,或多或少你都了解過 聽說過排序。在專案中我們也會經常用到排序,排序非常重要,現在我在這裡分享一些經典的排序演算法。先附上demo位址 氣泡排...