Don't think you are, know you are

博客园 首页 新随笔 管理


树形关系的数据例如:全国性的各个部门,商品的目录等。 特点是,数据间的关系呈树形,需求阶段无法确定结点的具体数量和树的层次到底有多少。存储这类数据不仅要体现树的结构,查询效率也要考虑,另外要考虑到树今后的扩展。

结构如图1:类别1                                           
               类别1.1
               类别1.1.1
               类别1.2
               类别2
               类别2.1
               类别3
               类别3.1
               类别3.2
                     ……
         
                    全国
                        省级1
                               市级1
                               市级2
                                      县级1
                        省级2
                               市级1
                     ..............

一种方法是:纪录每个节点的父结点,数据库表如:

ID 单位 父单位ID


这样构造整棵树是没有问题了,可是这样查询的效率却不高,如果需要重构整棵树,复杂度的数量级大家可以算一下。n*n ?

所以我们加入别的记录方法,回想一下数据结构中树的储存,我们可以采用编号的方法:
编号以不同的位数为单位展现节点的层次与关系。比如根节点 000000 ,以两位为 1 层次。前2位不为0,后面4位为0的代表第一层的节点,如 01 0000, 02 0000,以此类推 010100 为 010000 的第一个子节点,010101 为010100的第一个子节点。

ID           单位                  父单位         编号
1             总类别               0                 000000
2             类别1                1                 010000
3             类别1.1              2                 010100
4             类别1.2              2                 010200
5             类别2                1                 020000
6             类别2.1              5                 020100
7             类别3                1                 030000
8             类别3.1              7                 030100
9             类别3.2              7                 030200
10           类别1.1.1            3                 010101
……
这样构造整棵树的时候 “SELECT * FROM table1 ORDER BY 编号” 树的结构出来了吧。如果要分析树的层次也不必一个一个找到根节点了,树的父结点也体现出来了。
当然父结点字段还是要保留的,这样插入,删除,或是经常有查询单位父单位的情况下,将会提高响应时间。符合“数据库设计中适当保留冗余数据的来降低程序复杂度的原则数据库设计中适当保留冗余数据的来降低程序复杂度的原则”。

这里我想多说2句,有时候保留数据的冗余是很重要的,相当于我们先把查询结果或计算结果为以后使用先保存好了,这样在使用系统时,就会节省大量时间。当然这样做唯一的缺点是浪费了硬盘空间,但是当空间不是问题,而需要重点考虑程序性能时,何去何从就显而易见了。空间换时间,还是很实用的。

言归正传,大家都知道上面的树编码,6位的话,每层次允只能许 99个节点,层次 不能大于3 层,扩充位数当然可以解决一部分问题,12位允许999个节点4层关系。且不说以后还需要扩展层次怎么办,这样对存储空间的利用率也不高。许多节点大部分位数都是0。

我的解决想法是,在增加一个“层次”字段,   值就是节点在树中的层次。编码位数不需要变,如果节点层次大于3,那么它的实际编码就是 父结点的编码+自己的编码 即可。

比如        

ID           单位                  父单位         编号             层次
10           类别1.1.1               3            010101            3
11           类别1.1.1.1           10           010000            4

比如 类别1.1.1.1 的实际编号是   父结点编号  010101+自己编号 010000=010101010000
这样只需要做一下判断就可以了,编号的位数都不用变。
关键是在需要判定节点层次的地方,我们又一次用空间换回了时间。




posted on 2006-07-01 12:08  炭炭  阅读(3094)  评论(2编辑  收藏  举报