使用递归方式过滤树结构

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/neweastsun/article/details/83933810

使用递归方式过滤树结构

本文介绍使用递归方法过滤树数据结构。

需求

给定叶子节点,过滤树。下面通过示例说明。

示例数据结构

         0
       / |  \
      1  2   3
    /  \ |  / \
   4   5 6  7  8

给定条件为:4 和 6,如果所有子节点都不符合条件,对应父节点也不显示。

过滤后的树为:

         0
       / | 
      1  2 
    /    | 
   4     6  

定义数据结构

定义TreeNode 类,其包括子节点集合:

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.List;

@Getter
@Setter
@Builder
@ToString
public class TreeNode {
    private String nodeName;
    private String nodeCode;

    private List<TreeNode> children;
}

实现过滤算法

在TreeNode 类中定义静态方法实现过滤算法:

    public static List<TreeNode> filterNode(TreeNode treeNode, List<String> targetNode) {

        List<TreeNode> nodes = treeNode.getChildren();
        List<TreeNode> newNodes = Lists.newArrayList();
        List<TreeNode> tagNodes = Lists.newArrayList();

        for (TreeNode node : nodes) {
            if (targetNode.contains(node.getNodeName())) {
                newNodes.add(node);
            }
            if (node.getChildren() != null && node.getChildren().size() > 0) {
                List<TreeNode> retNodes = filterNode(node, targetNode);
                if (retNodes.size() > 0) {
                    node.setChildren(retNodes);
                } else {
                    // 没有子节点情况
                    node.setChildren(null);
                    // 标记,循环结束后删除
                    tagNodes.add(node);
                }
            }
        }
        nodes.removeAll(tagNodes);
        return newNodes;
    }

循环当前节点下所有子节点,如何该子节点符合条件加入newNodes;如果该子节点还有子节点集合,则递归调用自身;所有子节点循环结束后,判断其返回的newNodes集合,如何不空,替换其子节点集合,否则,删除子节点集合,并标记当前节点。当前循环结束后,删除标记的节点,返回当前节点的子节点newNodes集合。

测试

import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class FilterTreeNode {
    private Logger logger = LoggerFactory.getLogger(FilterTreeNode.class);
    private TreeNode node0;
    private List<String> targetNode = Lists.newArrayList("B1","C1");

    @Before
    public void init(){
        node0 = TreeNode.builder().nodeCode("0").nodeName("A").build();
        TreeNode node1 = TreeNode.builder().nodeCode("1").nodeName("B").build();
        TreeNode node2 = TreeNode.builder().nodeCode("2").nodeName("C").build();
        TreeNode node3 = TreeNode.builder().nodeCode("3").nodeName("D").build();

        TreeNode node4 = TreeNode.builder().nodeCode("4").nodeName("B1").build();
        TreeNode node5 = TreeNode.builder().nodeCode("5").nodeName("B2").build();
        TreeNode node6 = TreeNode.builder().nodeCode("6").nodeName("C1").build();
        TreeNode node7 = TreeNode.builder().nodeCode("7").nodeName("D1").build();
        TreeNode node8 = TreeNode.builder().nodeCode("8").nodeName("D2").build();

        node1.setChildren(Lists.newArrayList(node4,node5));
        node2.setChildren(Lists.newArrayList(node6));
        node3.setChildren(Lists.newArrayList(node7,node8));

        node0.setChildren(Lists.newArrayList(node1,node2,node3));
    }

    @Test
    public void filterTest(){
        logger.info("before filter node0: {}",node0);
        List<TreeNode> retNodes = TreeNode.filterNode(node0, targetNode);
        if (retNodes.size() >0){
            node0.setChildren(retNodes);
        }else {
            node0 = null;
        }
        logger.info("after filter node0: {}",node0);
    }
}

首先定义测试数据结构,然后调用TreeNode.filterNode()方法,最后判断其返回值,并决定是否修改node0子节点或自身。
测试结果如下:

INFO FilterTreeNode - before filter node0: TreeNode(nodeName=A, nodeCode=0, children=[TreeNode(nodeName=B, nodeCode=1, children=[TreeNode(nodeName=B1, nodeCode=4, children=null), TreeNode(nodeName=B2, nodeCode=5, children=null)]), TreeNode(nodeName=C, nodeCode=2, children=[TreeNode(nodeName=C1, nodeCode=6, children=null)]), TreeNode(nodeName=D, nodeCode=3, children=[TreeNode(nodeName=D1, nodeCode=7, children=null), TreeNode(nodeName=D2, nodeCode=8, children=null)])])

INFO FilterTreeNode - after filter node0: TreeNode(nodeName=A, nodeCode=0, children=[TreeNode(nodeName=B, nodeCode=1, children=[TreeNode(nodeName=B1, nodeCode=4, children=null)]), TreeNode(nodeName=C, nodeCode=2, children=[TreeNode(nodeName=C1, nodeCode=6, children=null)])])

总结

本文介绍java 树形结构数据过滤,使用递归方法并通过实际示例进行说明。

猜你喜欢

转载自blog.csdn.net/neweastsun/article/details/83933810