自学内容网 自学内容网

在Java中实现树结构并将其存储在MySQL数据库

在Java中实现树结构并将其存储在MySQL数据库中涉及几个步骤。

MySQL表设计

CREATE TABLE TreeNode (  
    id INT AUTO_INCREMENT PRIMARY KEY,  
    parentId INT,  
    name VARCHAR(255)
)

id 是节点的唯一标识符。
parentId 是父节点的ID,根节点的 parentId 为 NULL。
name 是节点的名称或其他属性。

树节点

@Data
public class TreeNode {  
    private int id;  
    private Integer parentId;  
    private String name;  
    private List<TreeNode> children;  
}

代码逻辑实现

递归实现
public class TreeBuilder {
 // 使用Map来存储节点,方便根据id查找
    private static Map<Integer, TreeNode> nodeMap = new HashMap<>();

    // 递归构建树的方法
    public static TreeNode buildTree(List<TreeNode> nodes, Integer rootPid) {
        // 将所有节点添加到Map中,方便后续查找
        for (TreeNode node : nodes) {
            nodeMap.put(node.getId(), node);
        }

        // 从Map中根据rootPid找到根节点,并递归构建树
        return buildTreeFromMap(rootPid);
    }

    // 递归辅助方法,从Map中构建树
    private static TreeNode buildTreeFromMap(Integer pid) {
        TreeNode currentNode = null;
        if (pid == null) {
            currentNode = nodeMap.get(pid);
        }
        // 如果pid为null,则查找父ID为null的节点作为根节点(假设只有一个根节点)
        if (currentNode == null && pid == null) {
            for (TreeNode node : nodeMap.values()) {
                if (node.getPid() == null) { // 或者使用 node.getPid() == SomeSpecialValue
                    currentNode = node;
                    break; // 找到根节点后退出循环
                }
            }
        }

        // 如果找到了当前节点(无论是根节点还是其他节点),则递归地为其添加子节点
        if (currentNode != null) {
            for (TreeNode node : nodeMap.values()) {
                if (Objects.equals(node.getPid(), currentNode.getId())) {
                    currentNode.getChildren().add(buildTreeFromMap(node.getId()));
                }
            }
        }

        return currentNode;
    }
}
非递归实现
public class TreeBuilder {
  public static TreeNode buildTree(List<TreeNode> nodes) {
        // 使用Map来存储节点,方便根据id查找
        Map<Integer, TreeNode> nodeMap = new HashMap<>();
        TreeNode root = null;

        // 第一步:将所有节点添加到Map中
        for (TreeNode node : nodes) {
            nodeMap.put(node.getId(), node);
        }

        // 第二步:构建树结构
        for (TreeNode node : nodes) {
            // 如果pid为null,说明是根节点
            if (node.getPid() == null) {
            // 对多个根结点的检查
            if (root != null) {
                    throw new IllegalArgumentException("结点列表中包含多个根结点");
                }
                root = node;
            } else {
                // 根据pid找到父节点,并将当前节点添加到父节点的children列表中
                TreeNode parentNode = nodeMap.get(node.getPid());
                if (parentNode != null) {
                    parentNode.getChildren().add(node);
                }
            }
        }

        return root;
    }
}
测试
    // 测试方法
    public static void main(String[] args) {

        List<TreeNode> nodes = new ArrayList<>();
        nodes.add(new TreeNode(1, null, "Root")); // 根节点,pid为null
        nodes.add(new TreeNode(2, 1, "Child1"));
        nodes.add(new TreeNode(3, 1, "Child2"));
        nodes.add(new TreeNode(4, 2, "Grandchild1"));
        nodes.add(new TreeNode(5, 2, "Grandchild2"));
        nodes.add(new TreeNode(6, 3, "Grandchild3"));

        // 构建树
        TreeNode tree = buildTree(nodes, null);

        // 打印树结构
        System.out.println(JSONObject.toJSONString(tree));
    }

输出结果:

{
    "children": [
        {
            "children": [
                {
                    "children": [

                    ],
                    "id": 6,
                    "name": "Grandchild3",
                    "pid": 3
                }
            ],
            "id": 3,
            "name": "Child2",
            "pid": 1
        },
        {
            "children": [
                {
                    "children": [

                    ],
                    "id": 4,
                    "name": "Grandchild1",
                    "pid": 2
                },
                {
                    "children": [

                    ],
                    "id": 5,
                    "name": "Grandchild2",
                    "pid": 2
                }
            ],
            "id": 2,
            "name": "Child1",
            "pid": 1
        }
    ],
    "id": 1,
    "name": "Root"
}

