程序开发中经常会用到树型结构,如组织机构·菜单·角色(支持继承的角色)·分目录的参数管理。
下面是我的一段经历,来单位不久我被分配到一个客服平台开发的项目中,由一位‘资深’项目经理带着做,他已经有五到六年的工作经验
了,不过在后来的工作中发现,他这六年是ctrl+c,ctrl+v过来的。
切入正题,我负责的模块中有一个是知识库的建立与应用,它的需求是这样的,要有一个目录,目录里有子目录,共要求三级目录,目录下
面对应着的是一些业务知识点供客服人员查看。
之前我没有用过树型结构,在这个程序里他们有写好的树型结构的读取工具,我看了看,大致如下做法是在后台组织一个html,然后发送到
前台再用js工具进行格式化成树的模样,具体操作是读很多次数据库数据,如果有三级就先读取一级结点,然后读取二级结点,再读取三级
结点。采用的是深度优先的做法把数据读取出来,在读取的时候组装html。
我看了以后头很大,因为我想用他们现有的模式去做,心里会很不舒服:
他们的做法有很多不足
1.在组装树型结构的时候会查询多次数据库,而且随着结点数目的增长,查询次数也随之增长很多。
2.不便于调试,有了问题很难发现。
3.不便于数据缓存。
4.增加网络流量。
5.针对一个js树型工具组装的html,如果换成其他的js工具几乎是不可能的。
6.代码没有可重用性,它把业务数据库与组装html混合在一起。
7.如果数据库数据出现循环引用,会在死循环里出不来,还有可能导致系统崩溃。
....
为了解决上述问题,我自己写了一个简单的树型结构加载工具,经历过数次的重构,在三个项目中使用。
定义一个结点类型:Node<T> 代码如下:
package com.**.power.tool.tree.node;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class Node<T> implements Serializable ,Comparable{
private static final long serialVersionUID = -8658937456797684778L;
private Node<T> parent; //父结点
private List<Node<T>> children; //子结点
private String id; //结点编号
private String text; //结点标签
private String parentId; //父结点编号
private int grade; //结点级别 根结点为0
private int subLevels; //结点下面最深有多少层
private boolean isexpand=false; //结点展开状态
public Node(){}
public Node(T t) {
this.extend=t;
}
//
private T extend; //扩展属性 用于扩展业务属性与指定的业务实体进行扩展
//....这里省去get set方法
@SuppressWarnings("unchecked")
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (super.equals(obj)) {
return true;
}
if (!(obj instanceof Node)) {
return false;
}
Node<T> target = (Node<T>) obj;
if (target.getId() == null) {
return false;
}
if (target.hashCode()==hashCode()) {
return true;
}
return false;
}
@Override
public int compareTo(Object o) {
if (o instanceof Node ) {
Node tmp=(Node) o;
Object ext=tmp.getExtend();
if (ext!=null&&this.getExtend()!=null) {
if (ext instanceof Comparable&&this.getExtend() instanceof Comparable) {
Comparable extcomp=(Comparable)this.extend;
Comparable tmpcomp=(Comparable)tmp.getExtend();
int i= tmpcomp.compareTo(extcomp);
System.out.println(i);
return i;
}
}
}
return 0;
}
}
从注释上可以看出以下几点:
1.它是一个泛型类型
2.业务无关
3.有可扩展属性
4.实现了Comparable接口,从而实现对结点进行排序
这个从接口实现上可以看出,先去查看它的扩展属性是不是实现了Comparable,如果实现了就用扩展属性进行比较,如果没有实现,就不进行比较返回0,表示相等以免对结点不必要的移动。
5.它有grade级别和subLevels下面最多有多少层,以便判断是不是对该结点进行相关操作。
这篇博客到此吧,下次再说如果组装树型结构。
谢谢大家来捧场!!
欢迎留言讨论!
分享到:
相关推荐
对树形结构的结点从1开始,自上而下,自左而右按层序编码,编码是64进制数,用java语言实现。对存取在mysql数据库的树形结构应该有帮助。 对一棵树的结点进行编码的步骤如下: 首先,对根节点编码,调用TreeCodeSet....
从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作: (1)访问结点本身(N), (2)遍历该结点的左子树(L), (3)遍历该...
无按凹入表形式打印树形结构。(1)利用树的先根遍历方法; (2)利用结点的深度控制横向位置。
从数据岛menuXML中读取数据,从树的根节点开始分析树, 利用 hasChildNodes() [方法:是否含有子节点 ] 判断当前 节点是否有子节点,如果有子节点继续向下...[对象:子节点对象集合] ,否则返回当前分析结果(树结点对象)。
二叉树是树形结构的一种重要类型。本算法是数据结构实验课上的一次实验,在熟悉二叉树结点的结构, 掌握二叉树的基本操作以及具体实现后,利用递归方法编写对二叉树这种递归数据结构进行处理的算法。
RAR里面全部是源代码,是本人在公司里面开发的一个软件软硬件管理的软件,主要用到树形结构,树形结构是从数据库里面读取出来的,对资料的修改是对二表进行操作,数据实时更新.
设计一个算法程序,使得该程序从二叉检索树中删除一个结点,并仍然保持二叉检索树的特性不变 实验要求: 创建一棵二叉检索树,然后用中序遍历查找要删除的结点的后继结点
该程序包括二叉树结构类型以及每一种操作的具体的函数定义和主函数。 1 按先序次序建立一个二叉树 2按(A:先序 B:中序 C:后序 )遍历输出二叉树的所有结点 3求二叉树中所有结点数 4求二叉树的深度
数据结构的练习题,树的练习题,求结点个数。
花生米AJAX-UI系列之:基于JQUERY的树形结构0.1版 feature: 1、可以静态载入一整棵树或子树,也可以动态AJAX载入一整棵树或子树 2、具有一般的对结点增,删,改,选中,取消选中的功能,并能让用户编写相关的触发事件...
1、 会定义顺序栈和链栈的结点类型。 2、 掌握双向栈的结构特点及其在一维数组中的实现。 3、 掌握在双向栈中进行插入和删除元素的方法。 二、 实验要求 1、 定义栈的存储结构。 2、 编写程序实现双向栈的基本操作...
带头结点 不带头结点 链表 数据结构作业 c++
0. 建立二叉树(方法0) 1. 建立二叉树(方法1) 2. 统计叶子结点个数 3. 求二叉树的树深
实现哈夫曼算法的前提是要考虑用什么样的存储结构来存储一棵哈夫曼树。在哈夫曼树中,没有度为1的结点,结点总数是n0+n2(其中n0表示二叉树中度为0的结点数,n2表示度为2的结点数),而由二叉树的性质知道n0=n2+1,...
//以头节点建立的链表。 单链表,适合初学者
数据结构之结构类型 偶然看到了专门⽤来处理关系结构的图数据库,根据其介绍了解到其原理是数据结构的图结构。⽽令⼈尴尬的是,说道图结构的特点, 算法,我竟然完全没有了⼀点印象。⼤学学习的这门课程已经还给了⽼...
给定一棵无穷的满二叉排序树,结点的编号是 1,2,3,4,…,即该二叉排序树的中序遍历序 列是从 1 开始的递增有序序列。如下图所示。 对于树中一棵根结点的编号为 X 的子树来说,沿着 X 的左孩子结点,以及左孩子...
设计程序实现二叉树结点的类型定义和对二叉树的基本操作。该程序包括二叉树结构类型以及每一种操作的具体的函数定义和主函数。 1 按先序次序建立一个二叉树 2按(A:先序 B:中序 C:后序 )遍历输出二叉树的所有结点
建立二叉树 能够求叶子结点个数 和度为2的结点个数
采用先序法建立一棵二叉树,设计输出某结点数据为x的双亲结点的数据的程序,二叉树的数据域类型为字符型, 扩展二叉树的叶子结点用‘#’表示,要求可以求一棵二叉树中多个结点的双亲。