阿瑟 發表
先建立有兩個欄位的資料表: 一欄位紀錄節點名稱, 另一欄位紀錄父節點名稱. 然後利用遞迴函式即可建立樹狀圖.
其實要製作一個樹狀圖並不困難.
只要記得在寫任何程式千萬不要一頭栽入, 而要仔細思考程式之中的邏輯. 就程式撰寫的部份, 最起碼要經過兩個階段: 邏輯設計 (Logical Design) 與 實體設計 (Actual Design). (Microsoft Solution Framework, MSF)
邏輯設計著重於程式邏輯與演算法的籌劃, 用"整體"的概念去思考程式中的每個功能. 就拿樹狀圖來說, 你可以拿一張紙畫出一樹狀圖. 然後試想:
如果以上是您所建立的資料表, 而 none 代表沒有父節點, 即該節點為最上層項目. 那要如何建立樹狀圖呢?
節點名稱 父節點 亞洲 none 印度 亞洲 台灣 亞洲 中國大陸 亞洲 菲律賓 亞洲 北美洲 none 美利堅合眾國 北美洲 墨西哥 北美洲 加拿大 北美洲
實體設計的部份, 我們要開始思考如何撰寫在邏輯設計部分寫出的程式邏輯, 或演算法.
如果我們已經建立了資料庫連結 (Database Connection), 我們可以用:
set rsm = Server.CreateObject("ADODB.Recordset") sql="SELECT *FROM 資料表 WHERE 父節點='" & none & "' ORDER BY 節點名稱" rsm.Open sql, cons,1, 3
set rsm = Server.CreateObject("ADODB.Recordset") sql="SELECT *FROM 資料表 WHERE 父節點='" & none & "' ORDER BY 節點名稱" rsm.Open sql, cons,1, 3 if NOT rsm.eof while NOT rsm.eof response.write rsm("節點名稱") rsm.movenext wend end if
set rsm = Server.CreateObject("ADODB.Recordset") sql="SELECT *FROM 資料表 WHERE 父節點='" & none & "' ORDER BY 節點名稱" rsm.Open sql, cons,1, 3 if NOT rsm.eof while NOT rsm.eof response.write rsm("節點名稱") & "<br>" set rsm2 = Server.CreateObject("ADODB.Recordset") sql2="SELECT *FROM 資料表 WHERE 父節點='" & rsm("節點名稱") & "' ORDER BY 節點名稱" rsm2.Open sql2, cons,1, 3 if NOT rsm2.eof while NOT rsm2.eof response.write rsm2("節點名稱") & "<br>" rsm2.movenext wend end if rsm.movenext wend end if
但是如果今天您要做的樹狀圖是:
其實幾乎多數用迴圈能解決的問題, 用遞迴函式 (Recursive Function) 幾乎都有辦法達到同樣的效果.
如果您不清楚什麼是遞迴函式, 您可以看看這個範例:
function calc(number) if number>1 then calc = number + calc(number-1) else calc = 1 end if end function
我們可以先寫一個會搜尋指定父節點的函式, 然後在每個找到的節點下再執行同樣的函式來尋找其子節點, 善用遞迴的特性.
以下是範例遞迴函式:
<% function extendTree(parent) set rsm = Server.CreateObject("ADODB.Recordset") sql="SELECT *FROM 資料表 WHERE 父節點='" & parent & "' ORDER BY 節點名稱" rsm.Open sql, cons,1, 3 if NOT rsm.eof Then response.write "<dir>" while NOT rsm.eof response.write "<li>" & rsm("節點名稱") extendTree rsm("節點名稱") response.write "</li>" rsm.movenext wend response.write "</dir>" end if rsm.close end function %>
要製作樹狀圖, 只要執行 extendTree("none") 來找出所有父節點為 none, 也就是沒有父節點的資料即可.
執行 extendTree("none") 的時候, 函式會找出所有最上層節點, 如 "中國大陸" 與 "美國".
之後函式會以每個節點為參數再次執行函式, 如找到"中國大陸"就會執行 extendTree("中國大陸")
如果沒有找到任何子結點當然extendTree()就會自動停止 (就跟之前範例到1會自動停止遞迴是一樣的), 因此利用遞迴這種演算法可以很彈性的設計自己的樹狀圖, 不管怎麼新增節點都不需要修改程式.
這個範例遞迴函式唯一的問題就是資料表中的節點不能夠有重複的名稱, 如上海市下有"市政府"子節點的話, 紐約市就不能有同樣名稱的子節點, 否則會混淆, 產生怪異的輸出結果.
大家可以再研究看看有沒有別的寫法, 很有趣的.