php堆是什么,PHP 堆與堆排序的詳解

堆排序:堆排序是利用堆的性質進行的一種選擇排序。下面先討論一下堆。

1.堆

堆實際上是一棵完全二叉樹,其任何一非葉節點滿足性質:

Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]

即任何一非葉節點的關鍵字不大于或者不小于其左右孩子節點的關鍵字。

堆分為大頂堆和小頂堆,滿足Key[i]>=Key[2i+1]&&key>=key[2i+2]稱為大頂堆,滿足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]稱為小頂堆。由上述性質可知大頂堆的堆頂的關鍵字肯定是所有關鍵字中最大的,小頂堆的堆頂的關鍵字是所有關鍵字中最小的。

2.堆排序的思想

利用大頂堆(小頂堆)堆頂記錄的是最大關鍵字(最小關鍵字)這一特性,使得每次從無序中選擇最大記錄(最小記錄)變得簡單。

其基本思想為(大頂堆):

1)將初始待排序關鍵字序列(R1,R2….Rn)構建成大頂堆,此堆為初始的無須區;

2)將堆頂元素R[1]與最后一個元素R[n]交換,此時得到新的無序區(R1,R2,……Rn-1)和新的有序區(Rn),且滿足R[1,2…n-1]<=R[n];

3)由于交換后新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,……Rn-1)調整為新堆,然后再次將R[1]與無序區最后一個元素交換,得到新的無序區(R1,R2….Rn-2)和新的有序區(Rn-1,Rn)。不斷重復此過程直到有序區的元素個數為n-1,則整個排序過程完成。

操作過程如下:

1)初始化堆:將R[1..n]構造為堆;

2)將當前無序區的堆頂元素R[1]同該區間的最后一個記錄交換,然后將新的無序區調整為新的堆。

因此對于堆排序,最重要的兩個操作就是構造初始堆和調整堆,其實構造初始堆事實上也是調整堆的過程,只不過構造初始堆是對所有的非葉節點都進行調整。

堆排序與快速排序,歸并排序一樣都是時間復雜度為O(N*logN)的幾種常見排序方法。學習堆排序前,先講解下什么是數據結構中的二叉堆。

PHP 堆管理代碼如下:

classheep{

staticfunctionadd(&$arr,$one){

$arr[]?=$one;

self::up($arr,count($arr)?-1);

}

//?下沉

staticfunctiondel(&$arr){

$arr[0]?=array_pop($arr);

self::down($arr,0,count($arr)-1);

}

staticfunctionswap(&$arr,$i,$p){

$tmp=$arr[$i];

$arr[$i]?=$arr[$p];

$arr[$p]?=$tmp;

}

//?增加元素?上浮

staticfunctionup(&$arr,$i){

$p=floor(($i-1)/2);

while($p>=?0?&&$i>?0?&&$arr[$p]?>$arr[$i]?){

self::swap($arr,$i,$p);

$i=$p;

$p=floor(($i-1)/2);

}

}

//?下沉?$i開始?$n結束

staticfunctiondown(&$arr,$i,$n){

$l=?2*$i+?1;

while($l<=$n){

if($l+1?<=$n&&$arr[$l+1]

if($arr[$l]?>$arr[$i]?)break;

self::swap($arr,$i,$l);

$i=$l;

$l=?2*$i+?1;

}

}

//?將數組變成堆

staticfunctionmake(&$arr){

$n=count($arr)-1;

for($i=$n/?2?–?1;$i>=?0;$i–)

self::down($arr,$i,$n);

}

//?將堆進行排序

staticfunctionsort(&$arr){

$n=count($arr)-1;

for($i=$n;$i>=?0;$i–){

self::swap($arr,0,$i);

self::down($arr,0,$i-1);

}

}

}

$arr=?[10,40,30];

$arr=array();

heep::add($arr,40);

heep::add($arr,10);

heep::add($arr,30);

heep::add($arr,15);

heep::add($arr,8);

heep::add($arr,50);

heep::add($arr,20);

heep::add($arr,3);

echojoin(',',$arr),'
';

heep::del($arr);

heep::del($arr);

heep::del($arr);

echojoin(',',$arr),'
';

//phpfensi.com

heep::sort($arr);

echojoin(',',$arr),'
';

$arr=?[40,10,30];

heep::make($arr);

echojoin(',',$arr),'
';

假設n為當前數組的key則,n的父節點為 n>>1 或者 n/2(整除);n的左子節點l= n<<1 或 l=n*2,n的右子節點r=(n<<1)+1 或 r=l+1,代碼如下:

$arr=array(1,8,7,2,3,4,6,5,9);

數組$arr的原形態結構如下:

1

/

8?7

/?/

2?3?4?6

/

5?9

heapsort($arr);print_r($arr);

排序后生成標準的小頂堆結構如下:

1

/

2?3

/?/

4?5?6?7

/

8?9

既數組:array(1,2,3,4,5,6,7,8,9):代碼如下:

functionheapsort(&$arr)

{

//求最后一個元素位

$last=count($arr);

//堆排序中通常忽略$arr[0]

array_unshift($arr,0);

//最后一個非葉子節點

$i=$last>>1;

//整理成大頂堆,最大的數整到堆頂,并將最大數和堆尾交換,并在之后的計算中忽略數組后端的最大數(last),直到堆頂(last=堆頂)

while(true)

{

adjustnode($i,$last,$arr);

if($i>1)

{

//移動節點指針,遍歷所有非葉子節點

$i–;

}

else

{

//臨界點last=1,既所有排序完成

if($last==1)break;

//當i為1時表示每一次的堆整理都將得到最大數(堆頂,$arr[1]),重復在根節點調整堆

swap($arr[$last],$arr[1]);

//在數組尾部按大小順序保留最大數,定義臨界點last,以免整理堆時重新打亂數組后面已排序好的元素

$last–;

}

}

//彈出第一個數組元素

array_shift($arr);

}

//整理當前樹節點($n),臨界點$last之后為已排序好的元素

functionadjustnode($n,$last,&$arr)

{

$l=$n<<1;//$n的左孩子位

if(!isset($arr[$l])||$l>$last)return;

$r=$l+1;//$n的右孩子位

//如果右孩子比左孩子大,則讓父節點的右孩子比

if($r<=$last&&$arr[$r]>$arr[$l])$l=$r;

//如果其中子節點$l比父節點$n大,則與父節點$n交換

if($arr[$l]>$arr[$n])

{

//子節點($l)的值與父節點($n)的值交換

swap($arr[$l],$arr[$n]);

//交換后父節點($n)的值($arr[$n])可能還小于原子節點($l)的子節點的值,所以還需對原子節點($l)的子節點進行調整,用遞歸實現

adjustnode($l,$last,$arr);

}

}

//交換兩個值

functionswap(&$a,&$b)

{

$a=$a^$b;

$b=$a^$b;

$a=$a^$b;

}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/257484.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/257484.shtml
英文地址,請注明出處:http://en.pswp.cn/news/257484.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Odoo (OpenERP/TinyERP)-10.0 (Debian 8)

平臺&#xff1a; Ubuntu 類型&#xff1a; 虛擬機鏡像 軟件包&#xff1a; odoo-10.0commercial erp odoo open source openerp tinyerp服務優惠價: 按服務商許可協議 云服務器費用:查看費用 立即部署產品詳情 產品介紹Odoo https://www.odoo.com/ &#xff08;前Op…

iOS開發- 藍牙后臺接收數據(BLE4.0)

最近在做一個藍牙相關的項目, 需要在應用進入后臺, 或者手機屬于鎖屏狀態的情況下, 仍然保持藍牙連接, 并且能正常接收數據。 本來以后會很麻煩, 但是學習了下..發現就2步而已。簡單的不能再簡單了。 好了。下面是具體實現辦法。 1.在xxx-info.plist文件中, 新建一行 Required…

貪心(數據結構):COGS 468. [NOI2010]超級鋼琴

★★★☆ 輸入文件&#xff1a;piano.in 輸出文件&#xff1a;piano.out 簡單對比 時間限制&#xff1a;2 s 內存限制&#xff1a;512 MB 超級鋼琴 【問題描述】 小Z是一個小有名氣的鋼琴家&#xff0c;最近C博士送給了小Z一架超級鋼琴&#xff0c;小Z希望能夠用這架…

java實現選擇排序 帶打印,選擇排序算法的JAVA實現

選擇排序算法的JAVA實現package Utils.Sort;/***利用選擇排序法對數組排序&#xff0c;數組中元素必須實現了Comparable接口。*/public class ChooseSort implements SortStrategy{/***對數組obj中的元素以選擇排序算法進行排序*/public void sort(Comparable[] obj){if (obj …

angularjs初始化時不顯示模板內容, 不顯示html, 不顯示template

template的內容可能在需要的數據準備好之前就顯示出來了, ng-cloak可以解決這個問題 ng-cloak <div id"template1" ng-cloak>{{ hello }}</div> <div id"template2" class"ng-cloak">{{ world }}</div>

左右箭頭滑動列表

//slideshow 左右箭頭滑動一組li焦點圖 autoSlide();function autoSlide(){clearAutoSsetInterval(autoFunS,5000);}function autoFunS(){var loc$(".slideshow-box ul").css("left");if(loc"-2370px"){loc"1185";}var newlocparseInt…

20159206《網絡攻防實踐》第四周學習總結

20159206《網絡攻防實踐》第四周學習總結 教材學習內容總結 本章主要介紹了網絡嗅探和協議分析 網絡嗅探是一種常用的竊聽技術&#xff0c;利用計算機的網絡接口截獲目的地為其他計算機的數據報文&#xff0c;以監聽數據流中所包含的用戶賬戶密碼或私密信息等。 網絡泄灘具有很…

四六級php,詳解四六級查詢API+網頁

這個API是第三方API&#xff0c;第三方API的工作原理大都基于此&#xff0c;本文主要起一反三之作用&#xff0c;代碼的不處周之還望及時指出。開發環境&#xff1a;WinServer2012 php7.0 Apache2.4.8思路&#xff1a;向官方查詢界面傳遞參數&#xff0c;使用curl抓取結果網頁…

終于把joomla 的 protostar 模版的菜單,從垂直改到水平了

protostar-applying-menu-class-suffixes-horizontal-vs-vertical-menus.html joomla 3.7.5 附帶的這個template , 菜單丑的要死。 估計是新改的。 看網上的其他站點都沒這毛病。 最后終于找到解決方法了。“ nav-pills“ 前面是有空格的 To make the menu horizonal, you can …

Find non-overlap jobs with max cost

Given a set of n jobs with [start time, end time, cost] find a subset so that no 2 jobs overlap and the cost is maximum.Job: &#xff08;start_time, end_time] --- cost 如果只是求maxCost, 一維就可以做。 但是如果要知道有選了哪些job&#xff0c;則需要存成二維。…

php 跨區域,PHP跨時區的功能實現

現在有一個跨時區的應用&#xff0c;不同時區登錄的用戶需要看到自己時區的時間&#xff0c;同時也要能夠進行時區的切換。我的思路是&#xff0c;系統中所有存儲的時間都是GMT(UTC)時間&#xff0c;用戶登錄時&#xff0c;根據用戶所在的時區進行對應的顯示。首先了解一下PHP中…

js實現向上滾動效果

源碼&#xff1a;<style type"text/css"> #up_zzjs{border:1px solid #ccc;width:170px;height:182px;line-height:20px;overflow:hidden;} #up_zzjs #up_li{list-style-type:none;margin:0;padding:0;margin-left:6px;} /*系統支持ie8就選line-heigh…

利用數據的商業智能分析工具

商業智能可以定義為獲取和轉換原始數據的技術和工具&#xff0c;這些信息可以為業務運營提供有意義的好處。 商業智能的發展 商業智能&#xff08;BI&#xff09;是一個可追溯到19世紀中期的術語&#xff0c;基本上是一樣的定義。但作為結構化數據的自動化處理的參考&#xff0…

管理之道(三) - 不要吝惜贊美

多一句贊美 人們相互希望得越多&#xff0c;想要給予對方的越多……就必定越親密。   幾天前&#xff0c;我和一位朋友在紐約搭計程車&#xff0c;下車時&#xff0c;朋友對司機說&#xff1a;“謝謝&#xff0c;搭你的車十分舒適。”這司機聽了愣了一愣&#xff0c;然后說&a…

優酷視頻整段代理php,thinkphp仿優酷帶數據源碼|php仿優酷視頻源碼帶后臺功能強大...

本項目是仿優酷官網&#xff0c;優酷官網是一個集多種知識面為一體的網站&#xff0c;能全面的鍛煉我們的技能,所以我們決定仿優酷網。本項目后臺主要實現了&#xff1a;用戶管理、分類管理、視頻管理、評論管理、權限管理、輪播管理、網站配置和廣告管理以及登錄退出等模塊。前…

Centos7安裝Oracle JDK

查看Linux是否自帶的JDK&#xff0c;如有openJDK&#xff0c;則卸載1 java -version 1 rpm -qa | grep -E ^open[jre|jdk]|j[re|dk] 卸載openjdk1 su root 2 3 yum -y remove java java-1.7.0-openjdk 下載oracle jdk1 wget --no-cookies --header "Cookie: oraclelice…

前端每周清單第 30 期:WebVR 指南,Vue 代碼分割范式,理想的 React 架構特性

前端每周清單專注前端領域內容&#xff0c;以對外文資料的搜集為主&#xff0c;幫助開發者了解一周前端熱點&#xff1b;分為新聞熱點、開發教程、工程實踐、深度閱讀、開源項目、巔峰人生等欄目。歡迎關注【前端之巔】微信公眾號&#xff08;ID&#xff1a;frontshow&#xff…

Oracle(3)——Oracle圖形界面工具創建數據庫

具體操作步驟詳情&#xff1a; 1.圖形界面工具首界面 Database Configuration Assistant 點擊下一步 2.默認 點擊下一步 3.默認 點擊下一步 4.設置全局數據庫名、SID 為新建數據庫起一個“全局數據庫名”&#xff0c;比如這里對數據庫名和SID&#xff1a;FKXT 點擊下一步 5.設置…

rsa 加密 js php,security.js+RSA做出加密功能

這次給大家帶來security.jsRSA做出加密功能&#xff0c;的注意事項有哪些&#xff0c;下面就是實戰案例&#xff0c;一起來看一下。在項目中遇到要對用戶輸入的密碼進行RSA加密的需求&#xff0c;總結一下實現過程&#xff1a;JS rsa加密加密//引入security.js文件var btn doc…

多線程面試題系列(12):多線程同步內功心法——PV操作上

上面的文章講解了在Windows系統下實現多線程同步互斥的方法&#xff0c;為了提高在實際問題中分析和思考多個線程之間同步互斥問題的能力&#xff0c;接下來將講解PV操作&#xff0c;這也是操作系統中的重點和難點。本文將會先簡要介紹下PV操作的來源和基本使用方法&#xff0c…