php实现无限级分类查询(递归、非递归)
递归函数实现方式
上面提到,递归函数的也是借助于栈的机制实现的,但是底层对于栈的处理对于程序员来说都是透明的,程序员只需要关心应用的实现逻辑。所以说使用递归处理上述问题理解起来比较容易,代码也比较简洁。
既然使用递归函数,看名字我们就知道必须借助于自定义的函数。我先大概说一下其实现思路,具体细节我们反映在代码中。
对于每一层的函数其主要做的工作就是查找父Id为当前Id的栏目,查找到以后再次调用自身函数,将查找到的栏目的id作为下一层的父id。
其流程图如下

不知道对于上面的解释大家能不能理解,没关系我们下面直接看代码
<?php
/**
* 个人博客:迹忆博客
* 博客地址:www.onmpw.com
* 递归实现无限极分类
*/
$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'=>"运动鞋",'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'=>"文学",'parId'=>2),
array('id'=>15,'name'=>"四书五经",'parId'=>14)
);
$html = array();
/**
* 递归查找父id为$parid的结点
* @param array $html 按照父-》子的结构存放查找出来的结点
* @param int $parid 指定的父id
* @param array $channels 数据数组
* @param int $dep 遍历的深度,初始化为1
*/
function getChild(&$html,$parid,$channels,$dep){
/*
* 遍历数据,查找parId为参数$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);
?>
这是递归实现无限级栏目查询的核心代码,结合图一对其实现流程应该有一个较清晰的认识。
非递归,即使用栈机制实现无限级栏目的查询
在上面我们大概介绍了一下使用递归的方式实现无限级栏目的查询,下面我们简单介绍一下非递归的方式。虽说不用递归函数的方式,但是鉴于无限级栏目的结构页需要参考递归的实现机制——栈的机制,解决这一问题。
在上学的时候老师就说,其实栈的核心机制也就四个字:先进后出。
在这对于栈的机制不多说,主要说一下如何借助栈实现无限级栏目查询。
1. 首先将顶级栏目压入栈中
2. 将栈顶元素出栈
3. 将出栈元素存入数组中,标记其深度(其深度就是在其父栏目的深度上面加1)
4. 以出栈的元素为父栏目,查找其子栏目
5. 将查找到的子栏目入栈,重复步骤2
6. 判断栈为空的话,流程结束;
通过对以上步骤的翻译,可以将这些步骤翻译成PHP代码,其核心代码如下
<?php
/**
* 个人博客:迹忆博客
* 博客地址:www.onmpw.com
*使用非递归,即使用栈的方式实现栏目的无限极分类查询
*/
$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'=>"运动鞋",'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'=>"文学",'parId'=>2),
array('id'=>15,'name'=>"四书五经",'parId'=>14)
);
$stack = array(); //定义一个空栈
$html = array(); //用来保存各个栏目之间的关系以及该栏目的深度
/*
* 自定义入栈函数
*/
function pushStack(&$stack,$channel,$dep){
array_push($stack, array('channel'=>$channel,'dep'=>$dep));
}
/*
* 自定义出栈函数
*/
function popStack(&$stack){
return array_pop($stack);
}
/*
* 首先将顶级栏目压入栈中
*/
foreach($channels as $key=>$val){
if($val['parId'] == 0)
pushStack($stack,$val,0);
}
/*
* 将栈中的元素出栈,查找其子栏目
*/
do{
$par = popStack($stack); //将栈顶元素出栈
/*
* 查找以此栏目为父级栏目的id,将这些栏目入栈
*/
for($i=0;$i<count($channels);$i++){
if($channels[$i]['parId'] == $par['channel']['id']){
pushStack($stack,$channels[$i],$par['dep']+1);
}
}
/*
* 将出栈的栏目以及该栏目的深度保存到数组中
*/
$html[] = array('id'=>$par['channel']['id'],'name'=>$par['channel']['name'],'dep'=>$par['dep']);
}while(count($stack)>0);
上面就是使用非递归方式实现的。
php实现无限级分类查询(递归、非递归)的更多相关文章
- Reverse Linked List 递归非递归实现
单链表反转--递归非递归实现 Java接口: ListNode reverseList(ListNode head) 非递归的实现 有2种,参考 头结点插入法 就地反转 递归的实现 1) Divide ...
- 【数据结构】——搜索二叉树的插入,查找和删除(递归&非递归)
一.搜索二叉树的插入,查找,删除 简单说说搜索二叉树概念: 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右 ...
- PHP无限级分类实现(递归+非递归)
<?php /** * Created by PhpStorm. * User: qishou * Date: 15-8-2 * Time: 上午12:00 */ //准备数组,代替从数据库中检 ...
- 二叉树的先序、中序以及后序遍历(递归 && 非递归)
树节点定义: class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } 递归建立二 ...
- 二叉树——遍历篇(递归/非递归,C++)
二叉树--遍历篇 二叉树很多算法题都与其遍历相关,笔者经过大量学习.思考,整理总结写下二叉树的遍历篇,涵盖递归和非递归实现. 1.二叉树数据结构及访问函数 #include <stdio.h&g ...
- 树的广度优先遍历和深度优先遍历(递归非递归、Java实现)
在编程生活中,我们总会遇见树性结构,这几天刚好需要对树形结构操作,就记录下自己的操作方式以及过程.现在假设有一颗这样树,(是不是二叉树都没关系,原理都是一样的) 1.广度优先遍历 英文缩写为BFS即B ...
- java:合并两个排序的链表(递归+非递归)
//采用不带头结点的链表 非递归实现 public static ListNode merge(ListNode list1,ListNode list2){ if(list1==null) retu ...
- 全排列问题(递归&非递归&STL函数)
问题描述: 打印输出1-9的所有全排序列,或者打印输出a-d的全排列. 思路分析: 将每个元素放到余下n-1个元素组成的队列最前方,然后对剩余元素进行全排列,依次递归下去. 比如:1 2 3 为例首先 ...
- 二叉树的递归,非递归遍历(java)
import java.util.Stack; import java.util.HashMap; public class BinTree { private char date; private ...
随机推荐
- NOIP2017逛公园(dp+最短路)
策策同学特别喜欢逛公园.公园可以看成一张N个点M条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. 策策每天都会 ...
- centos7下利用httpd2.4配置svn并使用Ldap用户认证
应用场景:Windows下有AD活动目录,类Unix系统下有Ldap,在运维开发工具平台逐步丰富的现在,统一用户管理大大便捷了管理人员. 其中不乏经典版本控制管理工具svn,与Ldap组合的用户认证方 ...
- ACM-ICPC 2017 Asia Xi'an A XOR (线性基+线段树思想)
题目链接 题意;给个数组,每次询问一个区间你可以挑任意个数的数字异或和 然后在或上k的最大值 题解:线性基不知道的先看这个,一个线性基可以log的求最大值把对应去区间的线性基求出来然后用线段树维护线性 ...
- 【洛谷P3901】数列找不同
题目大意:给定一个长度为 N 的序列,每个点被染了一个颜色.现有 M 个询问,每个询问查询区间 [l,r] 内的点是否颜色都是不同的. 题解:莫队裸题. 直接维护区间颜色数,用 cnt[] 记录下区间 ...
- bouncing-balls-evil-circle
效果如下 代码目录 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=&q ...
- http 请求头和响应头
客户端发送请求过程带着的数据: 1.请求地址 2.请求方式 3.请求头 request headers 4.请求参数 https://www.juhe.cn/ 130.... 1a2b....pei ...
- echarts柱状图鼠标移动在柱状图上显示数据给数据添加单位
解决问题: 关键代码如下: tooltip : { trigger: 'axis', formatter:function(params){ return params[0].name+"& ...
- 为什么fork()2次会避免产生僵尸进程
什么是僵尸进程:用fork()创建子进程后,子进程已终止但父进程没有对它进行善后处理,那么子进程的进程描述符就一直保存在内存中,子进程就是僵尸进程. 怎么产生僵尸进程: 1.父进程没有SIGCHLD信 ...
- (数学 尾0的个数) 51nod1003 阶乘后面0的数量
n的阶乘后面有多少个0? 6的阶乘 = 1*2*3*4*5*6 = 720,720后面有1个0. 收起 输入 一个数N(1 <= N <= 10^9) 输出 输出0的数量 输入样例 5 ...
- IIS 错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”
导致这种问题的原因是ASP.NET没有成功注册到IIS中,很有可能是先安装.Net Framework,然后安装IIS.为了避免此问题发生,要先安装IIS再安装.Net Framework. 解决方案 ...