首页 > 其他分享 >树形

树形

时间:2024-04-05 22:33:56浏览次数:22  
标签:name route List 节点 树形 id String

package com.example.designpattern;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TreeConverter2 {
private static final String separator = ",";

/**
 * 构建树形结构
 *
 * @param nodes
 * @return
 */
public static List<TreeNode> buildTree(List<TreeNode> nodes) {
    List<TreeNode> rootNodes = nodes.stream().filter(node -> node.getRoute().split(separator).length == 1).collect(Collectors.toList());
    for (TreeNode rootNode : rootNodes) {
        addChildTreeNodes(rootNode, nodes);
    }
    return rootNodes;
}

/**
 * 添加树形节点
 *
 * @param parent
 * @param nodes
 */
private static void addChildTreeNodes(TreeNode parent, List<TreeNode> nodes) {
    String parentRoute = parent.getRoute();
    List<TreeNode> childNodes = getChildrenTreeNode(parentRoute, nodes);
    if (CollUtil.isNotEmpty(childNodes)) {
        parent.setChildren(new ArrayList<>());
    }
    for (TreeNode childNode : childNodes) {
        parent.getChildren().add(childNode);
        addChildTreeNodes(childNode, nodes);
    }
}

/**
 * 获取当前节点下的元素
 *
 * @param level
 * @param allNodeList
 * @return
 */
private static List<TreeNode> getChildrenTreeNode(String level, List<TreeNode> allNodeList) {
    String[] levelParts = level.split(separator);
    List<TreeNode> list = new ArrayList<>();
    for (TreeNode item : allNodeList) {
        String[] routeParts = item.getRoute().split(separator);
        if (routeParts.length == levelParts.length + 1 && isAllEqual(levelParts, routeParts, levelParts.length)) {
            list.add(item);
        }
    }
    return list;
}

/**
 * 判断数组前n个元素是否相等
 *
 * @param array1
 * @param array2
 * @param n
 * @return
 */
public static boolean isAllEqual(String[] array1, String[] array2, int n) {
    if (array1 == null || array2 == null || n > Math.min(array1.length, array2.length)) {
        return false;
    }
    for (int i = 0; i < n; i++) {
        if (!StrUtil.equals(array1[i], array2[i])) {
            return false;
        }
    }
    return true;
}


/**
 * 树形结构转列表
 *
 * @param rootList
 * @return
 */
public List<TreeNode> treeToGridList(List<TreeNode> rootList) {
    List<TreeNode> gridList = new ArrayList<>();
    Map<String, String> routeMap = new HashMap<>();
    for (int i = 0; i < rootList.size(); i++) {
        TreeNode rootNode = rootList.get(i);
        String currentRoute = String.valueOf(i + 1);
        generateGridList(rootNode, 1, currentRoute, routeMap, gridList);
    }
    return gridList;
}

/**
 * 生成列表
 *
 * @param node
 * @param currentLevel
 * @param currentRoute
 * @param routeMap
 * @param gridList
 */
private void generateGridList(TreeNode node, int currentLevel, String currentRoute, Map<String, String> routeMap, List<TreeNode> gridList) {
    if (ObjectUtil.isEmpty(node)) {
        return;
    }
    gridList.add(new TreeNode(node.getId(), node.getName(), currentRoute));
    if (CollUtil.isNotEmpty(node.getChildren())) {
        for (TreeNode child : node.getChildren()) {
            int nextLevel = currentLevel + 1;
            generateGridList(child, nextLevel, calculateNextRoute(nextLevel, currentRoute, routeMap), routeMap, gridList);
        }
    }
}


/**
 * 计算下一个节点路径
 *
 * @param nextLevel
 * @param currentRoute
 * @param routeMap
 * @return
 */
private String calculateNextRoute(int nextLevel, String currentRoute, Map<String, String> routeMap) {
    String[] routeParts = StrUtil.split(currentRoute, separator);
    String newRoute = ArrayUtil.join(ArrayUtil.append(routeParts, String.valueOf(nextLevel)), separator);
    while (routeMap.containsKey(newRoute)) {
        String[] finalRouteParts = routeParts;
        List<String> matchingRoutes = routeMap.entrySet().stream()
                .filter(entry -> entry.getKey().split(separator).length == finalRouteParts.length + 1
                        && isAllEqual(entry.getKey().split(separator), finalRouteParts, finalRouteParts.length))
                .map(Map.Entry::getKey)
                .sorted().collect(Collectors.toList());
        String lastRoute = matchingRoutes.get(matchingRoutes.size() - 1);
        int maxLevel = Integer.parseInt(lastRoute.split(separator)[lastRoute.split(separator).length - 1]);
        routeParts = ArrayUtil.append(routeParts, String.valueOf(maxLevel + 1));
        newRoute = ArrayUtil.join(routeParts, separator);
    }
    routeMap.put(newRoute, newRoute);
    return newRoute;
}

public static void main(String[] args) throws Exception {
    String json = IoUtil.read(new FileInputStream(new File("F:\\project\\design-pattern\\src\\main\\resources\\test2.json")), "utf-8");
    List<TreeNode> list = JSONArray.parseArray(json, TreeNode.class);
    List<TreeNode> grid = new TreeConverter2().treeToGridList(list);
    // 打印二维表
    List<TreeNode> ss = new ArrayList<>();
    for (TreeNode row : grid) {
        System.out.println(row);
        TreeNode treeNode = new TreeNode(row.getId(), row.getName(), row.getRoute());
        ss.add(treeNode);
    }
    System.out.println("-------------------");
    List<TreeNode> treeNodeList = buildTree(ss);
    System.out.println(JSONArray.toJSONString(treeNodeList));
}

}

