摘要:排序嚴(yán)格來說不算數(shù)據(jù)結(jié)構(gòu),更應(yīng)該歸于算法一類,因?yàn)閿?shù)據(jù)結(jié)構(gòu)指的是數(shù)據(jù)與數(shù)據(jù)之間的關(guān)系,排序參與其中,更多的是讓數(shù)據(jù)狀態(tài)發(fā)生了改變。
引子排序嚴(yán)格來說不算數(shù)據(jù)結(jié)構(gòu),更應(yīng)該歸于算法一類,因?yàn)閿?shù)據(jù)結(jié)構(gòu)指的是數(shù)據(jù)與數(shù)據(jù)之間的關(guān)系,排序參與其中,更多的是讓數(shù)據(jù)狀態(tài)發(fā)生了改變。
于是,我們開始用PHP來聊聊算法。
其實(shí)有一句話說的是不錯的,“不必重復(fù)造輪子”,所以下面我將引用別人的文章作為本文的引文,直觀的感受一下排序過程,同時我將加入自己的理解和代碼+注釋(其實(shí)很多話都在注釋里面了)。事實(shí)上,如果作為一名純粹的PHP Developer在日常開發(fā)中,有很多數(shù)據(jù)結(jié)構(gòu)與算法是封裝好了的,之所以要自己動手實(shí)現(xiàn)一下函數(shù)庫,我認(rèn)為有的人是為了裝逼,當(dāng)然有的人也確實(shí)能從中領(lǐng)悟到更復(fù)雜的邏輯和計(jì)算機(jī)底層執(zhí)行規(guī)律從而提高編程能力,我是為了應(yīng)試,這同樣是一種能力。
引文原文出自:[直觀學(xué)習(xí)排序算法] 視覺直觀感受若干常用排序算法
1 快速排序
介紹:
快速排序是由東尼·霍爾所發(fā)展的一種排序算法。在平均狀況下,排序 n 個項(xiàng)目要Ο(n log n)次比較。在最壞狀況下則需要Ο(n2)次比較,但這種狀況并不常見。事實(shí)上,快速排序通常明顯比其他Ο(n log n) 算法更快,因?yàn)樗膬?nèi)部循環(huán)(inner loop)可以在大部分的架構(gòu)上很有效率地被實(shí)現(xiàn)出來,且在大部分真實(shí)世界的數(shù)據(jù),可以決定設(shè)計(jì)的選擇,減少所需時間的二次方項(xiàng)之可能性。
步驟:
從數(shù)列中挑出一個元素,稱為 "基準(zhǔn)"(pivot),
重新排序數(shù)列,所有元素比基準(zhǔn)值小的擺放在基準(zhǔn)前面,所有元素比基準(zhǔn)值大的擺在基準(zhǔn)的后面(相同的數(shù)可以到任一邊)。在這個分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置。這個稱為分區(qū)(partition)操作。
遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。
排序效果:
代碼實(shí)現(xiàn):
= $pivot){ $high --; #如果數(shù)組的高值端(假定)大于樞軸單元,則高值端從后往前移動,說明真的是高值不必交換 } swap($arr,$low,$high); #直到高值端小等于樞軸單元,則交換元素,將較大值放到高值端,較小值放到低值端,注意交換的是數(shù)組單元 while($low < $high && $arr[$low] <= $pivot){ $low ++; #如果數(shù)組的低值端(假定)小于樞軸單元(注意,因?yàn)榇饲發(fā)ow和high已經(jīng)交換過值了,現(xiàn)在的$arr[$low]已經(jīng)不等于原先的值了),則高值端從后往前移動 } swap($arr,$low,$high); #直到低值端大等于樞軸單元,則交換元素,將較大值放到高值端,較小值放到低值端 } return $low; #隨著low不斷++,high不斷--,它們在某處相遇,即樞軸下標(biāo),返回 } $arr = [4,7,3,2,7,6,8]; $res = main($arr); echo ""; print_r($res);2 歸并排序
介紹:歸并排序(Merge sort,臺灣譯作:合并排序)是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應(yīng)用
步驟:
申請空間,使其大小為兩個已經(jīng)排序序列之和,該空間用來存放合并后的序列
設(shè)定兩個指針,最初位置分別為兩個已經(jīng)排序序列的起始位置
比較兩個指針?biāo)赶虻脑兀x擇相對小的元素放入到合并空間,并移動指針到下一位置
重復(fù)步驟3直到某一指針達(dá)到序列尾
將另一序列剩下的所有元素直接復(fù)制到合并序列尾
排序效果:代碼實(shí)現(xiàn):
"; print_r($res);3 堆排序
介紹:堆積排序(Heapsort)是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法。堆是一個近似完全二叉樹的結(jié)構(gòu),并同時滿足堆性質(zhì):即子結(jié)點(diǎn)的鍵值或索引總是小于(或者大于)它的父節(jié)點(diǎn)。
步驟:
這里補(bǔ)充一下原文空白
a.構(gòu)造大(小)頂堆
b.每構(gòu)造出一個頂堆,便能獲取到最大或最小值,與尾節(jié)點(diǎn)交換,取出
c.循環(huán)構(gòu)造頂堆,取值排序效果:
代碼實(shí)現(xiàn):
0;$s--){ createHeap($arr,$s,$m); } return $arr; } /** * TODO:構(gòu)建大頂堆 * @param $arr Array 待構(gòu)數(shù)組 * @param $s int 開始下標(biāo)(二叉樹中最后一個擁有兩個孩子的父節(jié)點(diǎn)序號) * @param $m int 數(shù)組長度 例: 50 / 30 60 / 70 20 (這是不滿足堆的定義的,需要重新構(gòu)造) */ function createHeap(&$arr,$s,$m){ $temp = $arr[$s]; #二叉樹中最后一個擁有兩個孩子的父節(jié)點(diǎn) for($i=2*$s;$i<$m;$i*=2){ if($arr[$i]<$arr[$i+1]){ # i=2s i+1=2s+1 是s節(jié)點(diǎn)的左右孩子節(jié)點(diǎn),先左右孩子節(jié)點(diǎn)比較大小,找出較大值 $i++; } if($temp>=$arr[$i]){ #再將較大值與父節(jié)點(diǎn)比較,如果父節(jié)點(diǎn)大跳出循環(huán) break; } #如果父節(jié)點(diǎn)小,則交換父節(jié)點(diǎn)和該子節(jié)點(diǎn)值(無須額外輔助空間 空間復(fù)雜度為O(1)) $arr[$s] = $arr[$i]; $s = $i; } $arr[$s] = $temp; } /** * TODO:堆排序 */ function heapSort(&$arr){ $length = count($arr)-1; for($i=$length;$i>1;$i--){ #這里i不需要和本身交換,所以不需要等于1 swap($arr,1,$i); createHeap($arr,1,$i);#注意這里數(shù)組的長度會遞減 } return $arr; } $data = [0,5,1,9,3,7,4,8,6,2]; $res = main($data); //$heapArr = heapSort($res); echo ""; print_r($data);4 選擇排序
介紹:選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理如下。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續(xù)尋找最小元素,然后放到排序序列末尾。以此類推,直到所有元素均排序完畢。
排序效果:
詳細(xì)過程:
5 冒泡排序
介紹:冒泡排序(Bubble Sort,臺灣譯為:泡沫排序或氣泡排序)是一種簡單的排序算法。它重復(fù)地走訪過要排序的數(shù)列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數(shù)列的工作是重復(fù)地進(jìn)行直到?jīng)]有再需要交換,也就是說該數(shù)列已經(jīng)排序完成。這個算法的名字由來是因?yàn)樵叫〉脑貢?jīng)由交換慢慢“浮”到數(shù)列的頂端。
步驟:
比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
對每一對相鄰元素作同樣的工作,從開始第一對到結(jié)尾的最后一對。在這一點(diǎn),最后的元素應(yīng)該會是最大的數(shù)。
針對所有的元素重復(fù)以上的步驟,除了最后一個。
持續(xù)每次對越來越少的元素重復(fù)上面的步驟,直到?jīng)]有任何一對數(shù)字需要比較。
排序效果:詳細(xì)過程:
6 插入排序
介紹:插入排序(Insertion Sort)的算法描述是一種簡單直觀的排序算法。它的工作原理是通過構(gòu)建有序序列,對于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應(yīng)位置并插入。插入排序在實(shí)現(xiàn)上,通常采用in-place排序(即只需用到O(1)的額外空間的排序),因而在從后向前掃描過程中,需要反復(fù)把已排序元素逐步向后挪位,為最新元素提供插入空間。
步驟:
從第一個元素開始,該元素可以認(rèn)為已經(jīng)被排序
取出下一個元素,在已經(jīng)排序的元素序列中從后向前掃描
如果該元素(已排序)大于新元素,將該元素移到下一位置
重復(fù)步驟3,直到找到已排序的元素小于或者等于新元素的位置
將新元素插入到該位置中
重復(fù)步驟2
排序效果:
(暫無)
詳細(xì)過程:7 希爾排序
介紹:希爾排序,也稱遞減增量排序算法,是插入排序的一種高速而穩(wěn)定的改進(jìn)版本。
希爾排序是基于插入排序的以下兩點(diǎn)性質(zhì)而提出改進(jìn)方法的:
插入排序在對幾乎已經(jīng)排好序的數(shù)據(jù)操作時, 效率高, 即可以達(dá)到線性排序的效率
但插入排序一般來說是低效的, 因?yàn)椴迦肱判蛎看沃荒軐?shù)據(jù)移動一位
排序效果:
有時間再更。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/25970.html
摘要:數(shù)據(jù)結(jié)構(gòu)基本概念拆成數(shù)據(jù)和結(jié)構(gòu)兩個詞來看,結(jié)構(gòu)就是經(jīng)過排列組合后映射到內(nèi)存的一種關(guān)系,你想想化學(xué)中的分子結(jié)構(gòu)就明白了,所以數(shù)據(jù)結(jié)構(gòu)就是數(shù)據(jù)之間的一種關(guān)系,利用這些關(guān)系去處理強(qiáng)邏輯問題。該結(jié)構(gòu)的數(shù)據(jù)元素之間存在著多對多的關(guān)系,也稱網(wǎng)狀結(jié)構(gòu)。 數(shù)據(jù)結(jié)構(gòu)起源與起因 起因: ??????因?yàn)楝F(xiàn)實(shí)世界問題大多數(shù)是復(fù)雜的而非簡單的數(shù)值計(jì)算,將數(shù)據(jù)進(jìn)行適當(dāng)?shù)呐判颉⒔M合將有利于計(jì)算機(jī)對復(fù)雜性邏輯問題的...
摘要:數(shù)據(jù)結(jié)構(gòu)基本概念拆成數(shù)據(jù)和結(jié)構(gòu)兩個詞來看,結(jié)構(gòu)就是經(jīng)過排列組合后映射到內(nèi)存的一種關(guān)系,你想想化學(xué)中的分子結(jié)構(gòu)就明白了,所以數(shù)據(jù)結(jié)構(gòu)就是數(shù)據(jù)之間的一種關(guān)系,利用這些關(guān)系去處理強(qiáng)邏輯問題。該結(jié)構(gòu)的數(shù)據(jù)元素之間存在著多對多的關(guān)系,也稱網(wǎng)狀結(jié)構(gòu)。 數(shù)據(jù)結(jié)構(gòu)起源與起因 起因: ??????因?yàn)楝F(xiàn)實(shí)世界問題大多數(shù)是復(fù)雜的而非簡單的數(shù)值計(jì)算(例如:圖像、視頻、聲音),將數(shù)據(jù)進(jìn)行適當(dāng)?shù)呐判颉⒔M合將有利...
摘要:回來更新一波,最近刷劍指,才又發(fā)現(xiàn)樹真是一個大頭,二叉樹的題目和變化運(yùn)用好多啊二叉樹算法引子很多人說二叉樹沒什么卵用,我覺得是他的工資和公司讓他跨不過這個坎還有很多人學(xué)了一些樹的知識,發(fā)現(xiàn)也用不上,我想說的是,讀一本書體現(xiàn)不了這本書 回來更新一波,最近刷《劍指offer》,才又發(fā)現(xiàn)樹真是一個大頭,二叉樹的題目和變化運(yùn)用好多啊~ /** * PHP二叉樹算法 * Create...
摘要:回來更新一波,最近刷劍指,才又發(fā)現(xiàn)樹真是一個大頭,二叉樹的題目和變化運(yùn)用好多啊二叉樹算法引子很多人說二叉樹沒什么卵用,我覺得是他的工資和公司讓他跨不過這個坎還有很多人學(xué)了一些樹的知識,發(fā)現(xiàn)也用不上,我想說的是,讀一本書體現(xiàn)不了這本書 回來更新一波,最近刷《劍指offer》,才又發(fā)現(xiàn)樹真是一個大頭,二叉樹的題目和變化運(yùn)用好多啊~ /** * PHP二叉樹算法 * Create...
摘要:概述本系列文章主要運(yùn)用以實(shí)現(xiàn)常用的數(shù)據(jù)結(jié)構(gòu),包括基本結(jié)構(gòu)展現(xiàn)基本結(jié)構(gòu)實(shí)現(xiàn)應(yīng)用場景實(shí)現(xiàn)文章總體來說畢竟淺顯,適合新手閱讀和學(xué)習(xí)討論,歡迎指教,其實(shí)每一個作者都是期待讀者的反饋的。 之前都放在文章里,還是有點(diǎn)零散,剛好SF專欄門檻較低,便尋思著把文章重新整理一遍,這里也謝謝SF了。 概述 本系列文章主要運(yùn)用PHP以實(shí)現(xiàn)常用的數(shù)據(jù)結(jié)構(gòu),包括: 1.基本結(jié)構(gòu)展現(xiàn) 2.基本結(jié)構(gòu)實(shí)現(xiàn) 3.應(yīng)用場...
閱讀 1937·2021-11-24 09:39
閱讀 3522·2021-09-28 09:36
閱讀 3291·2021-09-06 15:10
閱讀 3446·2019-08-30 15:44
閱讀 1159·2019-08-30 15:43
閱讀 1802·2019-08-30 14:20
閱讀 2719·2019-08-30 12:51
閱讀 2037·2019-08-30 11:04