JAVA算法 List实体创建多叉树,使用递归遍历 实现多级菜单管理

项目描述

最近使用SSM做后台系统,已经使用递归的形式动态获取到多级菜单,现写一个多级菜单的管理程序,用于直接遍历出所有菜单,并实现创建菜单以及对菜单的管理与删除。

具体实现效果如下

实现方案

在后台以深度先序递归的方式将数据以JSON的形式遍历出来,在菜单数据表中,主要使用了两个,一个是id,一个是pid,其他数据字段再此不描述。具体流程图

1、先创建多叉树主节点主节点的pid=null,id=0。2、通过查找下一节点节点pid=主节点id值,进行创建子节点

3、遍历使用深度优先遍历的先序搜索进行遍历输出

实现代码

多叉树的节点结构为一个实体MenuTree.class

package com.song.model;


import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.song.model.AdminMenu;

public class  MenuTree{
//AdminMenu 为菜单实体
	private AdminMenu nodeEntity;
	private MenuTree parentNode;
	private List<MenuTree> childNodes;  

	public MenuTree(AdminMenu nodeEntity) { 
		this.getParentNode();  
        initChildList();  
	}
	
	
	public MenuTree () {
		initChildList();
	}

    /* 插入一个child节点到当前节点中 */  
	public void addChildNode(MenuTree childNode){
		initChildList();
        this.childNodes.add(childNode);
    }
	
	    
	public MenuTree getParentNode() {
        return parentNode;
    }
 
    public void setParentNode(MenuTree parentNode) {
        this.parentNode = parentNode;
    }
 
    public AdminMenu getNodeEntity() {
        return nodeEntity;
    }
 
    public void setNodeEntity(AdminMenu nodeEntity) {
        this.nodeEntity = nodeEntity;
    }
 
    public List<MenuTree> getChildNodes() {
        return childNodes;
    }
 
    public void setChildNodes(List<MenuTree> childNodes) {
        this.childNodes = childNodes;
    }


}
//返回前端JSON数组
	@ResponseBody
	@RequestMapping(value="/menupower",produces = "application/json;charset=UTF-8")
	public String menupower() {
		List<AdminMenu> menuall = adminmenuservice.superapimenuall();
		List<AdminMenu> menuallapi =new ArrayList<AdminMenu>();
		//创建一个AdminMenu的对象作为多叉树的根的值
		AdminMenu root=new AdminMenu();
		root.setId(0);
		//创建跟节点
		MenuTree roottree =new MenuTree();
		roottree.setNodeEntity(root);
		//开始创建多叉树
		CreateTree(roottree,menuall);
		//遍历多叉树,roottree 为多叉树的根节点,这个函数将根节点遍历给全局变量allmenu对象数组中
		DFStraverse(roottree,menuallapi);
		if(menuallapi.size()==0) {
			return SuperCommon.SuperJson(menuallapi,"超级权限中的菜单管理出错!");
		}
		return JSON.toJSONString(menuallapi);
	}
//创建多叉树
public boolean CreateTree(MenuTree menutree,List<AdminMenu> menuall) {
		if(menutree==null)
			return false;
		//先获取同等级节点
		List<AdminMenu> rootMenu = new ArrayList<AdminMenu>();
		for (AdminMenu res : menuall) {
			if (menutree.getNodeEntity().getId().equals(res.getPid())) {// 父节点是0的,为根节点。
				rootMenu.add(res);
			}
		}
		// 根据Menu类的order排序 ,对同等级节点进行排序
		Collections.sort(rootMenu, order());
		//对rootmenu继续创建节点
		for(AdminMenu res :rootMenu) {
			System.out.println("menutree.getNodeEntity().getId()---------"+menutree.getNodeEntity().getId()+"--------res.getPid()------"+res.getPid());
			if(menutree.getNodeEntity().getId().equals(res.getPid())) {
				System.out.println(JSON.toJSONString(res));
                //使用正则表达式判断获取的id属于第几级菜单,赋予不通的cname值
                if(Pattern.matches("^[1-9]{1}00",Integer.toString(res.getId()))) {
                	res.setCname("&nbsp;"+res.getName());
                }else if(Pattern.matches("^[1-9]{2}0$",Integer.toString(res.getId()))) {
                	res.setCname("&nbsp;&nbsp;&nbsp; ├"+res.getName());
                }else {
                	res.setCname("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |└"+res.getName());
                }
				MenuTree leaf=new MenuTree();
				leaf.setNodeEntity(res);				
				menutree.addChildNode(leaf);
				CreateTree(leaf,menuall);	
			}
		}
		return true;		
	}
