最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

php實(shí)現(xiàn)無限級(jí)分類查詢(遞歸、非遞歸)

 更新時(shí)間:2016年03月10日 15:24:05   作者:跡憶  
這篇文章分為兩種情況,介紹了在遞歸和不使用遞歸的情況下PHP實(shí)現(xiàn)無限級(jí)分類,感興趣的小伙伴們可以參考一下

做PHP這么長時(shí)間,發(fā)現(xiàn)后臺(tái)管理系統(tǒng)不可少的一個(gè)應(yīng)用模塊就是對(duì)欄目的分類,一般情況下欄目都要做成是無限級(jí)的,也就是說每個(gè)欄目理論上都可以添加子欄目。在我看來這種情況處理起來整體上說也不是很復(fù)雜,唯一一個(gè)相對(duì)來說較難的點(diǎn)是無限級(jí)欄目的查詢。

下面就這種情況我來向大家做一個(gè)簡單的介紹,對(duì)于這種無限級(jí)欄目的查詢一般情況下有兩種方式,其中一種就是使用棧的機(jī)制,另一種是使用遞歸函數(shù)的方式(當(dāng)然遞歸函數(shù)實(shí)現(xiàn)機(jī)制也是借助于棧來實(shí)現(xiàn)的)。就這兩種方式下面我們分別介紹。

遞歸函數(shù)實(shí)現(xiàn)方式

上面提到,遞歸函數(shù)的也是借助于棧的機(jī)制實(shí)現(xiàn)的,但是底層對(duì)于棧的處理對(duì)于程序員來說都是透明的,程序員只需要關(guān)心應(yīng)用的實(shí)現(xiàn)邏輯。所以說使用遞歸處理上述問題理解起來比較容易,代碼也比較簡潔。

既然使用遞歸函數(shù),看名字我們就知道必須借助于自定義的函數(shù)。我先大概說一下其實(shí)現(xiàn)思路,具體細(xì)節(jié)我們反映在代碼中。

對(duì)于每一層的函數(shù)其主要做的工作就是查找父Id為當(dāng)前Id的欄目,查找到以后再次調(diào)用自身函數(shù),將查找到的欄目的id作為下一層的父id。

其流程圖如下

圖一

不知道對(duì)于上面的解釋大家能不能理解,沒關(guān)系我們下面直接看代碼

<?php
/**
 * 個(gè)人博客:跡憶博客
 * 博客地址:www.onmpw.com
 * 遞歸實(shí)現(xiàn)無限極分類
 */
$channels = array(
  array('id'=>1,'name'=>"衣服",'parId'=>0),
  array('id'=>2,'name'=>"書籍",'parId'=>0),
  array('id'=>3,'name'=>"T恤",'parId'=>1),
  array('id'=>4,'name'=>"褲子",'parId'=>1),
  array('id'=>5,'name'=>"鞋子",'parId'=>1),
  array('id'=>6,'name'=>"皮鞋",'parId'=>5),
  array('id'=>7,'name'=>"運(yùn)動(dòng)鞋",'parId'=>5),
  array('id'=>8,'name'=>"耐克",'parId'=>7),
  array('id'=>9,'name'=>"耐克",'parId'=>3),
  array('id'=>10,'name'=>"鴻星爾克",'parId'=>7),
  array('id'=>11,'name'=>"小說",'parId'=>2),
  array('id'=>12,'name'=>"科幻小說",'parId'=>11),
  array('id'=>13,'name'=>"古典名著",'parId'=>11),
  array('id'=>14,'name'=>"文學(xué)",'parId'=>2),
  array('id'=>15,'name'=>"四書五經(jīng)",'parId'=>14)
);
$html = array();
/**
 * 遞歸查找父id為$parid的結(jié)點(diǎn)
 * @param array $html  按照父-》子的結(jié)構(gòu)存放查找出來的結(jié)點(diǎn)
 * @param int $parid  指定的父id
 * @param array $channels  數(shù)據(jù)數(shù)組
 * @param int $dep  遍歷的深度,初始化為1
 */
function getChild(&$html,$parid,$channels,$dep){
  /*
   * 遍歷數(shù)據(jù),查找parId為參數(shù)$parid指定的id
   */
  for($i = 0;$i<count($channels);$i++){
    if($channels[$i]['parId'] == $parid){
      $html[] = array('id'=>$channels[$i]['id'],'name'=>$channels[$i]['name'],'dep'=>$dep);
      getChild($html,$channels[$i]['id'],$channels,$dep+1);
    }
  }
}
getChild($html,0,$channels,1);
?>

這是遞歸實(shí)現(xiàn)無限級(jí)欄目查詢的核心代碼,結(jié)合圖一對(duì)其實(shí)現(xiàn)流程應(yīng)該有一個(gè)較清晰的認(rèn)識(shí)。

