·建站首页 ·钻石 ·繁體
您的位置: 中国建站之家 -> 网站开发设计 -> ASP教程 -> 使用“使用中值排序基数法”实现树状结构(二)

使用“使用中值排序基数法”实现树状结构(二)

作者:未知  来源:转载  发布时间:2005-7-26 9:07:45  发布人:acx

实现原理:以一排序字段(字符型实现排序),该字段的实际长度即为回复深度(用一位字符代表一层深度时)。
所受限制:回复深度只受排序串定义长度的限制(有点象空间换深度),每贴回复数(包括根贴和子贴)为30左右(当sql
server使用Dictionary order,case-insensitive排序方式,即不区分字母大小写时),如果sql server使用Binary orders排
序方式时受限为127(255?)。
改进方法:如果觉得不够用,可以使用多位字符对应一个深度(这样计算有点麻烦),或使用几位数字代表一个深度,例如3
位数字??最多可以999个子贴,不过些时排序字段的长度应为“3*最大深度”)
优点:此法是正则的??均匀的。

有关树状结构的字段:rootid、orderstr(varchar型,按需要深度定,假如你最大要使用20层回复深度,则定为varchar
(20),余类推)

例如:(以下排序均按order by rootid+(1-sign(rootid))*lybid desc,orderstr,id desc排序)
id rootid orderstr
1 0 空串
2 1 z ??回复根贴,使用串z初始化排序字串
___________________
3 1 y ??回复1,将排在1后面的排序字符串的最后一个字符z的ascii码减1,组成新的排序串。

排序结果为:
id rootid orderstr
1 0 空串
3 1 y
2 1 z
___________________
4 1 x ??回复1贴,排序字符串求法同上

排结果为:
id rootid orderstr
1 0 空串
4 1 x
3 1 y
2 1 z
___________________
5 1 xz ??回复4贴,检查4贴是否已经有回复,现没有,初始化排序串第二个字符(在4后加上z)

排序结果为:
id rootid orderstr
1 0 空串
4 1 x
5 1 xz
3 1 y
2 1 z
___________________
6 1 xy ??回复4贴,将4贴的第一子贴的排序字串最后一个字符的ascii码减1

排序结果为:
id rootid orderstr
1 0 空串
4 1 x
6 1 xy
5 1 xz
3 1 y
2 1 z

这样,根据orderstr和len(orderstr)??深度结合就实现了树状结构。
id orderstr
1 空串
4 x
6 xy
5 xz
3 y
2 z


加贴存储过程:
if exists (select * from sysobjects where id = object_id("lybsave"))
drop proc lybsave
CREATE PROCEDURE [lybsave] @keyid int=0,@guestname varchar(20),@guestitle varchar(100),@guestcomm
text,@guestemail varchar(50)='''',@emailflag bit=0,@fromip varchar(15),@recimail varchar(50) OUTPUT
AS
DECLARE @ostr varchar(30),@rootid int,@lybid int,@ostrs varchar(30),@l tinyint,@tdt datetime,@putdate
varchar(10),@puttime varchar(5),@eflag bit
select @tdt=getdate()
select @putdate=convert(varchar(4),datepart(yy,@tdt))+''-''+left(''0''+convert(varchar(2),datepart(mm,@tdt)),2)
+''-''+left(''0''+convert(varchar(2),datepart(dd,@tdt)),2)
select @puttime=left(''0''+convert(varchar(2),datepart(hh,@tdt)),2)+'':''+left(''0''+convert(varchar(2),datepart
(mi,@tdt)),2)
select @ostr='''',@rootid=0,@lybid=0,@l=0
if (@guestemail='''') select @emailflag=0
If @keyid=0 --发新贴
goto newin
ELSE
begin
SELECT @lybid=lybid,@rootid=rootid,@ostr=orderstr,@recimail=guestemail,@eflag=emailflag from guestbook
where lybid=@keyid
IF @lybid=0 --回复贴没找到,当新贴发表
goto newin
ELSE
BEGIN
if (@eflag=0 and @guestemail<>''swuse@21cn.com abc'') select @recimail='''' --如果是版主回复且指定发邮件给提
问者,则不管发贴者是否要求回复,后面的abc相当于管理密码
if (@rootid=0) select @rootid=@lybid
select @ostrs=@ostr+''%'',@lybid=0
select top 1 @lybid=lybid,@ostrs=orderstr from guestbook where rootid=@rootid and (orderstr like
@ostrs) and lybid<>@keyid order by orderstr
if (@lybid=0) select @ostr=@ostr+char(122)
else
begin
select @l=len(@ostrs)
select @ostr=left(@ostrs,@l-1)+char(ascii(substring(@ostrs,@l,1))-1)
end
goto newin
end
end

newin:
INSERT into guestbook
(guestname,guestitle,guestcomm,putdate,puttime,guestemail,emailflag,rootid,fromip,orderstr) values
(@guestname,@guestitle,@guestcomm,@putdate,@puttime,rtrim(@guestemail),@emailflag,@rootid,@fromip,@ostr)

删贴(剪枝)存储过程:

if exists (select * from sysobjects where id = object_id("lybdel"))
drop proc lybdel
CREATE PROCEDURE [lybdel] @keyid int
AS
DECLARE @ostr varchar(30),@rootid int,@lybid int
select @ostr='',@rootid=0,@lybid=0
SELECT @ostr=orderstr,@rootid=rootid,@lybid=lybid from guestbook where lybid=@keyid
if (@lybid<>0)
BEGIN
if (@rootid=0) select @rootid=@lybid
SELECT @ostr=@ostr+''%''
DELETE FROM guestbook where orderstr like @ostr and rootid=@rootid or lybid=@rootid
END


以下是建立库结构的Sql语句(以一个简单的树状留言薄为例):

if exists(select * from sysobjects where ID = object_id("guestbook"))
drop table guestbook
go
drop table guestbook
create table guestbook(
lybid int identity(1,1),
guestname varchar(40) NOT NULL,
guestitle varchar(100) NOT NULL,
guestcomm varchar(8000),
putdate varchar(20),
puttime varchar(10),
guestemail varchar(50),
emailflag bit,
rootid int,
fromip varchar(25),
orderstr varchar(3)
)

程序名称:savelyb.asp
程序功能:保存贴子内容

<!-- #include file="lybcon.inc

[1] [2] [3] [4] [5]  下一页

将本文收藏到QQ书签与更多好友分享