package com.example.designpattern;

import java.io.Serializable;
import java.util.List;

public class TreeNode implements Serializable {
private String id;
private String name;
private String route;
private List children;

public TreeNode(String id, String name, String route) {
    this.id = id;
    this.name = name;
    this.route = route;
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getRoute() {
    return route;
}

public void setRoute(String route) {
    this.route = route;
}

public List<TreeNode> getChildren() {
    return children;
}

public void setChildren(List<TreeNode> children) {
    this.children = children;
}

@Override
public String toString() {
    return "TreeNode{" +
            "id='" + id + '\'' +
            ", name='" + name + '\'' +
            ", route='" + route + '\'' +
            '}';
}

}

[{
"children": [{
"children": [{
"children": [{
"children": [{
"children": [{
"id": "2-1---1",
"name": "叶子节点23111",
"route": "1,2,3,4,5,6"
}],
"id": "2-1---1",
"name": "叶子节点231111",
"route": "1,2,3,4,5"
}],
"id": "2-1--1",
"name": "叶子节点2321111",
"route": "1,2,3,4"
}],
"id": "1-1-1-1",
"name": "叶子节点221111",
"route": "1,2,3"
}, {
"id": "1-2-2",
"name": "叶子节点2222",
"route": "1,2,4"
}, {
"id": "1-3-3",
"name": "叶子节点2233",
"route": "1,2,5"
}, {
"id": "1-4-4",
"name": "叶子节点2244",
"route": "1,2,6"
}],
"id": "1-1",
"name": "叶子节点221",
"route": "1,2"
}, {
"id": "1-2",
"name": "叶子节点222",
"route": "1,3"
}, {
"id": "1-3",
"name": "叶子节点223",
"route": "1,4"
}, {
"id": "1-4",
"name": "叶子节点224",
"route": "1,5"
}],
"id": "1",
"name": "父节点22折叠",
"route": "1"
}, {
"children": [{
"id": "2-1",
"name": "叶子节点231",
"route": "2,2"
}, {
"id": "2-2",
"name": "叶子节点232",
"route": "2,3"
}, {
"id": "2-3",
"name": "叶子节点233",
"route": "2,4"
}, {
"id": "2-4",
"name": "叶子节点234",
"route": "2,5"
}],
"id": "2",
"name": "父节点23 - 折叠",
"route": "2"
}, {
"children": [{
"children": [{
"id": "2-1-3",
"name": "叶子节点2313",
"route": "3,2,3"
}, {
"id": "2-2-3",
"name": "叶子节点2323",
"route": "3,2,4"
}, {
"id": "2-3-3",
"name": "叶子节点2333",
"route": "3,2,5"
}, {
"id": "2-4-3",
"name": "叶子节点2343",
"route": "3,2,6"
}],
"id": "2-1-1",
"name": "叶子节点232",
"route": "3,2"
}],
"id": "3",
"name": "父节点24 - 折叠",
"route": "3"
}]

标签:name,route,List,节点,树形,id,String
From: https://www.cnblogs.com/youkiko/p/18116316

相关文章

