带有层号的先根遍历树存储基于plsql的代码实现
2017-07-13 23:19
519 查看
本文来自李明子csdn博客(http://blog.csdn.net/free1985),商业转载请联系博主获得授权,非商业转载请注明出处!
摘要:本文介绍了带有层号的先根遍历树存储基于plsql的代码实现,本文中涉及的代码编写于2014年3月。另外,本文提供了测试表创建语句以及插入节点、获取直接子节点、获取自身及子孙节点、获取根到指定节点的路径、删除节点等方法的存储过程源码与测试样例。
带有层号的先根遍历树存储结构如表1-1所示。
表1-1 带有层号的先根遍历树的存储结构
插入节点存储过程代码如下:
3.2 测试
比如,我们要创建如图3-1所示的树。
图3-1 测试用例树结构图
要创建上面的树,可以调用以下示例代码:
执行后测试代码后,表记录被更新为如表3-1所示的状态。
表3-1 插入节点后的表记录
获取直接子节点存储过程代码如下:
4.2 测试
比如我们要获取节点A的直接子节点,调用GetChildren 后,得到的游标如表4-1所示。
表4-1 获取直接子节点返回结果游标
获取当前节点及子孙节点存储过程代码如下:
5.2 测试
比如我们要获取节点A及其子孙节点,调用GetDescendants后,得到的游标如表5-1所示。
表5-1 获取当前节点及其子孙节点返回结果游标
获取根到指定节点的路径存储过程代码如下:
6.2 测试
比如我们要获取根到节点G的路径,调用GetNodePath后,得到的游标如表6-1所示。
表6-1 根到指定节点返回结果游标
删除节点的存储过程代码如下:
7.2 测试
比如,我们要删除节点C,则C的子节点E、F、G将一并删除。删除后的表记录状态如表7-1所示。
表7-1 删除节点后的表记录
摘要:本文介绍了带有层号的先根遍历树存储基于plsql的代码实现,本文中涉及的代码编写于2014年3月。另外,本文提供了测试表创建语句以及插入节点、获取直接子节点、获取自身及子孙节点、获取根到指定节点的路径、删除节点等方法的存储过程源码与测试样例。
1 存储方式介绍
带有层号的先根遍历树存储方式的主要思想是通过记录先根遍历中第一次访问节点时的次序号(以下称左值)与回溯时第二次访问的次序号(以下称右值)来维护树型结构的层次关系。由先根遍历的概念可知,子节点的左值必然大于父节点左值,而右值必然小于父节点的右值。再结合排序操作就可以很容易的在不递归的情况下对树型数据进行各种查询操作。另外,在记录左值、右值的基础上,该方式还维护了节点的层号,以降低查询直接(父)子节点的时间复杂度。带有层号的先根遍历树存储结构如表1-1所示。
表1-1 带有层号的先根遍历树的存储结构
2 建表语句
带有层号的先根遍历树在Oracle下的建表语句如下。CREATE TABLE TREE ( NODENAME NVARCHAR2(50) NOT NULL, LEVELNUM NUMBER(8) NOT NULL, LEFTVALUE NUMBER(8) NOT NULL, RIGHTVALUE NUMBER(8) NOT NULL ); COMMENT ON TABLE TREE IS '带有层号的先根遍历树' ; COMMENT ON COLUMN TREE.NODENAME IS '节点名' ; COMMENT ON COLUMN TREE.LEVELNUM IS '层号,从1开始' ; COMMENT ON COLUMN TREE.LEFTVALUE IS '先根遍历左值' ; COMMENT ON COLUMN TREE.RIGHTVALUE IS '先根遍历右值' ; ALTER TABLE TREE ADD CONSTRAINT PK_NODENAME PRIMARY KEY (NODENAME) ;
3 插入节点
3.1 实现插入节点存储过程代码如下:
procedure InsertNode --插入节点 (parentName in nvarchar2, --父节点名,插入根时为空 nodeName in nvarchar2 --节点名 ) is parentRight TREE.RIGHTVALUE%type; --父节点右值 parentLevel TREE.LEVELNUM%type; --父节点层次 begin if parentName is null then insert into TREE values (nodeName, 1, 1, 2); else --获取父节点右值 select RIGHTVALUE, LEVELNUM into parentRight, parentLevel from TREE where NODENAME = parentName; update TREE set LEFTVALUE = LEFTVALUE + 2 where LEFTVALUE > parentRight - 1; update TREE set RIGHTVALUE = RIGHTVALUE + 2 where RIGHTVALUE > parentRight - 1; insert into TREE values (nodeName, parentLevel + 1, parentRight, parentRight + 1); end if; end InsertNode;
3.2 测试
比如,我们要创建如图3-1所示的树。
图3-1 测试用例树结构图
要创建上面的树,可以调用以下示例代码:
begin -- Call the procedure tree_package.InsertNode('', 'A'); tree_package.InsertNode('A', 'B'); tree_package.InsertNode('A', 'C'); tree_package.InsertNode('A', 'D'); tree_package.InsertNode('C', 'E'); tree_package.InsertNode('C', 'F'); tree_package.InsertNode('C', 'G'); end;
执行后测试代码后,表记录被更新为如表3-1所示的状态。
表3-1 插入节点后的表记录
4 获取直接子节点
4.1 实现获取直接子节点存储过程代码如下:
procedure GetChildren --获得子节点 (parentName IN NVARCHAR2, --父节点名 children OUT RETCURSOR --子节点名 ) is parentLeft TREE.LEFTVALUE%type; --父节点左值 parentRight TREE.RIGHTVALUE%type; --父节点右值 parentLevel TREE.LEVELNUM%type; begin select LEFTVALUE, RIGHTVALUE, LEVELNUM into parentLeft, parentRight, parentLevel from TREE where NODENAME = parentName; open children for select NODENAME from TREE where LEFTVALUE between parentLeft and parentRight and LEVELNUM = parentLevel + 1 order by LEFTVALUE asc; end GetChildren;
4.2 测试
比如我们要获取节点A的直接子节点,调用GetChildren 后,得到的游标如表4-1所示。
表4-1 获取直接子节点返回结果游标
5 获取当前节点及子孙节点
5.1 实现获取当前节点及子孙节点存储过程代码如下:
procedure GetDescendants --获取子孙节点 (parentName IN NVARCHAR2, --父节点名 descendants OUT RETCURSOR --子孙节点名 )is parentLeft TREE.LEFTVALUE%type; --父节点左值 parentRight TREE.RIGHTVALUE%type; --父节点右值 begin select LEFTVALUE, RIGHTVALUE into parentLeft, parentRight from TREE where NODENAME = parentName; open descendants for select NODENAME from TREE where LEFTVALUE between parentLeft and parentRight order by LEFTVALUE asc; end GetDescendants;
5.2 测试
比如我们要获取节点A及其子孙节点,调用GetDescendants后,得到的游标如表5-1所示。
表5-1 获取当前节点及其子孙节点返回结果游标
6 获取根到指定节点的路径
6.1 实现获取根到指定节点的路径存储过程代码如下:
procedure GetNodePath --获得节点路径 (node IN NVARCHAR2, --节点名 nodePath OUT RETCURSOR --节点路径 ) is nodeLeft TREE.LEFTVALUE%type; --节点左值 nodeRight TREE.RIGHTVALUE%type; --节点右值 begin select LEFTVALUE, RIGHTVALUE into nodeLeft, nodeRight from TREE where NODENAME = node; open nodePath for select NODENAME from TREE where LEFTVALUE <= nodeLeft and RIGHTVALUE >= nodeRight order by LEFTVALUE asc; end GetNodePath;
6.2 测试
比如我们要获取根到节点G的路径,调用GetNodePath后,得到的游标如表6-1所示。
表6-1 根到指定节点返回结果游标
7 删除节点
7.1 实现删除节点的存储过程代码如下:
procedure DeleteNode --删除节点及其子节点 (node IN NVARCHAR2 --节点名 ) is nodeLeft TREE.LEFTVALUE%type; --节点左值 nodeRight TREE.RIGHTVALUE%type; --节点右值 delNodeCount NUMBER; --删除的节点数 begin select LEFTVALUE, RIGHTVALUE into nodeLeft, nodeRight from TREE where NODENAME = node; delNodeCount := (nodeRight - nodeLeft+1)/2; delete from TREE where LEFTVALUE >= nodeLeft and RIGHTVALUE <= nodeRight; update TREE set LEFTVALUE = LEFTVALUE - delNodeCount * 2 where LEFTVALUE > nodeLeft; update TREE set RIGHTVALUE = RIGHTVALUE - delNodeCount * 2 where RIGHTVALUE > nodeRight; end DeleteNode;
7.2 测试
比如,我们要删除节点C,则C的子节点E、F、G将一并删除。删除后的表记录状态如表7-1所示。
表7-1 删除节点后的表记录
相关文章推荐
- 基于邻接矩阵存储的无向网图的创建,最小生成树算法实现完整代码
- 一个简单的AJAX实现,基于C#的ASP.Net,包括服务器端的程序代码
- 一个基于TiledLayer实现的滚屏代码
- 我转载的文章《.NET中统一的存储过程调用方法 》具体实现代码
- 基于JSP实现图片的数据库存储与显示
- [原创]实现基于Memcache存储的Session类
- 基于SMO方法的支持向量机Pascal代码实现
- 基于JSP实现图片的数据库存储与显示
- [原创]实现基于文件存储的Session类
- 存储过程分页实现代码,2005 T-SQL新增功能
- 基于FLASH介质嵌入式存储方案的设计与实现
- 基于web的QQ实现代码(asp) ——在网叶(web)上实现简单QQ功能(转)
- [原创]实现基于文件存储的Session类
- 双机热备的实现模式 - 基于共享存储与纯软件方式
- 动易的SiteFactory RC 已经发布了,基于.NET 2.0实现的,代码没加密,故建群聚有兴趣的来一起学习 QQ群号:19452522
- 一个简单的AJAX实现,基于C#的ASP.Net,包括服务器端的程序代码
- 基于AVI的网络视频监控存储系统的实现方法
- 基于泛型的延时加载集合实现代码
- Java:基于Map实现的频率统计代码
- 基于.NET 2.0的GIS开源项目SharpMap分析手记(十四):ASP.NET2.0实现无刷新客户端回调的Callback机制及例子代码下载