/* 遍历一棵树,层次遍历 */ 
	
   
    public void DFStraverse(MenuTree tree,List<AdminMenu> menuapi) {  
        if (tree.getChildNodes() == null || tree.getChildNodes().isEmpty())  
            return;
        int childNumber = tree.getChildNodes().size();  
        for (int i = 0; i < childNumber; i++) {  
        	MenuTree child = tree.getChildNodes().get(i);
        	menuapi.add(child.getNodeEntity());
        	DFStraverse(child,menuapi);  
        }  
    }    
    
    /*
	 * 排序,根据order排序
	 */
	public Comparator<AdminMenu> order() {
		Comparator<AdminMenu> comparator = new Comparator<AdminMenu>() {
			@Override
			public int compare(AdminMenu o1, AdminMenu o2) {
				if (o1.getSort() != o2.getSort()) {
					return o1.getSort() - o2.getSort();
				}
				return 0;
			}
		};
		return comparator;
	}
					

返回前端的数据格式

总结

在采用多叉树遍历所有菜单时,有点笨,使用了两天时间,到现在才明白过来具体具体算法思路,再创建多叉树的时候时由于遇到的一些问题,比如以后创建菜单时会不会发生id冲突,或者创建菜单的级别不同等问题,在创建菜单数据表时对菜单的id与pid做了以下情况,同时菜单只能建立三级,同级只能有九列。

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 我可以为你提供一个用Java语言实现的高效的多叉树的后序遍历算法的示例:public class PostOrderTraversal { public static void postOrder(TreeNode root) { // 如果根节点为空,则返回 if (root == null) { return; } // 递归遍历左子树 postOrder(root.left); // 递归遍历右子树 postOrder(root.right); // 访问根节点 System.out.print(root.data + " "); } } ### 回答2: 多叉树是一种每个节点可以有多个子节点的树结构。后序遍历是一种遍历树的方式,先遍历左子树,再遍历右子树,最后访问根节点。 在Java中,可以使用递归的方式来实现多叉树的后序遍历算法。下面是一个示例代码: ```java import java.util.ArrayList; import java.util.List; // 定义多叉树节点类 class Node { int data; List<Node> children; public Node(int data) { this.data = data; children = new ArrayList<>(); } } public class PostOrderTraversal { // 后序遍历算法 public static void postOrder(Node node) { if (node == null) { return; } // 遍历子节点 for (Node child : node.children) { postOrder(child); } // 访问根节点 System.out.print(node.data + " "); } public static void main(String[] args) { // 构造多叉树 Node root = new Node(1); Node child1 = new Node(2); Node child2 = new Node(3); Node child3 = new Node(4); Node child4 = new Node(5); root.children.add(child1); root.children.add(child2); child1.children.add(child3); child1.children.add(child4); // 后序遍历 System.out.print("后序遍历结果:"); postOrder(root); } } ``` 以上代码中,我们首先定义了一个多叉树的节点类Node,每个节点包含一个数据和一个子节点列表。然后实现了一个后序遍历的方法postOrder,采用递归的方式遍历子节点,并在最后访问根节点。在main函数中,我们构造了一个多叉树并进行后序遍历,输出结果为:4 5 2 3 1。 ### 回答3: 下面是一个用Java语言写的高效多叉树的后序遍历算法: ```java import java.util.ArrayList; import java.util.List; class TreeNode { int val; List<TreeNode> children; TreeNode(int val) { this.val = val; this.children = new ArrayList<>(); } } public class NaryTreePostorderTraversal { public List<Integer> postorderTraversal(TreeNode root) { List<Integer> result = new ArrayList<>(); if (root == null) { return result; } postorderHelper(root, result); return result; } private void postorderHelper(TreeNode node, List<Integer> result) { if (node == null) { return; } for (TreeNode child : node.children) { postorderHelper(child, result); } result.add(node.val); } public static void main(String[] args) { TreeNode root = new TreeNode(1); TreeNode child1 = new TreeNode(2); TreeNode child11 = new TreeNode(5); TreeNode child2 = new TreeNode(3); TreeNode child3 = new TreeNode(4); root.children.add(child1); root.children.add(child2); root.children.add(child3); child1.children.add(child11); NaryTreePostorderTraversal solution = new NaryTreePostorderTraversal(); List<Integer> result = solution.postorderTraversal(root); System.out.println(result); } } ``` 这个算法使用递归的方式实现多叉树的后序遍历。首先判断根节点是否为空,然后递归遍历每个子节点的子树,最后将根节点的值加入到结果列表中。通过遍历每个子节点,可以确保后序遍历的顺序是正确的。以上是一个示例程序,可以根据实际需求进行修改和调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值