【递归】java递归算法及替代方法


递归会造成压栈 栈帧变多 容易Stack Overflow,所以递归一般用于有限且数量可控范围内

个人是很讨厌递归的,一般要用到递归的实际场景,代码就是又臭又长了,但这也是最简单粗暴的算法了,所以记录个工作中遇到的递归案例,平常也需要加强练习,遇到才不会不知所措。

菜单树递归(树根往子节点递归)

需求: 取所有level小于2的节点 ( 返回结果为普通list格式)

Tree结构


    private Long id;
    private Long fid;
    private Integer level;
    private List<Tree> children;

allTreeList数据:
在这里插入图片描述

代码实现:

// SysMenuDTO 继承Tree
 List<SysMenuDTO> res= new ArrayList<>();
 res= handleChild(allTreeList, res);

handleChild 方法:

    private List<SysMenuDTO> handleChild(List<SysMenuDTO> treeList, List<SysMenuDTO> resList) {

        for (SysMenuDTO each : treeList) {
            if (each.getLevel() < 2) {
                resList.add(each);
            }
            if (null != each.getChildren()) {
                List<Tree> children = each.getChildren();
                // 转型
                List<SysMenuDTO> treeChild = new ArrayList<>();
                for (Tree child : children) {
                    treeChild.add((SysMenuDTO) child);
                }
                handleChild(treeChild, resList);
            }
        }
        return resList;
    }

为list格式的数据设置children(非递归)

需求: 数据库查出来的原始list 如果有children就设置

Tree结构同上

list数据: 可以看到此时的数据是平铺的 children为null
在这里插入图片描述
代码实现:

// allTreeList 结构同上
List<SysMenuDTO> allTreeList = Tree.assembleTree(allList);
    public static <T extends Tree> List<T> assembleTree (List<T> vos) {

        /*如果节点数为0或1,则不需要组装*/
        if ( vos == null ) {
            return vos;
        }

        List<T> retList = new ArrayList<>();
        Map<Long, T> map = new HashMap<>();

        for (T item : vos) {
            int level = getLevel(item.getCode());
            item.setLevel(level);
            map.put(item.getId(), item);
            if (item.getFid() == null || item.getFid() == 0 ) {
                retList.add(item);
                continue;
            }

            T fNode = map.get(item.getFid());
            if (null != fNode) {

                List<Tree> subs = fNode.getChildren();
                if (null == subs) {
                    subs = new ArrayList<>();
                    fNode.setChildren(subs);
                }

                subs.add(item);
            } else {
                log.error("Failed to get father node: {}", item);
            }
        }

        return retList;
    }

使用循环代替向下递归

需求:使用循环的方式 代替菜单树的递归

这个时候我们要借助第三方容器,通常使用栈或队列。

代码实现:

           // 所有菜单树
            List<SysMenuDTO> allTreeList = xxx;

            // 一二级菜单树 level从0开始
            List<SysMenuDTO> res = new ArrayList<>();

            Queue<SysMenuDTO> queue = new LinkedBlockingDeque() ;

            for (SysMenuDTO each : allTreeList) {
            	// 将每个节点放入队列中
                queue.offer(each);
            }

            while (!queue.isEmpty()) {
            	// 出队列
                SysMenuDTO each = queue.poll();
                if (Optional.ofNullable(each.getLevel()).orElse(0) < 2) {
                    res.add(each);
                }

                if (null != each.getChildren()) {
                    List<Tree> children = each.getChildren();
                     for (Tree eachElement : children) {
                     	// 子节点不为空 将子节点的每个对象入队列
                         queue.offer((SysMenuDTO) eachElement);
                     }
                }

            }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟秋与你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值