php堆排序詳解

來源:互聯網
上載者:User
堆排序(Heapsort)是指利用堆積樹(堆)這種資料結構所設計的一種排序演算法,它是選擇排序的一種。可以利用數組的特點快速定位指定索引的元素。堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i]。在數組的非降序排序中,需要使用的就是大根堆,因為根據大根堆的要求可知,最大的值一定在堆頂。

堆的定義

一個完全二叉樹中,任意父結點總是大於或等於(小於或等於)任何一個子節點,則為大頂堆(小頂堆)。

堆的數組儲存方式

完全二叉樹適合採用順序儲存的方式,因此一個數組可以看成一個完全二叉樹。

  • 節點編號:樹根起,自上層到下層,每層從左至右,給所有結點順序編號,能得到一個反映整個二叉樹結構的線性序列。

  • 編號特點:

從一個結點的編號就可推得其雙親,左、右孩子,兄弟等結點的編號。假設編號為i的結點是ki(1≤i≤n),則有:

  ①若i>1,則ki的雙親編號為i/2;若i=1,則Ki是根結點,無雙親。

  ②若2i≤n,則Ki的左孩子的編號是2i;否則,Ki無左孩子,即Ki必定是葉子。因此完全二叉樹中編號i>n/2的結點必定是葉結點。

  ③若2i+1≤n,則Ki的右孩子的編號是2i+1;否則,Ki無右孩子。

註:ki(0≤i≤n)滿足數組下標時,則可能的左右孩子分別為2i+1、2i+2。

堆排序的思想(以大頂堆為例)

利用堆頂記錄的是最大關鍵字這一特性,每一輪取堆頂元素放入有序區,就類似選擇排序每一輪選擇一個最大值放入有序區,可以把堆排序看成是選擇排序的改進。

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

  2. 將堆頂元素R[0]與最後一個元素R[n]交換,此時得到新的無序區(R0,R1,R2,......Rn-1)和新的有序區(Rn);

  3. 由於交換後新的堆頂R[0]可能違反堆的性質,因此需要對當前無序區(R0,R1,R2,......Rn-1)調整為新堆。

不斷重複此2、3步驟直到有序區的元素個數為n-1,則整個排序過程完成。

演算法分析

篩選演算法

//最難理解的地方

  • 目標:一個所有子樹都為堆的完全二叉樹。意思就是這個二叉樹只差跟節點不滿足堆的結構。//很重要,很重要,很重要

如:

  • 方法:首先將root和它的左右子樹的根結點進行比較,把最大的元素交換到root節點;然後順著被破壞的路徑一路調整下去,直至葉子結點,就得到新的堆。

  • 運用:1.在上文提到的堆排序思想,2-3步驟中將無序區調整為堆的時候用到。

2.初始化堆

初始化堆

從最後一個非葉子節點i(i=n/2,n為節點個數)開始,將以i為根節點的二叉樹通過篩選調整為堆。以第一張圖為例,編號順序為8、7、6...1。

從最後一個非葉子節就保證了篩選演算法的正確性,因為篩選演算法的目標是一個所有子樹都為堆的完全二叉樹。

php實現堆排序:<?php//堆排序,對簡單排序的改進  function swap(array &$arr,$a,$b)  {      $temp=$arr[$a];      $arr[$a]=$arr[$b];      $arr[$b]=$temp;  }  //調整$arr[$start]的關鍵字,$arr[$start]、$arr[$start+1]、、、$arr[$end]成為一個大根堆(根節點最大的完全二叉樹)  //注意:這裡節點s的左右孩子是 2*s +1 和 2*s+2(數組開始下標為0時)   function HeapAdjust(array &$arr $start $end)   {       $temp= $arr[$start];       //沿關鍵字較大的孩子節點向下篩選       //左右孩子計算 (這裡數組的開始下標為0)       //左邊孩子 2*$start+1,右邊孩子 2*$start+2       for ($j=2*$start+1; $j <=$end; $j=2*$j+1) {            if ($j !=$end &&$arr[$j] <$arr[$j+1]) {               $j++;  //轉化為右邊孩子           }           if ($temp >=$arr[$j]) {               break;  //已經滿足大根堆           }           //將根節點設定為子節點的較大值           $arr[$start]=$arr[$j];           //繼續往下           $start=$j;       }       $arr[$start] =$temp;   }   function HeapSort(array &$arr)   {       $count=count($arr);       //先將資料結構造成大根堆 (由於是完全二叉樹,所以這裡用floor($count/2-1),下標小於或等於這個數的節點都是有孩子的節點)       for ($i=floor($count /2)-1; $i >=0 ; $i--) {            HeapAdjust($arr,$i,$count);       }       for ($i=$count-1; $i >=0 ; $i--) {        //將堆頂元素與最後一個元素交換,擷取到最大元素(交換後的最後一個元素),將最大元素放到數組末尾           swap($arr,0,$i);       //經過交換,將最後一個元素(最大元素)脫離大根堆,並將未經排序的新數($arr[0...$i-1])重新調整為大根堆           HeapAdjust($arr,0,$i-1);       }   }   $arr=array(4,1,5,9);   HeapSort($arr);   v

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.