基于递归算法,树形结构数据下业务场景,封装解决方法
本文源码:GitHub·点这里 || GitEE·点这里
一、递归算法
1、概念简介
递归算法的核心思想是通过将问题重复分解为同类的或其子问题的方式,从而可以使用统一的解决方式。很多编程语言支持方法或函数自我调用,简单的说,就是在函数或方法体内,自身可以再次调用自身的方法结构。
2、基础案例
这里通过递归的方式,计算阶乘、求和等相关逻辑。
public class Demo01 {public static void main(String[] args) {int result1 = factorial(5);System.out.println(result1);int result2 = sum(100) ;System.out.println(result2);}// 递归阶乘private static int factorial (int n){if(n <= 1){return n ;}else{return n*factorial(n-1);}}// 递归求和private static int sum (int f){if(f <= 1){return f ;}else{return f + sum(f-1);}}
}
3、注意事项
- 使用方法
使用递归的时候,要明确业务逻辑可以分解为重复相同的问题,且要清楚的知道递归的结束条件,不然很容易出现死循环。
- 优缺点描述
递归算法的代码比较简洁,可读性较好;但是在实际的业务处理中会出现多次的重复调用,如果处理不好,很容易出现StackOverflowError报错。
二、树状结构
1、概念描述
树形结构是一层次的嵌套结构。一个树形结构的外层和内层有相似的结构,所以这种结构多可以递归的表示。
2、图解和定义
- 根节点
树的根源,没有父节点的节点,如上图A节点。
- 兄弟节点
拥有同一父节点的子节点。如图B与C与D节点。
- 叶子节点
没有子节点的节点。如图E和F等节点。
- 分支度
指一个节点有几个子节点。 如:A为3、B为2。
- 节点深度
指从该节点到某一节点的最长路径。如图A为2、B为1。
三、应用场景
1、场景描述
基于递归算法下,处理很多树形结构的业务数据。常见的业务场景如下:
- 省市区三级联动查询 ;
- 系统模块、菜单、按钮的授权 ;
- 常见的业务数据分类:商品分类等 ;
- 常见各种行业分类细化 ;
2、特殊场景
在管理系统中,对系统模块、菜单、按钮授权操作时候可能会出现如下情况。
假如系统管理员的权限如图所示,但是给到运营人员的权限如下,需要把3号菜单和5号菜单设置为同级别,这时候基本的处理手法就是把3号菜单父级ID作为3号菜单和下属功能的权限的根节点,这里把这里当成两颗树进行分别处理,最后合并数据就好。必要时按照配上节点编码,例如NODE01,NODE0101,NODE0102等方式,这里针对这个场景描述,就是希望在处理类似业务时候,思路要开阔,不必拘泥于单个树形结构。业务很多时候都是出人意料甚至是令人生厌,不过这确实就是生活
。
3、工具类封装
这里展示一个树形结构常用的几个封装方法,例如创建树形结构,遍历,判断等。
import java.util.ArrayList;
import java.util.List;public class ThreeUtil {/*** 递归创建树形结构*/private static List<ThreeNode> getTree(List<ThreeNode> nodeList, Integer parentId) {List<ThreeNode> threeNodeList = new ArrayList<>() ;for (ThreeNode entity : nodeList) {Integer nodeId = entity.getId() ;Integer nodeParentId = entity.getParentId() ;if (parentId.intValue() == nodeParentId.intValue()) {List<ThreeNode> childList = getTree(nodeList,nodeId) ;if (childList != null && childList.size()>0){entity.setChildNode(childList);entity.setChildNodeSize(childList.size());}threeNodeList.add(entity) ;}}return threeNodeList ;}/*** 获取指定子节点*/private static List<ThreeNode> getChildTree (Integer id,List<ThreeNode> nodeList){List<ThreeNode> resultList = new ArrayList<>();for (ThreeNode entity : nodeList) {if (entity.getParentId().intValue() == id) {List<ThreeNode> childList = getChildTree(entity.getId(),nodeList) ;entity.setChildNode(childList);entity.setChildNodeSize(childList.size());resultList.add(entity) ;}}return resultList ;}/*** 遍历树形结构*/private static transient List<Integer> treeIdList = new ArrayList<>() ;private static List<Integer> getTreeInfo (List<ThreeNode> treeList){for (ThreeNode entity : treeList) {if (entity.getChildNodeSize()!=null && entity.getChildNodeSize()>0){getTreeInfo(entity.getChildNode());}treeIdList.add(entity.getId());}return treeIdList ;}/*** 判断节是否是叶子节点*/private static boolean hasChildNode (Integer id,List<ThreeNode> nodeList){for (ThreeNode entity:nodeList){if (entity.getParentId().intValue() == id){return true ;}}return false ;}public static void main(String[] args) {List<ThreeNode> threeNodeList = new ArrayList<>() ;threeNodeList.add(new ThreeNode(1,"节点A",0)) ;threeNodeList.add(new ThreeNode(2,"节点B",1)) ;threeNodeList.add(new ThreeNode(3,"节点C",1)) ;threeNodeList.add(new ThreeNode(4,"节点D",1)) ;threeNodeList.add(new ThreeNode(5,"节点E",2)) ;threeNodeList.add(new ThreeNode(6,"节点F",2)) ;// 测试1List<ThreeNode> getTree = getTree(threeNodeList,0) ;System.out.println(getTree);// 测试2// List<ThreeNode> getChildTree = getChildTree(2,threeNodeList) ;// System.out.println(getChildTree);// 测试3List<Integer> treeIdList = getTreeInfo(getTree) ;System.out.println(treeIdList);// 测试4System.out.println(hasChildNode(2,threeNodeList)) ;}
}
四、源代码地址
GitHub·地址
https://github.com/cicadasmile
GitEE·地址
https://gitee.com/cicadasmile
基于递归算法,树形结构数据下业务场景,封装解决方法相关推荐
- linux摄像头 自动对焦,基于H3在Linux下驱动OV5640摄像头的方法与流程
技术特征: 1.基于H3在Linux下驱动OV5640摄像头的方法,其特征在于,包括如下步骤: S1打开OV5640摄像头所对应的设备文件/dev/videoX: S2为OV5640摄像头驱动添加读写 ...
- centos7安装python3.7.4_基于centos7 安装python3.6.4出错的解决方法
基于centos7 安装python3.6.4出错的解决方法 错误:zipimport.ZipImportError: can't decompress data; zlib not availabl ...
- android keytool 不是内部命令或外部命令在 (win7下不能用的解决方法)
android 关于MD5指纹中 keytool在win7下不能用的解决方法 只要在cmd中执行如下命令即可:注意C:\Users\Administrator\.android\debug.keyst ...
- Quill编辑器IOS下无法获取焦点的解决方法
Quill编辑器IOS下无法获取焦点的解决方法 参考文章: (1)Quill编辑器IOS下无法获取焦点的解决方法 (2)https://www.cnblogs.com/slmk/p/8618296.h ...
- Eclipse在高分屏下图标过小的解决方法
Eclipse在高分屏下图标过小的解决方法 参考文章: (1)Eclipse在高分屏下图标过小的解决方法 (2)https://www.cnblogs.com/wenziii/p/5599310.ht ...
- Python TimedRotatingFileHandler 多进程环境下的问题和解决方法
Python TimedRotatingFileHandler 多进程环境下的问题和解决方法 原文:https://my.oschina.net/lionets/blog/796438 Python ...
- [css] 父元素下有子元素,子元素也有高度但父元素的高度为何为0呢?分析下可能出现的原因及解决方法
[css] 父元素下有子元素,子元素也有高度但父元素的高度为何为0呢?分析下可能出现的原因及解决方法 父元素塌陷父元素在文档流中高度默认是被子元素撑开的,当子元素脱离文档流以后,将无法撑起父元素的高度 ...
- IntelliJ idea 创建Web项目后web文件夹下没有WEB-INF的解决方法
IntelliJ idea 创建Web项目后web文件夹下没有WEB-INF的解决方法 参考文章: (1)IntelliJ idea 创建Web项目后web文件夹下没有WEB-INF的解决方法 (2) ...
- vue IE下验证码无法显示解决方法
vue IE下验证码无法显示解决方法 使用axios进行get请求,返回格式为文件流可以使用一下方法解决 axios({method: 'get',url: '/verifyCode/authImag ...
最新文章
- Bzoj1123 Blockade
- java axis2 jar_Java axis2.jar包详解及缺少jar包错误分析
- MM的Windows 7 登录密码忘记之后
- python从list中取出连续的数_python list 中找连续的数字(由网友处学习)
- SQL(七) - 事务、索引、视图
- ipython介绍及使用
- Atitit.软件控件and仪表盘(23)--多媒体子系统--视频输出切换控制cvbs av s-video Ypbpr pal ntsc
- Multisim 10软件介绍
- hutool中的threadutil_Hutool
- 数据库系统的三大范式以及BCNF范式详细讲解 (很详细,很详细,很详细)
- 基于python的第三方库Pyautogui实现程序自动控制鼠标与键盘
- 数据结构队列的基本操作
- Matlab 生成方波信号
- 等比求和模版,下标从1开始
- 《必然》 一书中120条书摘
- [C]C语言基本语句(5/7)→ 用scanf语句输入int, float, double, char型数据
- HBuilderX连接苹果手机iPhone预览移动端页面
- Mac 使用Charles后,退出Charles后,不能浏览网页,提示:未连接到互联网代理服务器出现问题,或者地址有误。
- 嵌入式是什么?arm是什么?
- 使用hive制作一张日历表