非遞歸,即使用棧機(jī)制實(shí)現(xiàn)無限級(jí)欄目的查詢

在上面我們大概介紹了一下使用遞歸的方式實(shí)現(xiàn)無限級(jí)欄目的查詢,下面我們簡單介紹一下非遞歸的方式。雖說不用遞歸函數(shù)的方式,但是鑒于無限級(jí)欄目的結(jié)構(gòu)頁需要參考遞歸的實(shí)現(xiàn)機(jī)制——棧的機(jī)制,解決這一問題。

在上學(xué)的時(shí)候老師就說,其實(shí)棧的核心機(jī)制也就四個(gè)字:先進(jìn)后出。

在這對(duì)于棧的機(jī)制不多說,主要說一下如何借助棧實(shí)現(xiàn)無限級(jí)欄目查詢。

1. 首先將頂級(jí)欄目壓入棧中

2. 將棧頂元素出棧

3. 將出棧元素存入數(shù)組中,標(biāo)記其深度(其深度就是在其父欄目的深度上面加1)

4. 以出棧的元素為父欄目,查找其子欄目

5. 將查找到的子欄目入棧,重復(fù)步驟2

6. 判斷棧為空的話,流程結(jié)束;

通過對(duì)以上步驟的翻譯,可以將這些步驟翻譯成PHP代碼,其核心代碼如下

<?php
/**
 * 個(gè)人博客:跡憶博客
 * 博客地址:www.onmpw.com
*使用非遞歸,即使用棧的方式實(shí)現(xiàn)欄目的無限極分類查詢
*/
$channels = array(
  array('id'=>1,'name'=>"衣服",'parId'=>0),
  array('id'=>2,'name'=>"書籍",'parId'=>0),
  array('id'=>3,'name'=>"T恤",'parId'=>1),
  array('id'=>4,'name'=>"褲子",'parId'=>1),
  array('id'=>5,'name'=>"鞋子",'parId'=>1),
  array('id'=>6,'name'=>"皮鞋",'parId'=>5),
  array('id'=>7,'name'=>"運(yùn)動(dòng)鞋",'parId'=>5),
  array('id'=>8,'name'=>"耐克",'parId'=>7),
  array('id'=>9,'name'=>"耐克",'parId'=>3),
  array('id'=>10,'name'=>"鴻星爾克",'parId'=>7),
  array('id'=>11,'name'=>"小說",'parId'=>2),
  array('id'=>12,'name'=>"科幻小說",'parId'=>11),
  array('id'=>13,'name'=>"古典名著",'parId'=>11),
  array('id'=>14,'name'=>"文學(xué)",'parId'=>2),
  array('id'=>15,'name'=>"四書五經(jīng)",'parId'=>14)
);
$stack = array(); //定義一個(gè)空棧
$html = array();  //用來保存各個(gè)欄目之間的關(guān)系以及該欄目的深度
/*
 * 自定義入棧函數(shù)
 */
function pushStack(&$stack,$channel,$dep){
  array_push($stack, array('channel'=>$channel,'dep'=>$dep));
}
/*
 * 自定義出棧函數(shù)
 */
function popStack(&$stack){
  return array_pop($stack);
}
/*
 * 首先將頂級(jí)欄目壓入棧中
 */
foreach($channels as $key=>$val){
  if($val['parId'] == 0)
    pushStack($stack,$val,0);
}
/*
 * 將棧中的元素出棧,查找其子欄目
 */
do{
  $par = popStack($stack); //將棧頂元素出棧
  /*
   * 查找以此欄目為父級(jí)欄目的id,將這些欄目入棧
   */
  for($i=0;$i<count($channels);$i++){
    if($channels[$i]['parId'] == $par['channel']['id']){
      pushStack($stack,$channels[$i],$par['dep']+1);
    }
  }
  /*
   * 將出棧的欄目以及該欄目的深度保存到數(shù)組中
   */
  $html[] = array('id'=>$par['channel']['id'],'name'=>$par['channel']['name'],'dep'=>$par['dep']);
}while(count($stack)>0);

上面就是使用非遞歸方式實(shí)現(xiàn)的。

下載代碼:https://github.com/onmpw/phpApp

總結(jié)

上面兩種方式各有利弊,雖然實(shí)現(xiàn)形式上面不同,但是鑒于無限級(jí)欄目的結(jié)構(gòu),二者實(shí)現(xiàn)的機(jī)制都是相同的——都借助棧的方式來實(shí)現(xiàn)。在現(xiàn)實(shí)情況中,我們要根據(jù)現(xiàn)實(shí)情況的需要選擇一種方式來實(shí)現(xiàn)。

