树形结构结点编码(在mysql等关系数据库里存取树形结构)
新人,发个新帖拜拜山头。有项目实践经验的同学可能碰到过这样的问题:怎样才能高效地在mysql数据库里遍历树形结构。网络上有一些方法,但也各有优缺点。这是我实现的一套算法,看看能不能抛砖引玉,给这类问题提供一个新的思路。
主要目的是给树形结构的每个结点都赋予一个唯一的编号,并可以根据任一结点编号计算出其双亲结点,所有祖先结点,兄弟结点,孩子结点的编号。
实现原理是:
1、任何一棵树都可以用一棵唯一的二叉树来表示,如:
转换规则是:树的根结点转换成二叉树的根结点,根结点的第一个孩子结点转换成根结点的左孩子,根结点的第二个孩子转换成第一个孩子的右孩子,第三个孩子转换成第二个孩子的右孩子....依次类推。
然后对除根结点外其余结点所表示的子树也做上面的转换。
有学习过数据结构的同学可能会记得,这是孩子兄弟表示法,也就是说,在二叉树里每个结点的左孩子表示它的第一个孩子,而每个结点的右孩子表示它的右兄弟。
2、如果对一棵满二叉树的各个结点从1开始自上而下,自左而右开始编号,
那么编号为i的结点,其左孩子的编号为:2i,右孩子的编号为:2i+1,双亲结点的编号为:i/2。这个规律可以从图上看出来并用归纳法证明。
3、在二叉树上得到的结点编号,就是这棵二叉树所表示的树的各个结点的编号。如图
所不同的是,孩子结点和双亲结点的计算公式。在树结构中,一个编号为n的结点,其第i(i=1,2,3……)个孩子结点的编号为:(2^i)*n+2^(i-1)-1。
而从编号为n的结点得到其双亲结点编号的算法是,如果n是偶数,则其双亲结点编号为:n/2;否则反复进行n<-n/2 的操作,直到n为偶数为止。然后再做一次n<-n/2操作就得到双亲结点的编号。
4、由上面所说的编码方法,对一棵树从根结点开始,自上而下,自左而右进行编号的话,就可以从任一结点的编号计算出其双亲结点,所有祖先结点,兄弟结点,孩子结点的编号。
5、本文最后的附件里有2个java文件,提供了一些方法,可以根据当前结点编号计算其它结点的编号。编号是64进制数,用java语言实现。主要接口有:
(1)TreeCodeSet.root();这个方法返回树的根结点编码。
(2)TreeCodeSet.child(String code, int i);这个方法由树中某一结点的编码计算出其第i个(i=1,2,3,4,....)孩子结点的编码。
(3)TreeCodeSet.parent(String code);这个方法由树中某一结点的编码计算出其父结点的编码。
(4)TreeCodeSet.forefather(String code);这个方法由树中某一个结点的编码计算出其所有祖先结点的编码。
......
6、在给树的结点编号时,可以首先给根结点编号(调用TreeCodeSet.root()方法获取根结点编号),然后从根结点开始由上而下给每个结点的子节点编号(调用TreeCodeSet.child(String code, int i)获取各个子节点编号)。
给所有结点编号后,就可以根据编号在数据库中查找 父结点,子结点,祖先结点,兄弟结点。如果要给树插入新结点,给新结点编号方法相同。
7、这个编码表对存取在mysql数据库的树形结构应该有帮助。需要注意的是数据库里存储编码的字段,排序规则必须是大小写敏感的。
8、附件。
src.zip
(2.64 KB)
[此贴子已经被作者于2018-8-11 05:38编辑过]