1. 程式人生 > 其它 >PHP資料結構(二十三) ——快速排序

PHP資料結構(二十三) ——快速排序

PHP資料結構(二十三)——選擇排序

(原創內容,轉載請註明來源,謝謝)

一、概述

選擇排序的基本思想,是每一趟在n-i+1(i=1,2…n-1)個記錄中選取關鍵字最小的記錄作為第i個記錄。選擇排序分為簡單選擇排序、樹形選擇排序、堆排序。

二、簡單選擇排序

簡單選擇排序,即完全按照上述的說法進行排序。時間複雜度O(n2)。由於比較簡單,不具體描述。

1、演算法

1)遍歷整個陣列,找到最小值放置於第一個位置。

2)遍歷從第二個位置至末尾的陣列,找到最小值放在第二個位置。

3)重複上述操作直到排序完成。

2、實現原始碼如下

                  //簡單選擇排序
                  public function simpleSelectSort(array$arr = array()){
                   $arr= $this->_checkNeedSort($arr);
                   if(!$arr){
                            return$arr;
                   }
                   //長度只有1直接返回
                   if(1== count($arr)){
                            return$arr;
                   }
                   //遍歷陣列,第i次取第i小值放置於第i-1的位置
                   //由於n-1次已經可以遍歷完,故不需要第n次遍歷
                   for($i=0;$i<count($arr)-1;$i++){
                            //暫存臨時最小值與關鍵字
                            $min= $arr[$i];
                            $minIndex= $i;
                            for($j=$i+1;$j<count($arr);$j++){
                                     //如果最小值比暫存小,則更新暫存
                                     if($arr[$j]<$min){
                                               $min= $arr[$j];
                                               $minIndex= $j;
                                     }
                            }
                            //將暫存的最小值替換到第i個位置
                            $tmp= $arr[$i];
                            $arr[$i]= $arr[$minIndex];
                            $arr[$minIndex]= $tmp;
                   }
                   return$arr;
         }

三、樹形選擇排序

樹形選擇排序是利用簡單選擇排序在每一次排序的結果進行的排序,又被稱為錦標賽排序。兩兩進行排序,小的值再兩兩排序,直至選出最小值。再進行第二輪的排序選擇次小值。樹形選擇排序時間複雜度是O(nlogn)。

1、演算法

1)構造一棵滿二叉樹,其葉子節點都在同一層,且葉子節點包含了所有的待排序陣列。

2)兩兩節點進行比較,關鍵字對應的值小的那一個進入父節點,葉子節點的位置值置成無窮大。

3)直至比出根節點。則為最小值。

4)再次遍歷此樹,直至構造完成全部的值。

實際實現中,由於樹形選擇排序必須用完全二叉樹,而完全二叉樹的父節點和其子節點的編號關係是確定的,可以用陣列來表達。

陣列表達的方式,假設根節點為0,從左往右、從上往下編號,則第一層為0,第二層為1、2(父節點都是0),第三層為3、4、5、6(父節點3、4的是1,5、6的是2)。

依次類推,兩兩一組,可以確定,父節點編號=(左節點編號-1)/2,或父節點編號=右節點編號/2-1。因此可以兩兩一組進行遍歷。

2、樹形選擇排序如下圖所示(圖片來自網路):

