树形结构_数据库_利用递归遍历一棵只知道父节点的树

43 篇文章 0 订阅


今天头提了一个需求,要求 求一棵只知道父节点的树下有多少叶子节点,叶子节点有可能挂在中间节点上。

(怕说的不明确:求一个部门下的所有人,部门下可能有子部门,一级部门下有人,二级部门下也可能有人。

已知条件:1.已知人所属的部门                       2.知道部门的父节点          3.部门节点的层数(无用))


我的设计思想:       希望有其他思路的同学可以踊跃发言,谢谢

1.利用广搜的思路,额外开辟一个空间记录哪些部门节点被遍历了。

2.将该节点下所有的子节点加入到额外空间中,并标识为未访问。

3.将该节点下的所有人加入到总人数中,将该节点标识为已访问。

4.直到所有节点标识显示都被访问。(所有都被访问表示树被遍历完成,因为:新加入的节点都是未访问的)


下面以SQL中的存储过程的形式 给出答案

不熟悉存储过程的同学可以参看我的存储过程讲解,传送门:http://blog.csdn.net/u010003835/article/details/50496904


[sql]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. DROP PROCEDURE IF EXISTS calShouldNum;  
  2.   
  3. -- 计算某个部门下的应到人数  
  4. CREATE PROCEDURE calShouldNum(  
  5.     IN parent_dep_id INT(40),  
  6.     INOUT should_num INT  
  7. )  
  8. BEGIN  
  9.     -- 存储过程说明:  
  10.     -- 计算某部门的应到人数,利用递归完成。  
  11.   
  12.     DECLARE total_num INT DEFAULT 0;  
  13.     DECLARE tmp_dep_id INT(40) DEFAULT 0;  
  14.     DECLARE tmp_count INT DEFAULT 0;  
  15.   
  16.     -- 临时表,相当于广搜的队列(需要多次使用)  
  17.     CREATE TABLE IF NOT EXISTS tmpCalShouldTable  
  18.     (    
  19.          department_num INT(40),  
  20.          should_mark INT DEFAULT 0  
  21.     );  
  22.   
  23.     -- 设置系统递归层数  
  24.     set max_sp_recursion_depth=254;  
  25.   
  26.     -- 计算还未被访问并递归的部门数量  
  27.     SELECT COUNT(tmpCalShouldTable.department_num) FROM tmpCalShouldTable WHERE should_mark = 0 INTO tmp_count;  
  28.     -- 若还有节点没有被访问  
  29.     WHILE tmp_count <> 0  DO  
  30.         -- 1.找到第一个没有被遍历的节点  
  31.         SELECT department_num FROM tmpCalShouldTable WHERE tmpCalShouldTable.should_mark = 0 LIMIT 1 OFFSET 0 INTO tmp_dep_id;  
  32.         -- 2.查找当前节点有多少人,并累加到应到人数中  
  33.         SELECT COUNT(u_info.user_id) FROM user_info u_info WHERE u_info.department_id = tmp_dep_id INTO total_num;  
  34.         SET should_num = total_num + should_num;  
  35.         UPDATE tmpCalShouldTable SET should_mark = 1 WHERE department_num = tmp_dep_id;  
  36.         -- 3.将当前部门下的所有子部门加到临时表中  
  37.         INSERT INTO tmpCalShouldTable(department_num)  
  38.         SELECT u_dep.department_num FROM user_department u_dep   
  39.         WHERE u_dep.parent_id = parent_dep_id;  
  40.         -- 4.查找第一个未被访问的子节点,并递归  
  41.         SELECT department_num FROM tmpCalShouldTable WHERE tmpCalShouldTable.should_mark = 0 LIMIT 1 OFFSET 0 INTO tmp_dep_id;  
  42.         CALL calShouldNum(tmp_dep_id, should_num);  
  43.         -- 计算还未被访问并递归的部门数量  
  44.         SELECT COUNT(tmpCalShouldTable.department_num) FROM tmpCalShouldTable WHERE should_mark = 0 INTO tmp_count;  
  45.     END WHILE;  
  46. END;  

/** * 根据等级查询类目 * * @param level * @return */ @Override public List queryCategoryTree(Integer level) { //查询当前级别下类目 List list = categoryDAO.list(level); //组装好的类目,返回前端 List categoryTree = new ArrayList(); //所有类目 List allDTOList = new ArrayList(); if (CollectionUtils.isEmpty(list)) { return categoryTree; } for (CategoryDO categoryDO : list) { allDTOList.add(new CategoryTreeDTO().convertDOToDTO(categoryDO)); } //当前等级类目 categoryTree = allDTOList.stream().filter(dto -> level.equals(dto.getLevel())).collect(Collectors.toList()); for (CategoryTreeDTO categoryTreeDTO : categoryTree) { //组装类目为结构 assembleTree(categoryTreeDTO, allDTOList,Constants.CATEGORY_MAX_LEVEL - level); } return categoryTree; } /** * 组装 * * @param categoryTreeDTO * @param allList * @param remainRecursionCount 剩余递归次数 * @return */ public CategoryTreeDTO assembleTree(CategoryTreeDTO categoryTreeDTO, List allList, int remainRecursionCount) { remainRecursionCount--; //最大递归次数不超过Constants.CATEGORY_MAX_LEVEL-level次,防止坏数据死循环 if(remainRecursionCount < 0){ return categoryTreeDTO; } String categoryCode = categoryTreeDTO.getCategoryCode(); Integer level = categoryTreeDTO.getLevel(); //到达最后等级返回 if (Constants.CATEGORY_MAX_LEVEL == level) { return categoryTreeDTO; } //子类目 List child = allList.stream().filter(a -> categoryCode.equals(a.getParentCode())).collect(Collectors.toList()); if (null == child) { return categoryTreeDTO; } categoryTreeDTO.setChildren(child); //组装子类目 for (CategoryTreeDTO dto : child) { assembleTree(dto, allList,remainRecursionCount); } return categoryTreeDTO; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值