人人做人人澡人人爽欧美,国产主播一区二区,久久久精品五月天,羞羞视频在线观看免费

當(dāng)前位置:蘿卜系統(tǒng)下載站 > 技術(shù)開(kāi)發(fā)教程 > 詳細(xì)頁(yè)面

運(yùn)用多中值排序基數(shù)完成大型樹(shù)狀結(jié)構(gòu)

運(yùn)用多中值排序基數(shù)完成大型樹(shù)狀結(jié)構(gòu)

更新時(shí)間:2019-11-11 文章作者:未知 信息來(lái)源:網(wǎng)絡(luò) 閱讀次數(shù):

使用多中值排序基數(shù)實(shí)現(xiàn)大型樹(shù)狀結(jié)構(gòu)

在“中值排序基數(shù)法實(shí)現(xiàn)樹(shù)狀結(jié)構(gòu)”中,為了解決回復(fù)限制的問(wèn)題,我們可以增加第二(三、四……)基數(shù)字段。
其實(shí)在一般的BBS中,使用一個(gè)基數(shù)已經(jīng)足夠,因?yàn)橐粋(gè)貼子的回復(fù)太多或深度太大的時(shí)候,無(wú)論你的樹(shù)狀結(jié)構(gòu)做得多好,由于屏幕的限制(顯示折行),顯示總會(huì)亂,因此不如象在《補(bǔ)充》一文中,達(dá)到一定深度或個(gè)數(shù)時(shí),后面的貼子采用平行顯示的方法,不過(guò)那部分已經(jīng)不再是樹(shù)狀結(jié)構(gòu)了。
原理:在貼子顯示的order by子句中,如果排序基數(shù)相同,則根據(jù)第二基數(shù)排序,從而避免樹(shù)狀結(jié)構(gòu)限制。

一、在BBS的內(nèi)容表中再增加一個(gè)第二基數(shù)字段ordernumS,同第一基數(shù)一樣,可為int或numeric,看需要定。

這樣在表中增加了四個(gè)冗余字段,rootid——用于記錄根id,deep——用于記錄回復(fù)的深度(為0時(shí)表示根貼),ordernum——第一排序基數(shù),ordernumS——第二排序基數(shù)

表forum與(只列與樹(shù)狀結(jié)構(gòu)有關(guān)的字段):
id rootid deepordernumordernumS
其中id、rootid、deep均為int型(deep可為tinyint型),ordernum為int或float型,ordernumS(默認(rèn)值為0)同ordernum。

例:(在此為了簡(jiǎn)單,使用一個(gè)小的起始排序基數(shù),且為int型,以清楚觀察什么時(shí)候第二排序基數(shù)起作用)。
(下面所說(shuō)的排序均指按ordernum從小到大,ordernumS從小到大排序,即order by ordernum,ordernumS)
(下面所說(shuō)的精度為后貼與前貼的ordernum的差,精度標(biāo)記指的是這個(gè)差大于某個(gè)值這個(gè)條件,比如(后貼的ordernum-前貼的ordernum)>1)

id rootiddeepordernumordernumS
10000
21180
_____________________________________
31140回復(fù)第1貼,第一基數(shù)取1、2貼的第一基數(shù)中值即(0+8)/2=4

排序后結(jié)果為:
id rootiddeepordernumordernumS
10000
31140
21180
_____________________________________
41260回復(fù)第3貼,第一基數(shù)取3、2的第一基數(shù)中值即(4+8)/2

排序后結(jié)果為:
id rootiddeepordernumordernumS
10000
31140
41260
21180
_____________________________________
51370回復(fù)第4貼,第一基數(shù)取4、2的第一基數(shù)中值即(6+8)/2

排序后的結(jié)果為:
id rootiddeepordernumordernumS
10000
31140
41260
51370
21180
_____________________________________
61368 回復(fù)第4貼,第一基數(shù)取4、5的第一基數(shù)中值即(6+7)/2,因是int型,被截成了6
此時(shí)精度標(biāo)記(暫設(shè)為1)已經(jīng)不滿足(即5的第一基數(shù)與4的第一基數(shù)差不大于1,為1),此時(shí)在父貼的第二基數(shù)加上一起始值作為新貼的第二基數(shù)
排序后的結(jié)果為:
id rootiddeepordernumordernumS
10000
31140
41260
61368
51370
21180
_____________________________________
71364 回復(fù)第4貼,第一基數(shù)取4、6的第一基數(shù)中值即(6+6)/2=6
此時(shí)精度標(biāo)記(暫設(shè)為1)已經(jīng)不滿足(即4的第一基數(shù)與6的第一基數(shù)差不大于1,為0),此時(shí)第二基數(shù)取6、4的第二基數(shù)中值(0+8)/2=4


排序后的結(jié)果為:
id rootiddeepordernumordernumS
10000
31140
41260
71364
61368
51370
21180