3、實現原始碼如下

         //樹形選擇排序
         publicfunction treeSelectSort(array $arr = array()){
                   $arr= $this->_checkNeedSort($arr);
                   if(!$arr){
                            return$arr;
                   }
                   //長度只有1直接返回
                   if(1== count($arr)){
                            return$arr;
                   }
                   //確定陣列長度,即完全二叉樹葉子節點的個數
                   $arrLength= count($arr);
                   //完全二叉樹
                   $arrTreeNodes= array();
                   //完全二叉樹節點總數為葉子節點個數*2-1
                   $treeNodesLength= 2 * $arrLength -1;
                   //倒序將陣列放置於完全二叉樹陣列的末尾,構造葉子節點
                   for($i=$arrLength-1,$j=0;$i>=0;$i--,$j++){
                            $arrTreeNodes[$treeNodesLength-1-$j]= $arr[$i];
                   }
                   //補全完全二叉樹葉子節點以外的節點。i每兩個進行比較,從最後一個節點起,相當於每次都在右節點,因此其父節點位置為i/2-1
                   for($i=$treeNodesLength-1;$i>0;$i=$i-2){
                            //取小的值為父節點的值
                            $arrTreeNodes[$i/2-1]= $arrTreeNodes[$i] < $arrTreeNodes[$i-1] ? $arrTreeNodes[$i] :$arrTreeNodes[$i-1];
                   }
                   //從0起生成最終的陣列
                   $low= 0;
                   while($low< $arrLength){
                            //每次生成樹後,其當前的第一個值(下標是0)即為最小值
                            $curMin= $arrTreeNodes[0];
                            //最小值放入最終的陣列
                            $arr[$low++]= $curMin;
                            //從最後一個元素起,找結果為最小值的下標
                            $curMinIndex= $treeNodesLength - 1;
                            //相等時找到下標
                            while($curMin!= $arrTreeNodes[$curMinIndex]){
                                     $curMinIndex--;
                            }
                            //將結果最小的值設定成無窮大
                            $arrTreeNodes[$curMinIndex]= INF;
                            //找其父節點即父節點的父節點,直至根節點
                            while(0< $curMinIndex){
                                     //如果是偶數,說明是右節點,父節點是i/2-1,要比較的是i和i-1
                                     if(0== $curMinIndex%2){
                                             $arrTreeNodes[$curMinIndex/2-1]= $arrTreeNodes[$curMinIndex] < $arrTreeNodes[$curMinIndex-1] ?$arrTreeNodes[$curMinIndex] : $arrTreeNodes[$curMinIndex-1];
                                               $curMinIndex= $curMinIndex / 2 - 1;
                                     }else{
                                               //如果是奇數,說明是左節點,父節點是(i-1)/2,要比較的是i和i+1
                                               $arrTreeNodes[($curMinIndex-1)/2]= $arrTreeNodes[$curMinIndex] < $arrTreeNodes[$curMinIndex+1] ?$arrTreeNodes[$curMinIndex] : $arrTreeNodes[$curMinIndex+1];
                                               $curMinIndex= ($curMinIndex - 1) / 2;                                       
                                     }
                            }
                   }
                   return$arr;
         }

4、評價

樹形選擇排序由於需要額外的空間較多,而且有大量的INF(PHP中表示無窮大的值),浪費空間較多,實際中不常用,而往往使用優化版的樹形選擇排序——堆排序。

堆排序的內容見下文。

——written by linhxx 2017.07.20

相關閱讀:

PHP資料結構(二十二) ——快速排序

PHP資料結構(二十一) ——希爾排序

PHP資料結構(二十) ——其他插入排序

PHP資料結構(十九) ——B+樹

PHP資料結構(十八) ——直接插入排序

PHP資料結構(十七) ——內部排序綜述

PHP資料結構(十六) ——B樹

PHP資料結構(十五) ——雜湊表​

PHP資料結構(十四) ——鍵樹(雙鏈樹)

PHP資料結構(十三) ——動態查詢表(二叉排序樹)

PHP資料結構(十二) ——靜態查詢表​

PHP資料結構(十一) ——圖的連通性問題與最小生成樹演算法(2)

PHP資料結構(十一) ——圖的連通性問題與最小生成樹演算法(1)

PHP資料結構(十) ——有向無環圖與拓撲演算法

PHP資料結構(九) ——圖的定義、儲存與兩種方式遍歷

PHP資料結構(八) ——赫夫曼樹實現字串編解碼(實踐2)

PHP資料結構(八) ——赫夫曼樹實現字串編解碼(實踐1)

PHP資料結構(八) ——赫夫曼樹實現字串編解碼(理論)

PHP資料結構(七) ——串與實現KMP演算法

PHP資料結構(六) ——樹與二叉樹之概念及儲存結構

PHP資料結構(六) ——陣列的相乘、廣義表

PHP資料結構(五) ——陣列的壓縮與轉置

PHP資料結構(四) ——佇列

PHP資料結構(三)——運用棧實現括號匹配

PHP資料結構(二)——鏈式結構線性表

PHP資料結構(一)——順序結構線性表