相關(guān)文章

  • PHP正則匹配操作簡單示例【preg_match_all應(yīng)用】

    PHP正則匹配操作簡單示例【preg_match_all應(yīng)用】

    這篇文章主要介紹了PHP正則匹配操作,結(jié)合簡單實(shí)例形式分析了php中preg_match_all針對(duì)HTML標(biāo)簽中P元素及img src元素內(nèi)容的獲取技巧,需要的朋友可以參考下
    2017-07-07
  • PHP函數(shù)strip_tags的一個(gè)bug淺析

    PHP函數(shù)strip_tags的一個(gè)bug淺析

    PHP 函數(shù) strip_tags 提供了從字符串中去除 HTML 和 PHP 標(biāo)記的功能,該函數(shù)嘗試返回給定的字符串 str 去除空字符、HTML 和 PHP 標(biāo)記后的結(jié)果。
    2014-05-05
  • php基于curl實(shí)現(xiàn)隨機(jī)ip地址抓取內(nèi)容的方法

    php基于curl實(shí)現(xiàn)隨機(jī)ip地址抓取內(nèi)容的方法

    這篇文章主要介紹了php基于curl實(shí)現(xiàn)隨機(jī)ip地址抓取內(nèi)容的方法,可生成隨機(jī)IP進(jìn)行訪問,涉及curl設(shè)置與使用技巧,需要的朋友可以參考下
    2016-10-10
  • PHP鉤子與簡單分發(fā)方式實(shí)例分析

    PHP鉤子與簡單分發(fā)方式實(shí)例分析

    這篇文章主要介紹了PHP鉤子與簡單分發(fā)方式,結(jié)合實(shí)例形式分析了PHP鉤子的定義與使用方法,以及多通道自由切換的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-09-09
  • PHP異步進(jìn)程助手async-helper

    PHP異步進(jìn)程助手async-helper

    這篇文章主要介紹了PHP異步進(jìn)程助手async-helper的詳細(xì)用法以及相關(guān)代碼實(shí)例,對(duì)此有需要的朋友學(xué)習(xí)下。
    2018-02-02
  • 淺談PHP中類和對(duì)象的相關(guān)函數(shù)

    淺談PHP中類和對(duì)象的相關(guān)函數(shù)

    下面小編就為大家?guī)硪黄獪\談PHP中類和對(duì)象的相關(guān)函數(shù)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • 簡單談?wù)凱HP中的include、include_once、require以及require_once語句

    簡單談?wù)凱HP中的include、include_once、require以及require_once語句

    include() 、require()語句包含并運(yùn)行指定文件。這兩結(jié)構(gòu)在包含文件上完全一樣,唯一的區(qū)別是對(duì)于錯(cuò)誤的處理。require()語句在遇到包含文件不存在,或是出錯(cuò)的時(shí)候,就停止即行,并報(bào)錯(cuò)。include()則繼續(xù)即行。
    2016-04-04
  • 分析PHP的垃圾回收機(jī)制

    分析PHP的垃圾回收機(jī)制

    垃圾回收,簡稱gc。在說這個(gè)之前先接觸一下內(nèi)存泄露,大概意思就是申請(qǐng)了一塊地兒拉了會(huì)兒屎,拉完后不收拾,那么那塊兒地就算是糟蹋了,地越用越少,最后一地全是屎。說到底一句,用了記得還。一定程度上說,垃圾回收機(jī)制就是用來擦屁股的。
    2021-06-06
  • PHP5.0~5.6 各版本兼容性cURL文件上傳功能實(shí)例分析

    PHP5.0~5.6 各版本兼容性cURL文件上傳功能實(shí)例分析

    這篇文章主要介紹了PHP5.0~5.6 各版本兼容性cURL文件上傳功能,結(jié)合實(shí)例形式分析了php各個(gè)常見版本進(jìn)行curl文件上傳操作的相關(guān)實(shí)現(xiàn)技巧與注意事項(xiàng),需要的朋友可以參考下
    2018-05-05
  • php 數(shù)組隨機(jī)取值的簡單實(shí)例

    php 數(shù)組隨機(jī)取值的簡單實(shí)例

    下面小編就為大家?guī)硪黄猵hp 數(shù)組隨機(jī)取值的簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-05-05

最新評(píng)論

靖安县| 抚顺县| 平安县| 龙里县| 盐亭县| 犍为县| 盘山县| 读书| 墨脱县| 望城县| 内乡县| 禹州市| 阜南县| 祥云县| 凉城县| 宜昌市| 宜昌市| 赤水市| 武邑县| 开鲁县| 新绛县| 东城区| 馆陶县| 吴桥县| 涟水县| 满洲里市| 石林| 桐庐县| 赣州市| 锡林郭勒盟| 南涧| 龙海市| 蛟河市| 肇庆市| 东兰县| 满城县| 遵义市| 宝应县| 肇源县| 托克逊县| 金湖县|