這樣排序基數(shù)ordernum、ordernumS與回復(fù)深度deep一起就實(shí)現(xiàn)了如下的樹(shù)狀結(jié)構(gòu):
id
1
3
 4
 7
 6
 5
2

在這可以看到,第一基數(shù)ordernum與第二基數(shù)ordernumS以及深度deep實(shí)現(xiàn)了樹(shù)狀結(jié)構(gòu)!


二、插入的實(shí)現(xiàn)(如何確定排序基數(shù),下面所指貼子均為同一根下的子貼)
(一)根第一基數(shù)ordernum定為0
(二)所有貼子第二基數(shù)默認(rèn)為0
(三)第一條回復(fù)貼子基數(shù)定為2的整數(shù)次冪(如65536=2^16,可取更大的數(shù))
(四)回復(fù)樹(shù)中最后一條貼子時(shí),基數(shù)取最后一貼的基數(shù)ordernum再加上2的整數(shù)次冪(同上)
(五)當(dāng)?shù)谝换鶖?shù)差大于精度標(biāo)記時(shí),第一基數(shù)取中值,忽略第二基數(shù)(為0)
(五)當(dāng)?shù)谝换鶖?shù)差等于精度標(biāo)記時(shí),第一基數(shù)取回復(fù)貼的第一基數(shù),第二基數(shù)取回復(fù)貼的第二基數(shù)加上基數(shù)起始值
(六)當(dāng)?shù)谝换鶖?shù)差小于精度標(biāo)記時(shí),第一基數(shù)取回復(fù)貼的第一基數(shù),第二基數(shù)取前后貼的第二基數(shù)中值

如果要使用parentid字段,則更新相關(guān)的parentid,這里不再討論。

三、刪除的實(shí)現(xiàn)

刪除貼子(剪枝)時(shí),當(dāng):
(一)要?jiǎng)h除的是根貼時(shí),將整個(gè)樹(shù)刪除即可
(二)要?jiǎng)h除的是子枝時(shí),只需按ordernum和ordernumS排序,找出從指定要?jiǎng)h除的貼子開(kāi)始的所有貼子(使用條件rootid=@rootid and (ordernum>@ordernum or ordernum=@ordernum and ordernumS>=@ordernumS)),從上到下逐個(gè)判斷深度是不是增加,如果增加則予以刪除。一旦發(fā)現(xiàn)深度等于或小于要?jiǎng)h貼子(枝頂)的深度,則馬上退出刪除。
如上例子中,要?jiǎng)h除4貼一個(gè)分枝,只需找出4后面的所有貼子,然后逐個(gè)往下判斷,如果深度大小4貼的深度則刪除,而一旦遇到深度等于或者小于4貼深度,則馬上退出刪除。結(jié)果是4、7、6、5滿足條件,這就是我們要?jiǎng)h除的子枝。
如果要增加parentid字段,則需判斷共刪除了多少個(gè)貼子,以例更新有關(guān)的parentid字段。
為了方便和提高速,使用操作API光標(biāo)的存儲(chǔ)過(guò)程來(lái)進(jìn)行。

四、顯示的實(shí)現(xiàn)
只需執(zhí)行select * from forum order by rootid+id-sign(rootid)*id desc,ordernum,ordernumS,然后結(jié)合deep就可實(shí)現(xiàn)樹(shù)狀的顯示。


五、具體實(shí)現(xiàn)方法(以存儲(chǔ)過(guò)程為例)

加貼存儲(chǔ)過(guò)程:(ordernum和ordernumS使用int型,設(shè)精度標(biāo)記為1)

CREATE PROCEDURE [add] @keyid int,@message varchar(50) OUTPUT———keyid為回復(fù)的貼子id號(hào),如果是新貼則為0,@message為出錯(cuò)信息
AS
IF (@keyid=0)
INSERT INTO forum (rootid,deep,ordernum,ordernumS……) values(0,0,0,0……)
ELSE
BEGIN
 DECLARE @rootid int,@id int,@deep int,@begnum int,@endnum intt,@begS int,endS int,@ordernum int,@ordernumS int
 SELECT @rootid=0,@id=0,@deep=0,@begnum=0,@endnum=0,@ordernum=0,@ordernumS=0,@begS=0,@endS=0
 SELECT @rootid=rootid,@id=id,@begnum=ordernum,@begs=begs,@deep=deep from forum where id=@keyid
 IF (@id=0)
 BEGIN
SELECT @message='要回復(fù)的貼子已經(jīng)被刪除!'
return
 END
 ELSE
 BEGIN
IF (@rootid=0) SELECT @rootid=@id——回復(fù)的是根貼,取其id為新加貼的rootid
#1SELECT top 1 @endnum=ordernum,@endS=ordernumS where rootid=@rootid and id<>@id by ordernum,ordernumS ——取回復(fù)貼子后面的那條貼出來(lái)
if @endnum-@begnum>1
SELECT @ordernum=(@begnum+@endnum)/2,@ordernumS=0——精度大小精度標(biāo)記(在取為1),忽略第二基數(shù)(定為0)
else
BEGIN
select case @endnum-begnum
case 1
select @ordernum=@begnum,@ordernumS=@begS+65536 ——在父貼的第二基數(shù)基礎(chǔ)上加一起始值作為新貼第二基數(shù),實(shí)際應(yīng)用中可在此限制范圍以防溢出
case 0
select @ordernum=@begnum,@ordernumS=(@begS+endS)/2——取第二基數(shù)中值作為新貼第二基數(shù)
case else ——小于0(即@begnum=0),表示#1句中沒(méi)有找到后面一條貼子,即要回復(fù)的是樹(shù)中的最后一條貼子
SELECT @ordernum=@begnum+65536,@ordernumS=0 ——實(shí)際應(yīng)用中可限制@ordernum的范圍,以免溢出
end select
END
INSERT into forum (rootid,deep,ordernum,orderS……) values(@rootid,@deep+1,@ordernum,@ordernumS……)
 END
END
Select @message='成功'
return



剪枝存儲(chǔ)過(guò)程:
CREATE PROCEDURE [del] @keyid int,@message varchar(50) OUTPUT———keyid為要?jiǎng)h除的貼子id號(hào),如果是新貼則為0,@message為出錯(cuò)信息
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) ——要?jiǎng)h的是根貼
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——?jiǎng)h除最頂枝
WHILE @@fetch_status=0
BEGIN
FETCH FROM forum_cur INTO @deep
IF (@deep<=@tdeep) or @@fetch_status<>0——一旦發(fā)現(xiàn)深比枝頂?shù)纳钕嗟然蜻要小或者游標(biāo)到了尾部,則馬上退出
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

顯示(略)


過(guò)程看起來(lái)比使用單個(gè)排序基數(shù)復(fù)雜了不少,其實(shí)主要是判斷何時(shí)給第二基數(shù)賦值的問(wèn)題。
注意事項(xiàng):基數(shù)起始值不能取類型的最大值,比如int的最大限制為2^31,則基數(shù)起始值要預(yù)留空間,否則最后的子貼是無(wú)法回復(fù)的!!(或者如果限制了ordernum的范圍,雖然可以回復(fù),但它是平行顯示的)
使用了兩個(gè)基數(shù)的時(shí)候,一個(gè)子貼的回復(fù)數(shù)最多了900左右(int類型,30*30),14400(使用numeric類型時(shí)——此時(shí)的精度標(biāo)記得細(xì)加斟酌),理論是有限制都是不夠的,但實(shí)際上并不需要這么多。
對(duì)于基數(shù)分布不均勻的問(wèn)題是無(wú)法解決的,因?yàn)閷?shí)際上回復(fù)客戶回復(fù)哪條貼子是不可預(yù)測(cè)的。
使用2的冪作為基數(shù),是很容易理解的——不易近起結(jié)果取近似值(除非達(dá)到了計(jì)算機(jī)的最大精度),另一個(gè)原因是計(jì)算機(jī)使用二進(jìn)制進(jìn)行運(yùn)算,乘除2只是位移操作,速度要比其它數(shù)快得多(我是這么想的)。另一個(gè)個(gè)人的原因是因?yàn)槲覀(gè)算法是源于以前的思想:收斂數(shù)列與遞歸算法。
由于增加了算法復(fù)雜程度和冗余字段,如非必要,實(shí)非不必。
其實(shí)我是沒(méi)有時(shí)間進(jìn)行測(cè)試的,如果由于考慮不周或者算法錯(cuò)誤引起無(wú)法使用,還請(qǐng)多多指教。

歡迎訪問(wèn)我的個(gè)人主頁(yè)http://swuse.yeah.net

溫馨提示:喜歡本站的話,請(qǐng)收藏一下本站!

本類教程下載

系統(tǒng)下載排行

網(wǎng)站地圖xml | 網(wǎng)站地圖html
主站蜘蛛池模板: 商洛市| 莱西市| 荥经县| 启东市| 拉萨市| 迭部县| 庆阳市| 达州市| 武陟县| 东光县| 东莞市| 杭锦后旗| 定襄县| 蓬安县| 安福县| 九龙城区| 资溪县| 庆城县| 台东市| 临江市| 泸州市| 达孜县| 织金县| 凤冈县| 连州市| 蓝山县| 广河县| 玉林市| 建水县| 佛坪县| 庆阳市| 临澧县| 石首市| 青田县| 泰安市| 五常市| 灵台县| 万源市| 沙河市| 会同县| 华池县|