多个根节点的树生成逻辑

基本思路:

 1.创建一个HashMap来存储所有节点,以便我们可以根据ID快速查找它们。
 2.我们遍历节点列表,对于每个节点,我们检查其pid。如果pid为null,我们将该节点添加到根节点列表中。否则,我们查找其父节点,并将当前节点添加到父节点的子节点列表中。
 3.我们返回根节点列表,它可能包含多个根节点。
    public static List<TreeNode> buildTree(List<TreeNode> nodes) {
        Map<Integer, TreeNode> nodeMap = new HashMap<>();
        List<TreeNode> roots = new ArrayList<>();

        // 将所有节点放入Map中,以便快速查找
        for (TreeNode node : nodes) {
            nodeMap.put(node.getId(), node);
        }

        // 构建树结构
        for (TreeNode node : nodes) {
            if (node.getPid() == null) {
                // 如果pid为null,说明是根节点
                roots.add(node);
            } else {
                // 根据pid找到父节点,并将当前节点添加到父节点的children列表中
                TreeNode parentNode = nodeMap.get(node.getPid());
                if (parentNode != null) {
                    parentNode.getChildren().add(node);
                }
            }
        }

        return roots; // 返回根节点列表,可能包含多个根节点
    }
测试
// 测试方法
    public static void main(String[] args) {

        List<TreeNode> nodes = new ArrayList<>();

        // 创建根节点
        TreeNode root1 = new TreeNode();
        root1.setId(1);
        root1.setPid(null);
        root1.setName("Root 1");
        nodes.add(root1);

        TreeNode root2 = new TreeNode();
        root2.setId(2);
        root2.setPid(null);
        root2.setName("Root 2");
        nodes.add(root2);

        // 创建子节点
        TreeNode child1 = new TreeNode();
        child1.setId(3);
        child1.setPid(1); // child1 是 root1 的子节点
        child1.setName("Child 1 of Root 1");
        nodes.add(child1);

        TreeNode child2 = new TreeNode();
        child2.setId(4);
        child2.setPid(1); // child2 也是 root1 的子节点
        child2.setName("Child 2 of Root 1");
        nodes.add(child2);

        TreeNode child3 = new TreeNode();
        child3.setId(5);
        child3.setPid(2); // child3 是 root2 的子节点
        child3.setName("Child 1 of Root 2");
        nodes.add(child3);

        // 创建三级节点
        TreeNode grandChild1 = new TreeNode();
        grandChild1.setId(6);
        grandChild1.setPid(3); // grandChild1 是 child1 的子节点
        grandChild1.setName("Grandchild 1 of Child 1 of Root 1");
        nodes.add(grandChild1);

        TreeNode grandChild2 = new TreeNode();
        grandChild2.setId(7);
        grandChild2.setPid(4); // grandChild2 是 child2 的子节点
        grandChild2.setName("Grandchild 1 of Child 2 of Root 1");
        nodes.add(grandChild2);

        List<TreeNode> tree = buildTree(nodes);

        // 打印树结构(这里只是简单地打印每个节点的名称和它的子节点)

        printTree(tree, 0); // 0 是缩进级别
    }

    // 辅助方法,用于打印树结构
    private static void printTree(List<TreeNode> nodes, int level) {
        for (TreeNode node : nodes) {
            for (int i = 0; i < level; i++) {
                System.out.print("  "); // 缩进
            }
            System.out.println(node.getName());
            printTree(node.getChildren(), level + 1); // 递归打印子节点
        }
    }

输出结果:

[
    {
        "children": [
            {
                "children": [
                    {
                        "children": [

                        ],
                        "id": 6,
                        "name": "Grandchild 1 of Child 1 of Root 1",
                        "pid": 3
                    }
                ],
                "id": 3,
                "name": "Child 1 of Root 1",
                "pid": 1
            },
            {
                "children": [
                    {
                        "children": [

                        ],
                        "id": 7,
                        "name": "Grandchild 1 of Child 2 of Root 1",
                        "pid": 4
                    }
                ],
                "id": 4,
                "name": "Child 2 of Root 1",
                "pid": 1
            }
        ],
        "id": 1,
        "name": "Root 1"
    },
    {
        "children": [
            {
                "children": [

                ],
                "id": 5,
                "name": "Child 1 of Root 2",
                "pid": 2
            }
        ],
        "id": 2,
        "name": "Root 2"
    }
]

原文地址:https://blog.csdn.net/weixin_43833540/article/details/143475920

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!