符合lft, rgt的无限分类算法的Java生成代码

今天看了csdn中lifetragedy的一篇精华博文通向架构师的道路(第六天)之漫谈基于数据库的权限系统的设计,里面提到的菜单表的设计方式。其中使用lft,rgt两个字段的标示和预计算,从而jquery等tree控件能够从检索结果,通过一次遍历达到构建菜单目录树的效果。详情参见:http://blog.csdn.net/lifetragedy/article/details/7734864


笔者想到创建表的时候可以直接从树形结构的菜单,通过计算获得lft,rgt,level字段,并与其他所需信息一同入库,这个方式在初始建库的时候特别有用。不需要每一个菜单项都是用lifetragedy给出的四步,当然,如果后续添加一些菜单,还是使用lifetragedy的方法直接一些。


下面给出笔者的模拟代码(其中的tree使用的是lifetragedy在原文中给出的示例,这里的Tree可以是从xml文件中读取,那么这段代码的实用性就大了。):

package com.ss.util;

public class CreateMenuTable {
	private static Node tree;
	static{
		//create a menu tree
		tree = new Node("caidan");
		
		//first level
		Node baobiao = new Node("baobiao");
		Node xitong = new Node("xitongguanli");
		tree.addChild(baobiao);
		baobiao.setParent(tree);
		tree.addChild(xitong);
		xitong.setParent(tree);

		//second level
		Node nianbao = new Node("nianbao");
		Node jibao = new Node("jibao");
		Node yuebao = new Node("yuebao");
		Node zhoubao = new Node("zhoubao");
		baobiao.addChild(zhoubao);
		zhoubao.setParent(baobiao);
		baobiao.addChild(yuebao);
		yuebao.setParent(baobiao);
		baobiao.addChild(jibao);
		jibao.setParent(baobiao);
		baobiao.addChild(nianbao);
		nianbao.setParent(baobiao);
				
		Node yonghuguanli = new Node("yonghuguanli");
		Node jueseguanli = new Node("jeuseguanli");
		xitong.addChild(yonghuguanli);
		yonghuguanli.setParent(xitong);
		xitong.addChild(jueseguanli);
		jueseguanli.setParent(xitong);
	
		//third level
		Node zengjia = new Node("zengjia");
		Node shanchu = new Node("shanchu");
		yonghuguanli.addChild(zengjia);
		zengjia.setParent(yonghuguanli);
		yonghuguanli.addChild(shanchu);
		shanchu.setParent(yonghuguanli);
		
		Node zengjia1 = new Node("zengjia");
		Node shanchu1 = new Node("shanchu");
		jueseguanli.addChild(zengjia1);
		zengjia1.setParent(jueseguanli);
		jueseguanli.addChild(shanchu1);
		shanchu1.setParent(jueseguanli);
	}
	
	//use depth first traversal method to calc width of each node.
	//every node's span is 2, so set it's width = 2
	private void calculate_width(Node tree){
		//leaf node set width = 2
		if(tree.getChilds().size() == 0){
			tree.setWidth(2);
			
			return;
		}
		
		//calc each child's width
		for(Node child : tree.getChilds()){
			calculate_width(child);
		}
		
		//calc this root node's width
		for(Node child : tree.getChilds()){
			tree.setWidth(tree.getWidth() + child.getWidth());
		}
		tree.setWidth(tree.getWidth() + 2);//his own width
	}
	//calc by breadth first traversal method and use the following equals:
	//for the first child node--
	//lft = parent.lft + 1
	//rgt = lft + width -1
	//
	//for orther child node--
	//lft = rgt_before + 1
	//rgt = lft + width -1
	private void calculate_landr(Node tree){
		//for leaf node
		if(tree.getChilds().size() == 0){
			
			return;
		}
		
		//for trees has child node
		//calc first node's landr
		Node firstNode = tree.getChilds().get(0);
		firstNode.setLft(firstNode.getParent().getLft() + 1);
		firstNode.setRft(firstNode.getLft() + firstNode.getWidth() -1);
		
		printNodeInfo(firstNode);
		
		Node preNode = firstNode;
		for(int index=1, size=tree.getChilds().size(); index<size; index++){
			Node otherNode = tree.getChilds().get(index);
			otherNode.setLft(preNode.getRft() + 1);
			otherNode.setRft(otherNode.getLft() + otherNode.getWidth() -1);
			
			printNodeInfo(otherNode);
			
			preNode = otherNode;
		}
		
		//calc tree's child's child's landr
		for(Node child : tree.getChilds()){
			calculate_landr(child);
		}
	}
	private void printNodeInfo(Node node){
		StringBuilder sbuilder = new StringBuilder();
		sbuilder.append(node.getName());
		sbuilder.append(" ");
		sbuilder.append(node.getLft());
		sbuilder.append(" ");
		sbuilder.append(node.getRft());
		sbuilder.append(" ");
		sbuilder.append(node.getWidth());
		sbuilder.append(" ");
		
		System.out.println(sbuilder.toString());
	}
	public static void main(String[] arg){
		CreateMenuTable cmt = new CreateMenuTable();
		cmt.calculate_width(tree);
		tree.setLft(1);
		tree.setRft(1 + tree.getWidth() - 1);
		cmt.printNodeInfo(tree);
		cmt.calculate_landr(tree);
		
	}
}
下面给出Node类的代码:

package com.ss.util;

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

public class Node {
	private Node parent;
	private List<Node> childs = new ArrayList<Node>();
	private String name;
	private int lft;
	private int rft;
	private int depth;
	private int width;
	public int getWidth() {
		return width;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public Node(String name){
		this.name = name;
	}
	public Node getParent() {
		return parent;
	}
	public void setParent(Node parent) {
		this.parent = parent;
	}
	public String getName() {
		return name;
	}
	public void addChild(Node child){
		this.childs.add(child);
	}
	public List<Node> getChilds(){
		return this.childs;
	}
	public int getLft() {
		return lft;
	}
	public void setLft(int lft) {
		this.lft = lft;
	}
	public int getRft() {
		return rft;
	}
	public void setRft(int rft) {
		this.rft = rft;
	}
	public int getDepth() {
		return depth;
	}
	public void setDepth(int depth) {
		this.depth = depth;
	}
}

运行输出的控制台结果如下:

caidan 1 26 26 
baobiao 2 11 10 
xitongguanli 12 25 14 
zhoubao 3 4 2 
yuebao 5 6 2 
jibao 7 8 2 
nianbao 9 10 2 
yonghuguanli 13 18 6 
jeuseguanli 19 24 6 
zengjia 14 15 2 
shanchu 16 17 2 
zengjia 20 21 2 
shanchu 22 23 2 


已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:C马雯娟 返回首页