PHP的數(shù)組是數(shù)列Array,列表List,散列表/關(guān)聯(lián)數(shù)組/字典Hashtable的聚合體。是一個(gè)非常高級的數(shù)據(jù)結(jié)構(gòu)。也是一個(gè)優(yōu)秀的設(shè)計(jì)。

在開陽等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作按需網(wǎng)站設(shè)計(jì),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站制作,成都全網(wǎng)營銷,成都外貿(mào)網(wǎng)站制作,開陽網(wǎng)站建設(shè)費(fèi)用合理。
基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)只具備PHP數(shù)組的一部分功能,處理各種問題性能也不同。而PHP囊括、綜合了這些結(jié)構(gòu)的優(yōu)點(diǎn),所以說是一個(gè)高級結(jié)構(gòu)。
學(xué)好的關(guān)鍵在于掌握基礎(chǔ)的“數(shù)據(jù)結(jié)構(gòu)”和“算法”。
比如
如果我知道從算法的角度明白數(shù)列[0...n]的隨機(jī)操作比字典快,在密集計(jì)算時(shí)我就用數(shù)組,而少用$a['gg']這樣字典。這是一個(gè)小例子。
hashtable 中文應(yīng)該是翻譯為:哈希表。散列表(Hash table,也叫哈希表),是根據(jù)關(guān)鍵碼值(Key value)而直接進(jìn)行訪問的數(shù)據(jù)結(jié)構(gòu)。也就是說,它通過把關(guān)鍵碼值映射到表中一個(gè)位置來訪問記錄,以加快查找的速度。這個(gè)映射函數(shù)叫做散列函數(shù),存放記錄的數(shù)組叫做散列表。
具體進(jìn)一步的了解,建議你看計(jì)算機(jī)專業(yè)的數(shù)據(jù)結(jié)構(gòu)方面的教程。
PHP 使用HashTable來保存數(shù)組信息,md5/sha1都是哈希表的算法,具體的應(yīng)用比如:文件校驗(yàn)、數(shù)字簽名等。
注:為方便描述,下面的排序全為正序(從小到大排序)
假設(shè)有一個(gè)數(shù)組[a,b,c,d]
冒泡排序依次比較相鄰的兩個(gè)元素,如果前面的元素大于后面的元素,則兩元素交換位置;否則,位置不變。具體步驟:
1,比較a,b這兩個(gè)元素,如果ab,則交換位置,數(shù)組變?yōu)椋篬b,a,c,d]
2,比較a,c這兩個(gè)元素,如果ac,則位置不變,數(shù)組變?yōu)椋篬b,a,c,d]
3,比較c,d這兩個(gè)元素,如果cd,則交換位置,數(shù)組變?yōu)椋篬b,a,d,c]
完成第一輪比較后,可以發(fā)現(xiàn)最大的數(shù)c已經(jīng)排(冒)在最后面了,接著再進(jìn)行第二輪比較,但第二輪比較不必比較最后一個(gè)元素了,因?yàn)樽詈笠粋€(gè)元素已經(jīng)是最大的了。
第二輪比較結(jié)束后,第二大的數(shù)也會冒到倒數(shù)第二的位置。
依次類推,再進(jìn)行第三輪,,,
就這樣最大的數(shù)一直往后排(冒),最后完成排序。所以我們稱這種排序算法為冒泡排序。
選擇排序是一種直觀的算法,每一輪會選出列中最小的值,把最小值排到前面。具體步驟如下:
插入排序步驟大致如下:
快速排序是由東尼·霍爾所發(fā)展的一種排序算法。在平均狀況下,排序 n 個(gè)項(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ì)的選擇,減少所需時(shí)間的二次方項(xiàng)之可能性。
步驟:
從數(shù)列中挑出一個(gè)元素,稱為 “基準(zhǔn)”(pivot),
重新排序數(shù)列,所有元素比基準(zhǔn)值小的擺放在基準(zhǔn)前面,所有元素比基準(zhǔn)值大的擺在基準(zhǔn)的后面(相同的數(shù)可以到任一邊)。在這個(gè)分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置。這個(gè)稱為分區(qū)(partition)操作。
遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。
算法原理
下列動圖來自五分鐘學(xué)算法,演示了快速排序算法的原理和步驟。
步驟:
從數(shù)組中選個(gè)基準(zhǔn)值
將數(shù)組中大于基準(zhǔn)值的放同一邊、小于基準(zhǔn)值的放另一邊,基準(zhǔn)值位于中間位置
遞歸的對分列兩邊的數(shù)組再排序
代碼實(shí)現(xiàn)
function
quickSort($arr)
{
$len
=
count($arr);
if
($len
=
1)
{
return
$arr;
}
$v
=
$arr[0];
$low
=
$up
=
array();
for
($i
=
1;
$i
$len;
++$i)
{
if
($arr[$i]
$v)
{
$up[]
=
$arr[$i];
}
else
{
$low[]
=
$arr[$i];
}
}
$low
=
quickSort($low);
$up
=
quickSort($up);
return
array_merge($low,
array($v),
$up);
}
測試代碼:
$startTime
=
microtime(1);
$arr
=
range(1,
10);
shuffle($arr);
echo
"before
sort:
",
implode(',
',
$arr),
"\n";
$sortArr
=
quickSort($arr);
echo
"after
sort:
",
implode(',
',
$sortArr),
"\n";
echo
"use
time:
",
microtime(1)
-
$startTime,
"s\n";
測試結(jié)果:
before
sort:
1,
7,
10,
9,
6,
3,
2,
5,
4,
8
after
sort:
1,
2,
3,
4,
5,
6,
7,
8,
9,
10
use
time:
0.0009009838104248s
時(shí)間復(fù)雜度
快速排序的時(shí)間復(fù)雜度在最壞情況下是O(N2),平均的時(shí)間復(fù)雜度是O(N*lgN)。
這句話很好理解:假設(shè)被排序的數(shù)列中有N個(gè)數(shù)。遍歷一次的時(shí)間復(fù)雜度是O(N),需要遍歷多少次呢?至少lg(N+1)次,最多N次。
1)
為什么最少是lg(N+1)次?快速排序是采用的分治法進(jìn)行遍歷的,我們將它看作一棵二叉樹,它需要遍歷的次數(shù)就是二叉樹的深度,而根據(jù)完全二叉樹的定義,它的深度至少是lg(N+1)。因此,快速排序的遍歷次數(shù)最少是lg(N+1)次。
2)
為什么最多是N次?這個(gè)應(yīng)該非常簡單,還是將快速排序看作一棵二叉樹,它的深度最大是N。因此,快讀排序的遍歷次數(shù)最多是N次。
您可能感興趣的文章:PHP快速排序算法實(shí)例分析PHP四種排序算法實(shí)現(xiàn)及效率分析【冒泡排序,插入排序,選擇排序和快速排序】PHP排序算法之快速排序(Quick
Sort)及其優(yōu)化算法詳解PHP遞歸實(shí)現(xiàn)快速排序的方法示例php
二維數(shù)組快速排序算法的實(shí)現(xiàn)代碼PHP常用排序算法實(shí)例小結(jié)【基本排序,冒泡排序,快速排序,插入排序】PHP快速排序quicksort實(shí)例詳解
常見的php排序算法
本文匯總了常見的php排序算法,在進(jìn)行算法設(shè)計(jì)的時(shí)候有不錯(cuò)的借鑒價(jià)值。現(xiàn)分享給大家供參考之用。具體如下:
一、插入排序
用文字簡單的描述,比如說$arr = array(4,2,4,6,3,6,1,7,9); 這樣的一組數(shù)字進(jìn)行順序排序:
那么,首先,拿數(shù)組的第二個(gè)元素和第一元素比較,假如第一個(gè)元素大于第二元素,那么就讓兩者位置互換,接下來,拿數(shù)組的第三個(gè)元素,分別和第二個(gè),第一個(gè)元素比較,假如第三個(gè)元素小,那么就互換。依次類推。這就是插入排序,它的時(shí)間頻度是:1+2+...+(n-1)=(n^2)/2。則它的時(shí)間復(fù)雜度為O(n^2).
php實(shí)現(xiàn)代碼如下:
?phpfunction Sort($arr){ $count = count($arr); if($count2){ return $arr; } for($i=1;$i$count;$i++){ tmp="$arr[$i];" j=""=0$arr[$j]$arr[$i]){ return=""
二、選擇排序
選擇排序用語言描述的話,可以這樣,如:$arr = array(4,3,5,2,1);
首先,拿第一個(gè)和后面所有的比,找出最小的那個(gè)數(shù)字,然后和第一個(gè)數(shù)組互換(當(dāng)然,如果是第一個(gè)最小,那么就不用互換了),接著循環(huán),即:拿第二個(gè)和后面的比較,找出最小的數(shù)字,然后和第二個(gè)數(shù)字互換,依次類推,也就是說每次都是找出剩余最小的值。 可得到:第一次,時(shí)間頻度 是n, (第一個(gè)和后面的n-1個(gè)比較,找到最小的,再看是不是第一個(gè),不是第一個(gè)的話進(jìn)行互換) 在往后,依次是 減一 。 它的時(shí)間復(fù)雜度,也是O(n^2);
php實(shí)現(xiàn)代碼如下:
?phpfunction selectSort($arr){ $count = count($arr); if($count2){ return $arr; } for($i=0;$i$count;$i++){ $min=$i; for(j=$i+1;$j$count;$j++){$arr[$j]){ $min = $j; //找到最小的那個(gè)元素的下標(biāo) } } if($min!=$i){//如果下標(biāo)不是$i 則互換。 $tmp= $arr[$i]; $arr[$i] = $arr[$min]; $arr[$min] = $tmp; } } return $arr; }?
三、冒泡排序
冒泡排序其實(shí)上是和選擇排序相比,并無明顯差別。都是找到最小的,放到最左端。依次循環(huán)解決問題。差別在于冒泡排序的交換位置的次數(shù)較多,而選擇排序則是找到最小的元素的下標(biāo),然后直接和最左端的交換位置。
php實(shí)現(xiàn)代碼如下:
?phpfunction selectSort($arr){ $count = count($arr); if($count2){ return $arr; } for($i=0;$i$count;$i++){ for(j=$i+1;$j$count;$j++){$arr[$j]){ $tmp= $arr[$i]; $arr[$i] = $arr[$i]; $arr[$i] = $tmp; } } } return $arr; }?
四、快速排序
快速排序,用語言來形容的話,從數(shù)組中選擇一個(gè)值$a,然后和其余元素進(jìn)行比較,比$a大的放到數(shù)組right中,反之,放到數(shù)組left中。然后將left right 分別進(jìn)行遞歸調(diào)用,即:再細(xì)分left right ,最后進(jìn)行數(shù)組的合并。
php實(shí)現(xiàn)快速排序:
?phpfunction mySort($arr){ $count = count($arr); if($count2){ return $arr; } $key = $arr[0];//選擇第一個(gè)元素作為比較元素,可選其他 $left = array(); $right = array(); for($i=1;$i$count;$i++){ key=""=$arr[$i]){ $left[] = $arr[$i]; }else{ $right[] = $arr[$i]; } } $left = mySort($left); $right = mySort($right); $result = array_merge($left,$right); return $result; }?
五、歸并排序
其實(shí)歸并排序是一種拆分,合并的思想。和快速排序思想有共通之處,左邊一堆,右邊一堆,然后進(jìn)行合并。通過遞歸實(shí)現(xiàn)排序。 區(qū)別之處呢? 他們的區(qū)別也是思想上本質(zhì)的區(qū)別,快速排序的拆分,是選擇了特定的值進(jìn)行大小比較,從而分為left 和 right 。也就是小的一堆放入left,大的一堆放入right。而后,小的left 再細(xì)分為left1 right1。。。。通過進(jìn)行類似的遞歸完成排序。也就是說,一直細(xì)分下去,遞歸最末尾的left1就是最小值。
而歸并排序,是從幾何上的左右切分,一直遞歸切分成2或者1的'最小粒度的數(shù)組,然后才開始進(jìn)行比較大小,然后合并。此處的比較大小是:兒子left的元素 和兒子的right元素 進(jìn)行比較,而后進(jìn)行排序合并成為父親left或者right。在此,直到拿到各自排序合并完成最后兩個(gè)數(shù)組:最起初的left 和right,也僅僅直到他們各自的順序,并不能確認(rèn)整個(gè)數(shù)組的順序,還是需要通過最終的left right 比較后合并才能完成真正意義上的排序。
?phpfunction gbSort($arr){ if(count($arr)=1){return min="floor(count($arr)/2);//取中間數(shù)字進(jìn)行拆分" left="gbSort($left);" right="gbSort($right);" return="" function=""$right[0] ? array_shift($right) : array_shift($left); //進(jìn)行比較,小的移除,并且放入到數(shù)組$m中。 } return arr_merge($m,$left,$right);//進(jìn)行合并(由于不知道left right 哪個(gè)會為空,所以進(jìn)行統(tǒng)一合并)}?
六、堆排序
本例中fixDown函數(shù)實(shí)現(xiàn)對某一個(gè)節(jié)點(diǎn)的向下調(diào)整,這里默認(rèn)的是起始節(jié)點(diǎn)為1,方便計(jì)算父子節(jié)點(diǎn)關(guān)系
注:
起始節(jié)點(diǎn)為1的父子關(guān)系: 父節(jié)點(diǎn)k, 子節(jié)點(diǎn)為2K、2k+1 子節(jié)點(diǎn)j, 父節(jié)點(diǎn)為 floor(j/2) floor為向下取整
起始節(jié)點(diǎn)為0的父子關(guān)系: 父節(jié)點(diǎn)k, 子節(jié)點(diǎn)為2K+1, 2k+2 子節(jié)點(diǎn)j, 父節(jié)點(diǎn)為 floor((j-1)/2)
參數(shù)$k為調(diào)整點(diǎn)位置, $lenth為數(shù)組長度,也就是從1起始到最后一個(gè)節(jié)點(diǎn)的坐標(biāo).
?phpfunction fixDown($arr, $k, $lenth){while(2*$k=$lenth) { //只要當(dāng)前節(jié)點(diǎn)有子節(jié)點(diǎn), 就需要繼續(xù)該循環(huán) $j = $k*2; if ($j$lenth $arr[$j]$arr[$j+1]) $j++; // 只要子節(jié)點(diǎn)有右節(jié)點(diǎn),且右節(jié)點(diǎn)比左節(jié)點(diǎn)大,那么切換到右節(jié)點(diǎn)操作。 if ($arr[$j] $arr[$k]) break; // 如果子節(jié)點(diǎn)都沒有父節(jié)點(diǎn)大, 那么調(diào)整結(jié)束。 exch($arr[$j], $arr[$k]); $k = $j; }}function exch($a, $b) { $tmp = $a; $a = $b; $b = $tmp;}function headSort($arr){ $len = count($arr); array_unshift($arr, NULL); for($i=$len/2;$i=1;$i--) { fixDown($arr, $i, $len); } while($len1) { exch($arr[1], $arr[$len]); fixDown($arr, 1, --$len); } array_shift($arr);}$arr = array(4,6,4,9,2,3);headSort($arr);?
希望本文所述排序算法實(shí)例對大家的php程序設(shè)計(jì)有所幫助。
;
網(wǎng)站欄目:php數(shù)據(jù)結(jié)構(gòu)算法詳解 php數(shù)據(jù)結(jié)構(gòu)算法詳解
URL標(biāo)題:http://chinadenli.net/article28/hpesjp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、網(wǎng)站導(dǎo)航、網(wǎng)站設(shè)計(jì)、企業(yè)建站、網(wǎng)站制作、網(wǎng)站內(nèi)鏈
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)