  • WPF实现树形下拉列表框(TreeComboBox)
    前言树形下拉菜单是许多WPF应用程序中常见的用户界面元素,它能够以分层的方式展示数据,提供更好的用户体验。本文将深入探讨如何基于WPF创建一个可定制的树形下拉菜单控件,涵盖从原理到实际实现的关键步骤。一、需求分析    树形下拉菜单控件的核心是将ComboBox与TreeVi......
  • WPF实现树形表格控件(TreeListView)
    前言本文将探讨如何利用WPF框架实现树形表格控件,该控件不仅能够有效地展示复杂的层级数据,还能够提供丰富的个性化定制选项。我们将介绍如何使用WPF提供的控件、模板、布局、数据绑定等技术来构建这样一个树形表格。一、运行效果1.1默认样式1.2自定义样式二、代码实现......
  • 树形DP+树上路径贡献
    题目一棵树有n个节点,每个节点都同有一个符号+或者-,表示该节点是正极节点还是负极节点。如果从正极走到负极,或者从负极走到正极,都会受到1点伤害。现在需要知道走过所有路径后会受到的总伤害是多少?树上任意2点存在唯一的路径。需要计算所有任意2点的路径的伤害和。注意:从u到,和从v......
  • vue之实现单击与双击、同一标签使用click实现单双击操作、不选最后一个子元素的选择器
    MENUhtmlJavaScriptstyle解析html<template><divclass="box"><divclass="box_content"><pclass="box_p1"@click.prevent="tabSwitch({id:'keyId'})">......
  • 构建树形结构集合的方法-Java
    完整代码如下构建树形结构方法importjava.lang.reflect.Field;importjava.util.ArrayList;importjava.util.LinkedList;importjava.util.List;publicclassTableUtils<T>{/***集合构建成层级结构**ps:处于顶级的数据,上下级字段值必须为......
  • 用生动的语言讲mysql索引机制与B+树形象化理解
    索引,index,是什么呢,假如说,没有索引,比如你要点名,你就得挨个问,你是不是某某某,效率奇低,但是,当他们有了独一无二的号数或者名字,就可以免于追寻,一觅即中,这就是索引存在的意义但是,凡事有利有弊,索引增加了查询的效率,但是却降低了增删改的效率,比如说,班级加入一名新同学,你还要给他一个号数,......
  • C# 组合模式构建树形结构,实现多级指令菜单模式
    使用场景图形界面库:在图形界面开发中,UI元素(按钮、文本框等)和容器元素(面板、窗口等)可以使用组合模式来构建复杂的用户界面。这样,可以统一处理单个元素和组合元素,使得客户端代码更简洁文件系统和目录结构:文件系统是一个经典的组合模式应用场景。文件夹可以包含文件和其他文件夹,形......
  • vue2/3 - element组件库el-tree树形控件实现一键全选/一键反选取消/全部收起/全部折叠
    效果图在vue2、vue3|element饿了么组件库中,详细使用el-tree树状组件完成功能按钮组,支持全部选中节点、反选取消节点、对所有树节点进行折叠收起、是否上下级联动等等!提供详细示例代码教程,一键复制开箱即用~~示例代码请看下方代码及技术点介绍。<template><div......
  • 树形DP 01
    树形DP1、没有上司的舞会(选或不选)题目描述某大学有\(n\)个职员,编号为\(1\ldotsn\)。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数\(r_i\),但是呢,如果某个职......
  • Dev TreeList 树形结构
    一.您将treeList.OptionsView.ShowCheckBoxes设置为True,树形结构前就会出现CheckBox选择框,如果您想达到选择父节点,子节点也同时选中的效果,需将treeList.OptionsBehavior.AllowRecursiveNodeChecking设置为True。  设置完即可看到效果,如图: 二.获取选中行数据privatevo......