国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > PHP > 正文

php 無限分類遞歸及其排序詳細(xì)解讀

2019-11-06 07:35:32
字體:
供稿:網(wǎng)友

在各種欄目以及分類設(shè)置中,無限分類經(jīng)常會被用到,而無限分類在進(jìn)行排序的時候必然要用到遞歸,這里進(jìn)行一次詳細(xì)的分析解讀。

首先我們先了解一下遞歸函數(shù):

遞歸函數(shù)在語言學(xué)習(xí)的時候會單獨(dú)拿出來學(xué)習(xí),因?yàn)樗浅3S茫举|(zhì)上來講遞歸函數(shù)就是調(diào)用自己的函數(shù)。

舉個例子:

<?phpfunction test(){	static $a=0;	if($a<10){		$a++;		test();	}	echo $a."<br/>";}test();

test函數(shù)里面又再調(diào)用了自身,這就是俗稱的遞歸函數(shù)!遞歸函數(shù)都有條件設(shè)置,不然的會無限循環(huán)下去,這樣會導(dǎo)致程序奔潰。

所以一般來講我總結(jié)遞歸函數(shù)有兩個特點(diǎn):

一個是記錄條件值,記錄的條件值必須保證不會再下一次調(diào)用時丟失。

test函數(shù)里$a便是記錄條件值,它是依靠使用static關(guān)鍵字來保證記錄每次增加的數(shù)值不會再下一次調(diào)用test()函數(shù)而丟失,因?yàn)楹瘮?shù)中static修飾的變量僅僅在第一次初始化,并保留變量值。所以只要保證這一點(diǎn),不光static,其他的方式也可以達(dá)到目的,例如global還有&修飾符。

另一個是條件檢查。test里面對$a大小的限制就是該條件的檢查過程。

test函數(shù)中if($a<10)就是這個條件檢查的過程,它限制了test()函數(shù)對自身的調(diào)用,這樣就可以防止無限調(diào)用導(dǎo)致程序奔潰。

函數(shù)a內(nèi)部調(diào)用另外的函數(shù)b,如果b函數(shù)沒有完成,那么a函數(shù)就會一直等待下去,直到b函數(shù)完成,才會回到a函數(shù)繼續(xù)執(zhí)行。遞歸的過程中利用了這個特性,正是這個能幫助我們對無限分類進(jìn)行排序,用上面test()遞歸函數(shù)說明:

上面test()打印出來的結(jié)果是:

10,10,10,10,10,10,10,10,10,10,10

可能和很多人想的不一樣,大概有許多人會覺得不應(yīng)該是0,1,2,3,4,5,6,7,8,9,10這樣的結(jié)果嗎?

這是因?yàn)楹瘮?shù)test調(diào)用過程中,只要$a<10,就會調(diào)用自身的test(),每次調(diào)用的test()都沒有到達(dá)echo處,也就是每次調(diào)用的test函數(shù)并沒有完結(jié),直到$a遞增到了10,才第一次echo $a,這個時候$a已經(jīng)是10了,因此第一個10實(shí)際是遞歸了11次后的$a,第十一次遞歸的test由于不符合<10的條件該函數(shù)完結(jié),這個時候才開始回到遞歸第十次test函數(shù)里執(zhí)行echo,這個時候由于$a是靜態(tài)變量,值已經(jīng)是10了,因此echo出的結(jié)果是10,下面依次回到之前的test函數(shù)完成前面未完成的echo步驟,因此echo出11個10,最后一個10實(shí)際是第一次執(zhí)行test函數(shù)的echo結(jié)果。

無限分類的排序完成也是用的這個原理,遞歸排序函數(shù)不斷的通過parentid等于上一級id的子類來匹配該類別的子類別,只要找到第一個子類,就用找到的這個子類的id去找下一級的子類,直到?jīng)]有更下級的子類的時候,才返回上一級接著繼續(xù)找,找到后又開始尋找該子類下一級子類,直到?jīng)]有為止才返回,這個過程不斷循環(huán)。可能用文字不太能理解,下面的實(shí)例中我會畫出圖例,請先往后看。

