📄 使用多中值排序基数实现大型树状结构.txt
字号:
end select
END
INSERT into forum (rootid,deep,ordernum,orderS……) values(@rootid,@deep+1,@ordernum,@ordernumS……)
END
END
Select @message='成功'
return
剪枝存储过程:
CREATE PROCEDURE [del] @keyid int,@message varchar(50) OUTPUT ———keyid为要删除的贴子id号,如果是新贴则为0,@message为出错信息
AS
DECLARE @rootid int,@id int,@deep int,@deept int
SELECT @rootid=0,@id=0,@deep=0,@deept=0
SELECT @id=id,@rootid=rootid,@deept=deep from forum where id=@keyid
IF (@id=0)
BEGIN
SELECT @message='该贴子不存在!"
return
END
ELSE
BEGIN
if (@rootid=0) ——要删的是根贴
delete from forum where id=@id or rootid=@id
else ——剪子枝
BEGIN
DECLARE forum_cur CURSOR
FOR
SELECT deep FROM forum WHERE rootid=@rootid and (ordernum>@ordernum or ordernum=@ordernum and ordernumS>=@ordernumS) order by ordernum,ordernumS
OPEN forum_cur
FETCH FROM forum_cur INTO @deep
DELETE FROM forum where CURRENT OF forum_cur ——删除最顶枝
WHILE @@fetch_status=0
BEGIN
FETCH FROM forum_cur INTO @deep
IF (@deep<=@tdeep) or @@fetch_status<>0 ——一旦发现深比枝顶的深相等或还要小或者游标到了尾部,则马上退出
BEGIN
select @message='成功删除子枝'
CLOSE forum_cur
DEALLOCATE forum_cur
return
END
DELETE FROM forum WHERE CURRENT OF forum_cur
END
END
CLOSE freelt_cur
DEALLOCATE forum_cur
END
END
显示(略)
过程看起来比使用单个排序基数复杂了不少,其实主要是判断何时给第二基数赋值的问题。
注意事项:基数起始值不能取类型的最大值,比如int的最大限制为2^31,则基数起始值要预留空间,否则最后的子贴是无法回复的!!(或者如果限制了ordernum的范围,虽然可以回复,但它是平行显示的)
使用了两个基数的时候,一个子贴的回复数最多了900左右(int类型,30*30),14400(使用numeric类型时——此时的精度标记得细加斟酌),理论是有限制都是不够的,但实际上并不需要这么多。
对于基数分布不均匀的问题是无法解决的,因为实际上回复客户回复哪条贴子是不可预测的。
使用2的幂作为基数,是很容易理解的——不易近起结果取近似值(除非达到了计算机的最大精度),另一个原因是计算机使用二进制进行运算,乘除2只是位移操作,速度要比其它数快得多(我是这么想的)。另一个个人的原因是因为我个算法是源于以前的思想:收敛数列与递归算法。
由于增加了算法复杂程度和冗余字段,如非必要,实非不必。
其实我是没有时间进行测试的,如果由于考虑不周或者算法错误引起无法使用,还请多多指教。
欢迎访问我的个人主页http://swuse.yeah.net
“中值排序基数法实现树状结构”的补充
--------------------------------------------------------------------------------
【廖家远】 于 2000-07-29 15:09:51 加贴在 Joy ASP ↑:
“中值排序基数法实现树状结构”的补充
由于一时疏忽,造成了此法“对于int类型的基数字段,对原始贴的回复只能有31个;numeric类型的基数字段,对原始贴的回复也不能超过120个”(实际上是对于int型字段,原始贴的回复第32个以上的树状结构显示开始紊乱,对于numeric型的基数字段,原始贴的回复从121个以上树状结构显示开始紊乱——回复并不会出问题),这是由于计算机存储精度引起的。
我们可以将加贴的存储过程修改一下(加进前面加上**号的行)以限制到了一定深度(在特定数据类型下,基数无法分辨)的时候不再以树状结构显示(而采用平显——平行显示,这样做虽然有点象折衷的做法,但在实际上由于浏览器等的限制——即使在深度100的时候能以树状结构显示,但从你的浏览器看来的树状结构的结果仍然不是清晰的——屏幕宽度不够,会折行呗)。
加贴存储过程:
CREATE PROCEDURE [add] @keyid int,@message varchar(50) OUTPUT ———keyid为回复的贴子id号,如果是新贴则为0,@message为出错信息
AS
IF (@keyid=0)
INSERT INTO forum (rootid,deep,ordernum,……) values(0,0,0,……)
ELSE
BEGIN
DECLARE @rootid int,@id int,@deep int,@begnum float,@endnum float,@ordernum float
SELECT @rootid=0,@id=0,@deep=0,@begnum=0,@endnum=0,@ordernum=0
SELECT @rootid=rootid,@id=id,@begnum=ordernum,@deep=deep from forum where id=@keyid
IF (@id=0)
BEGIN
SELECT @message='要回复的贴子已经被删除!'
return
END
ELSE
BEGIN
IF (@rootid=0) SELECT @rootid=@id ——回复的是根贴,取其id为新加贴的rootid
SELECT @endnum=ordernum where rootid=@rootid and ordernum>@begnum order by ordernum
IF (@endnum=0)
SELECT @ordernum=@begnum+65536 ——回复的是最后一贴,可以在此限制@ordernum的范围以防溢出
ELSE
** BEGIN
** IF @endnum-@begnum>1 ——精度仍能分辨。此处的1为精度标记,适合于基数字段为int,如果基数字段为numeric字段,请酌情选娶(呸呸呸,错别字来了),目的是使基数精度过小时限制深度增加,避免显示时的紊乱
** SELECT @ordernum=(@begnum+@endnum)/2,@deep=@deep+1 ——关键,取排序基数中值
** ELSE
** SELECT @ordernum=@begnum ——限制深度不能再增加,此贴与回复贴平行显示,如果存在parentid字段,则要取parentid和回复贴的parentid一样
** END
** INSERT into forum (rootid,deep,ordernum,……) values(@rootid,@deep,@ordernum,……)
END
END
Select @message='成功'
return
剪枝存储过程改为:
CREATE PROCEDURE [del] @keyid int,@message varchar(50) OUTPUT ———keyid为要删除的贴子id号,如果是新贴则为0,@message为出错信息
AS
DECLARE @rootid int,@id int,@deep int,@begnum float,@endnum float
SELECT @rootid=0,@deep=0,@begnum=0,@endnum=0,@id=0
SELECT @id=id,@begnum=ordernum,@rootid=rootid,@deep=deep from forum where id=@keyid
IF (@id=0)
BEGIN
SELECT @message='该贴子不存在!"
return
END
ELSE
BEGIN
SELECT @endnum=ordernum from forum where rootid=@rootid and deep<=@deep and ordernum>@begnum order by ordernum
IF (@endnum=0) ——要删除的是最后一个子枝或是根贴
DELETE FROM forum where ordernum>=@begnum and (rootid=@rootid or id=@rootid)
ELSE
** BEGIN
** IF @begnum=@endnum
** DELETE FROM forum where id=@id and (rootid=@rootid or id=@rootid) ——已经受精度限制的枝,只删当前贴
** ELSE
** DELETE FROM forum where ordernum>=@begnum and ordernum<@endnum and (rootid=@rootid or id=@rootid)
** END
END
虽然是限制,但此限制应该是必须的,因为实际上的回复深是不能太大的(就象我在这里灌到八九层的时候,讨饭猫就大叫“打住打住”了,呵呵)
欢迎访问我的个人主页http://swuse.yeah.net(原来bigeagle是说我这一句话“目的明显啊”)
--------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -