使用“使用中值排序基數法”實現樹狀結構(一)

來源:互聯網
上載者:User
排序|排序 在BBS的編寫中,經常有人問怎樣實現樹狀結構?一個比較不負責任的回答是:使用遞迴演算法。當然,遞迴是一個可行的辦法(二叉樹的曆遍也好象只能使用遞迴演算法),但對於BBS來說,這樣做勢必要進行大量的Sql查詢(雖然可以使用預存程序來做,但要從根本上加快速度,則應該考慮更快的演算法)。
下面給出一個可行的徹底屏棄遞的實現樹狀結構的演算法。

下面給出另一種使用“使用中值排序基數法”實現樹狀結構:
一、主要思想:增加一個排序基數欄位ordernum,回複同一根貼的貼子中插入貼子時,排序基數ordernum取兩者的中值。
為了敘述的簡潔,在此只討論與樹狀結構有關的欄位。

在表中增加三個冗餘欄位,rootid——用於記錄根id,deep——用於記錄回複的深度(為0時表示根貼),ordernum——排序基數(關鍵所在)。

表forum與(只列與樹狀結構有關的欄位):
id rootid deepordernum
其中id、rootid、deep均為int型(deep可為tinyint型),ordernum為float型。

例:(在此為了簡單,使用一個小的起始排序基數,在實際應用中,應使用較大的起始基數,且應取2的整數次冪,如65536=2^16,下面所說的排序均指按ordernum從小到大排序)。
id rootiddeepordernum
1000
211 64
______________________________
311 32回複第1貼,取1、2基數的中值即(0+64)/2

排序後結果為:
id rootiddeepordernum
1000
311 32
211 64
______________________________
412 48 回複第3貼,取3、2的基數中值即(32+64)/2

排序後結果為:
id rootiddeepordernum
1000
311 32
412 48
211 64
______________________________
513 56回複第4貼,取4、2的基數中值即(48+64)/2

排序後的結果為:
id rootiddeepordernum
1000
311 32
412 48
513 56
211 64
______________________________
612 40回複第3貼,取3、4的基數中值即(32+48)/2

排序後的結果為:
id rootiddeepordernum
1000
311 32
612 40
412 48
513 56
211 64

這樣排序基數ordernum與回複深度deep一起就實現了如下的樹狀結構:
id
1
3
6
4
5
2


二、插入的實現(如何確定排序基數,下面所指貼子均為同一根下的子貼)
(一)根ordernum定為0
(二)第一條回複貼子基數定為2的整數次冪(如65536=2^16,可取更大的數)
(三)回複最後一條貼子時,基數取最後一貼的基數ordernum再加上2的整數次冪(同上)
(四)回複中間的貼子時,基數ordernum取前後貼子的基數中值

三、刪除的實現
刪除貼子(剪枝)時,只需找出下一個回複深度deep小於或等於要刪貼子的回複深度(deep)的貼子,然後將基數ordernum位於兩個貼子基數之間的貼子刪除即可實現剪枝。
如上例子中,要刪除3貼(基數為32)下的子枝,由於3的深度為1,下一個深度小於或等於1的貼子為2貼(它的基數為64),則只需刪除基數在32至64間(64除外)的貼子就行了。也就是刪除了3、6、4、5貼。要刪其它亦然。

四、顯示的實現
只需執行select * from forum order by rootid+id-sign(rootid)*id
desc,ordernum,然後結合deep就可實現樹狀的顯示。


五、具體實現方法(以預存程序為例)

加貼預存程序:(省略註冊使用者檢測以及積分部分內容)

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 ——回複的是最後一貼
ELSE
SELECT @ordernum=(@begnum+@endnum)/2——關鍵,取排序基數中值
INSERT into forum (rootid,deep,ordernum,……)
values(@rootid,@deep+1,@ordernum,……)
END
END
Select @message='成功'
return




相關文章

Cloud Intelligence Leading the Digital Future

Alibaba Cloud ACtivate Online Conference, Nov. 20th & 21st, 2019 (UTC+08)

Register Now >

Starter Package

SSD Cloud server and data transfer for only $2.50 a month

Get Started >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。