我們先來看無限分類的數(shù)據(jù)er圖:

例如一個裙子的類目,它有父類別女裝,女裝又屬于衣服的類目,假定裙子的id為3,女裝為2,衣服為1,那么裙子的parentid就是直接的上級類目裙子的id,因此parentid=2,而child是裙子所在的樹形結(jié)構(gòu)上全部的祖先元素id,那么child應(yīng)該是1,2,3,因此裙子的深度deep為3,這里我假設(shè)的是用,隔開,也可以用其他的符號隔開,title不用說就是裙子。

具體我們來看這個樹形結(jié)構(gòu):

從樹形結(jié)構(gòu)分類還可以繼續(xù)延伸下去,上一級的id是下一級的parentid,就是通過id和parent這兩個列來實(shí)現(xiàn)基本的無限分類的,再進(jìn)行無限分類的遞歸排序的時候也是依靠這兩個字段的關(guān)系。

下面是一個無限分類的表結(jié)構(gòu)以及數(shù)據(jù)的例子:

為了更清楚下面畫了樹形圖:

上一代的類別的id就是自身的parentid,最高一級的parentid則為0,這點(diǎn)非常重要,是無限分類的排序的依據(jù)。

我們所要的無限分類排序效果應(yīng)該是各欄目下的子欄目都放到該欄目下方,用id進(jìn)行排序,我們要的效果就是下面這樣,為了方便查看我用了tab以及|——來間隔區(qū)分欄目之間的關(guān)系:

衣服

|——男裝

|——休閑上衣

|——短袖

|——長袖

|——休閑褲

|——女裝

|——女裝上衣

|——女裝下裝

|——牛仔褲

|——裙子

由于類別可以無限延伸下去,所以這里明顯我們需要使用遞歸函數(shù)進(jìn)行排序分類。

獲取數(shù)據(jù)所有結(jié)果,并按id排序

$MySQLi=new mysqli('localhost','root','root','test')or die("連接失敗");$mysqli->set_charset("utf8");$re=$mysqli->query("select * from col order by id asc");$result=$re->fetch_all(MYSQLI_ASSOC);

遞歸排序函數(shù)

function recursion($result,$parentid=0){	/*記錄排序后的類別數(shù)組*/	static $list=array();	foreach ($result as $k => $v){    	if($v['parentid']==$parentid){    		/*將該類別的數(shù)據(jù)放入list中*/    		$list[]=$v;    		recursion($result,$v['id']);    	}   	}   	return $list;}這個時候我們就能得到按類別排序好的數(shù)組了,但是如果要有相應(yīng)的格式,例如上面的|——,就需要對函數(shù)進(jìn)行改進(jìn)。

function recursion($result,$parentid=0,$format="|--"){	/*記錄排序后的類別數(shù)組*/	static $list=array();	foreach ($result as $k => $v){    	if($v['parentid']==$parentid){    		if($parentid!=0){    			$v['title']=$format.$v['title'];    		}    		/*將該類別的數(shù)據(jù)放入list中*/    		$list[]=$v;    		recursion($result,$v['id'],"  ".$format);    	}   	}   	return $list;}$list=recursion($result,0,'|--');這樣排序的結(jié)果如下:

整個遞歸函數(shù)的執(zhí)行情況大概是什么樣的,我們接上面說過的要畫的實(shí)例圖,看圖后就很清楚這個原理了,這個圖只畫了部分,不過足夠理解這個過程了:


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 凤阳县| 蓝田县| 九寨沟县| 济源市| 张家川| 弥渡县| 开化县| 常宁市| 利津县| 咸阳市| 临汾市| 华安县| 邹城市| 柘荣县| 前郭尔| 蒙城县| 定西市| 佛山市| 交城县| 名山县| 洪泽县| 汨罗市| 米林县| 博客| 河北区| 封丘县| 中山市| 嘉黎县| 新津县| 九龙坡区| 疏附县| 米泉市| 万山特区| 屯门区| 射阳县| 谷城县| 阿合奇县| 万安县| 尚志市| 长寿区| 象州县|