圖 1 未使用Ajax(a)和使用Ajax(b)的web應用比較 |
|
dl.bitsCN.com網管軟件下載
圖 3 樹型表結構示意圖 |
樹遍歷的時間複雜度是O( n ),可是將樹信息存放到數據庫後,就不能按傳統的方式遍歷樹,必須使用SQL 語句訪問數據庫表的內容,而一次性取的數據量越多,消耗的資源也越多,用戶等待的時間就越長。若是將無序的數據從數據庫中讀出,在服務器端,必須將排序後的樹送到客戶端顯示。所以,最好從數據庫讀出已排好序的樹。
咱們知道,字符串排序是按照字典序形式。結合SQL 語句的特色和樹結構特色,數據庫表中,節點的類別代碼採用多級字符串形式,如AAABBBCCC,從樹根節點開始,每向下一級字符串就增長一級,而且子節點類別代碼以父節點類別代碼開始,再開始本級的類別代碼。同級的節點按照生成的順序編號,如節點類別代碼爲AAA 的下一級孩子類別代碼爲AAAAAA,AAAAAB 等,AAAAAB 的孩子節點爲AAAAABAAA、AAAAABAAB等。每一級編號字符的寬度與實際的應用關聯,如AAA~ZZZ 一級則有263 個節點,若是不夠用再增長一個字符用於編碼。該巧妙的編號方式。使得在執行SQL 語句select * from tree_class order by classcode 後,一次得到完整的先序樹。
2.3 業務邏輯層設計
2.3.1 動態加載技術 play.bitsCN.com累了嗎玩一下吧
若是一次性獲取完整的先序樹,構形成xml提供給JavaScript解析,數據量越大,消耗的資源越多,客戶端響應延遲時間就越長,所以對於大數據量的樹,採用動態加載方式,即每次單擊「+」圖片時,判斷是否已加載子節點數據,若是未加載則經過Ajax的XMLHTTP組件XMLHTTPRequest對象異步發送請求,鏈接服務器執行SQL 語句「select * from tree_class where parent = ?order by classcode 」獲取節點數據。相關JavaScript 代碼以下:
/*判斷是否已經加載數據,未加載則訪問服務器加載數據*/ html
dhtmlTree.prototype.Loading=function(pObject){
if(((pObject.XMLload==0)&&(this.XMLsource))&&(!this.XMLloading)){
pObject.XMLload=1;
this.loadXML(this.XMLsource+getUrlSymbol(this.XMLsource)+"id="+escape(pObject.id));
}
}
dtmlXMLObject.prototype.loadXML=function(url){//加載數據
try {
this.xmlDoc = new XMLHttpRequest();
/*經過GET方法異步鏈接到 url 加載數據*/
this.xmlDoc.open("GET", url,true);//true:異步;false:同步
this.xmlDoc.send(null);
} catch(e){
this.xmlDoc = new ActiveXObject("Microsoft.XMLHTTP");//使用IE
this.xmlDoc.open("GET", url,true);//true:異步;false:同步
this.xmlDoc.send(null);
}
return this.xmlDoc.responseXML;
}
每次只取同一個父節點ParentId的子節點序列,按XML格式封裝成樹的文檔結構,例如:
<tree id="0">
<leaf child=」1" name="國防科技大學" id="1" im0="leaf.gif" im1="folderOpen.gif" im2=" folderClosed.gif"/>
</tree>
須要什麼來搜一搜吧so.bitsCN.com node
提供給JavaScript的dhtmlTreeObject.prototype.insertItem()解析並組織好html輸出節點;其中child:1表示有子節點,0表示沒有子節點;im0表示沒有子節點時的圖標;im1表示有子節點而且打開節點時的圖標;im2表示有子節點而且關閉時的圖標;因此還能夠在構造XML時自定義圖標。
2.3.2 樹型結構的構造
從數據庫中返回的是有序的先序樹,而XML是完整的樹型結構文檔,因此將樹型數據構形成預約義的XML格式,只需從根節點開始,遍歷一遍樹,便可將樹所有生成。相關JavaScript代碼以下:
/*動態加載樹的構造方法*/ web
dtmlXMLObject.prototype.constructTree=function(){ 數據庫
//採用動態加載時獲取的xml數據,解析樹型數據 bitsCN_com 設計模式
var node=this.XMLLoader.getXMLTopNode("tree"); bitsCN_com關注網管是咱們的使命 數組
var parentId=node.getAttribute("id"); bbs.bitsCN.com國內最先的網管論壇 瀏覽器
for(var i=0;i<node.childNodes.length;i++) { //逐個解析xml文件的leaf節點 服務器
if((node.childNodes[i].nodeType==1)&&(node.childNodes[i].tagName == "leaf")){
var name=node.childNodes[i].getAttribute("text");
…………
var temp=dhtmlObject.a0Find(parentId);//獲取父節點對象
temp.XMLload=1;//已加載
//構造html輸出節點
dhtmlObject.insertItem(parentId,cId,name,im0,im1,im2,chd);
dhtmlObject.addDragger = this;//設置可拖放的對象
};
}
2.3.3 樹型結構的維護
在維護樹型結構表時,刪除節點較爲簡單,SQL 語句爲: "delete from tree_class where classcode like′"+ classcode +"%′",便可將其節點和孩子一併刪除;增長節點時,分爲前插、後插、和插入子節點三種狀況,前兩種狀況須要更新遞歸更新類別代碼,後者只需找到父節點的孩子的最大類別代碼加1 後,做爲增長節點的類別代碼;經過拖放來改變樹的結構時,只需將拖動節點的parentId更新爲目標節點的Classid便可,對應的SQL語句爲:"update tree_class set parentId = "+ classidTo+" where classid = "+ classidFrom。
三、效率分析
對於樹的存儲通常有兩種形式:二維表和鏈表,遍歷方式通常也有深度遍歷和廣度遍歷兩種方式,遍歷的時間複雜度都是O( n )。用二維表存儲時,在內存中用數組的下標能準肯定位節點的父節點、兄弟節點所在的數組下標。數據庫中節點的定位也是準確的,可是將節點信息從數據庫中讀到內存中時,若是沒法經過內存數組下標定位節點信息,那麼就必須遍歷一遍尋找一個節點,n 個節點中尋找一個節點的時間是O(n/2),n 個節點排序的時間複雜度將是O( n 2/2),這也是通常實現的B/S 模式的樹結構效率低下的緣由。本方案採用字典序編號方案,使得從數據庫中取得的樹是已經排序的,直接遍歷生成客戶頁面程序,時間複雜度爲O( n )。 數據結構
bitsCN.com中國網管聯盟架構