• 非递归多层树形结构


    非递归多层树形结构

    开发过程中经常会遇到返回一些多层树形结构的需求,而且该属性结构层级不确定,没办法确定用循环次数。此时最方便的方法是使用递归来解决,简单快捷,但是该方式在层级特别深的情况就有问题,可能会导致栈溢出,所以需要使用非递归的方式。

    数据准备

    // 样例数据,为了图方便使用 guava 包的数据结构
    List<Map<String, Object>> treeData() {
          List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
          list.add(ImmutableMap.of("id", "1", "pid", "0"));
          list.add(ImmutableMap.of("id", "2", "pid", "0"));
          list.add(ImmutableMap.of("id", "3", "pid", "1"));
          list.add(ImmutableMap.of("id", "4", "pid", "1"));
          list.add(ImmutableMap.of("id", "5", "pid", "3", "tag", "A1"));
          list.add(ImmutableMap.of("id", "5", "pid", "3", "tag", "A2"));
          list.add(ImmutableMap.of("id", "6", "pid", "3", "tag", "B1"));
          list.add(ImmutableMap.of("id", "6", "pid", "3", "tag", "B2"));
          list.add(ImmutableMap.of("id", "7", "pid", "4", "tag", "C1"));
          list.add(ImmutableMap.of("id", "8", "pid", "4", "tag", "D1"));
          list.add(ImmutableMap.of("id", "8", "pid", "4", "tag", "D2"));
          list.add(ImmutableMap.of("id", "9", "pid", "2"));
          list.add(ImmutableMap.of("id", "10", "pid", "2"));
          list.add(ImmutableMap.of("id", "11", "pid", "9", "tag", "E1"));
          list.add(ImmutableMap.of("id", "11", "pid", "9", "tag", "E2"));
          list.add(ImmutableMap.of("id", "12", "pid", "9", "tag", "F1"));
          list.add(ImmutableMap.of("id", "12", "pid", "9", "tag", "F2"));
          list.add(ImmutableMap.of("id", "13", "pid", "10", "tag", "G1"));
          list.add(ImmutableMap.of("id", "14", "pid", "13", "tag", "H1"));
          // ImmutableMap是不可变的,所以需要修改为可修改的map
          list = list.stream().map( m -> {
              return new HashMap<String, Object>(m);
          }).collect(Collectors.toList());
          return list;
    }
    
    // 根据ID查询所有子节点
    List<Map<String, Object>> findData(String id) {
      return treeData().stream().collect(Collectors.groupingBy( m -> m.get("pid").toString(), Collectors.toList())).get(pid);
    }
    

    递归

    @Test
    public void testRecuruly() {
        List<Map<String, Object>> list =  recursively("0");
        System.out.println(JSON.toJSONString(list));
    }
    
    // 使用递归
    List<Map<String, Object>> recursively(String pid) {
        List<Map<String,Object>> list = findData(pid);
        if(list != null && list.size() > 0) {
            for(Map<String, Object> m : list) {
                List<Map<String,Object>> list2 = recursively(m.get("id").toString());
                m.put("children", list2);
            }
        }
        return list;
    }
    

    非递归

    递归方式逻辑上很简单,使用非递归的时候主要是参照递归的思路,递归使用jvm栈空间,我们可以创建自己的栈数据结构,在需要入栈的时候代码入栈,来达到递归的效果。java.util.Stack<E>提供了栈的实现。我们直接用就好了。

    // 使用非递归 OK 
    @Test
    public void testStack () {
        List<Map<String,Object>> list = findData("0");
        // 创建栈
        Stack<List<Map<String,Object>>> stack = new Stack<List<Map<String,Object>>>();
        stack.push(list); // 入栈
        while(!stack.isEmpty()) {
              List<Map<String,Object>> popList = stack.pop();
              for(Map<String, Object> m : popList) {
                    List<Map<String,Object>> subList = findData(m.get("id").toString());
    		if(subList != null && subList.size() > 0) {
    		    m.put("children", subList);
    		    stack.push(subList); // 入栈
    	        }
    	  }
        }
        System.out.println(JSON.toJSONString(list));
    }
    

    结果

    发现两种方式的结果一致,说明了递归的优化改造完成了。

    [
        {
            "children": [
                {
                    "children": [
                        {
                            "pid": "3",
                            "id": "5",
                            "tag": "A1"
                        },
                        {
                            "pid": "3",
                            "id": "5",
                            "tag": "A2"
                        },
                        {
                            "pid": "3",
                            "id": "6",
                            "tag": "B1"
                        },
                        {
                            "pid": "3",
                            "id": "6",
                            "tag": "B2"
                        }
                    ],
                    "pid": "1",
                    "id": "3"
                },
                {
                    "children": [
                        {
                            "pid": "4",
                            "id": "7",
                            "tag": "C1"
                        },
                        {
                            "pid": "4",
                            "id": "8",
                            "tag": "D1"
                        },
                        {
                            "pid": "4",
                            "id": "8",
                            "tag": "D2"
                        }
                    ],
                    "pid": "1",
                    "id": "4"
                }
            ],
            "pid": "0",
            "id": "1"
        },
        {
            "children": [
                {
                    "children": [
                        {
                            "pid": "9",
                            "id": "11",
                            "tag": "E1"
                        },
                        {
                            "pid": "9",
                            "id": "11",
                            "tag": "E2"
                        },
                        {
                            "pid": "9",
                            "id": "12",
                            "tag": "F1"
                        },
                        {
                            "pid": "9",
                            "id": "12",
                            "tag": "F2"
                        }
                    ],
                    "pid": "2",
                    "id": "9"
                },
                {
                    "children": [
                        {
                            "pid": "10",
                            "id": "13",
                            "tag": "G1",
                            "children": [
                                {
                                    "pid": "13",
                                    "id": "14",
                                    "tag": "H1"
                                }
                            ]
                        }
                    ],
                    "pid": "2",
                    "id": "10"
                }
            ],
            "pid": "0",
            "id": "2"
        }
    ]
    
  • 相关阅读:
    Bellman-Ford算法
    POJ 1990 MooFest
    POJ3067:Japan(树状数组求逆序对)
    树状数组求逆序对
    树状数组
    Is It A Tree?(hdu1325)
    强连通图 Tarjan算法
    UVALive
    UVALive
    Problem Statement
  • 原文地址:https://www.cnblogs.com/bartggg/p/13275250.html
Copyright © 2020-2023  润新知