樹形結構數據構建算法

在一些前端開發過程中,我們通常需要將後臺查詢出來的集合數據進行相應的轉換,轉成樹形結構對象,比如常用的評論區數據就是一種典型的樹形結構數據,如下圖所示。

而後臺服務端傳來的數據通常是一種普通的集合(元素中有 id 和 pid ,以此構成 父子節點關係)它們是一種數組集合對象(服務端可能是List集合 ,前端爲json對象或json串),如下圖所示

[{
	"CODE": "6",
	"PID": "0",
	"ID": "6",
	"NAME": "天安門金領總校"
}, {
	"CODE": "101",
	"PID": "6",
	"ID": "101",
	"NAME": "校辦"
}, {
	"CODE": "102",
	"PID": "6",
	"ID": "102",
	"NAME": "市場部"
}, {
	"CODE": "103",
	"PID": "6",
	"ID": "103",
	"NAME": "學術部"
}, {
	"CODE": "104",
	"PID": "6",
	"ID": "104",
	"NAME": "教質就業部"
}, {
	"CODE": "102101",
	"PID": "102",
	"ID": "102101",
	"NAME": "網諮部"
}, {
	"CODE": "102102",
	"PID": "102",
	"ID": "102102",
	"NAME": "媒體部"
}, {
	"CODE": "102103",
	"PID": "102",
	"ID": "102103",
	"NAME": "諮詢部"
}, {
	"CODE": "103101",
	"PID": "103",
	"ID": "103101",
	"NAME": "教員組"
}, {
	"CODE": "104101",
	"PID": "104",
	"ID": "104101",
	"NAME": "班主任組"
}, {
	"CODE": "104102",
	"PID": "104",
	"ID": "104102",
	"NAME": "就業專員組"
}, {
	"CODE": "104103",
	"PID": "104",
	"ID": "104103",
	"NAME": "學員組"
}]

上面的json數據是平行結構(列表)最終在前端構成的展示數據是一棵樹,如下圖所示

那麼,我們如何將平行結構的數據轉化成樹型對象數據(平行二維列表數據轉成有 N層次深度樹形對象) 如下圖所示

節點中如果有subnode屬性,則表明該節點非葉子節點(擁有子節點),圖中顯示了樹形對象的根節點,子節點,孫節點的關係

這裏涉及到常用算法參考如下

遞歸算法反覆構建葉子節點,至到將數組內的所有節點加載到相匹配的父級節點下,具體js代碼參數如下

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script lang="javascript">
var treelist = [{
	"CODE": "6",
	"PID": "0",
	"ID": "6",
	"NAME": "天安門金領總校"
}, {
	"CODE": "101",
	"PID": "6",
	"ID": "101",
	"NAME": "校辦"
}, {
	"CODE": "102",
	"PID": "6",
	"ID": "102",
	"NAME": "市場部"
}, {
	"CODE": "103",
	"PID": "6",
	"ID": "103",
	"NAME": "學術部"
}, {
	"CODE": "104",
	"PID": "6",
	"ID": "104",
	"NAME": "教質就業部"
}, {
	"CODE": "102101",
	"PID": "102",
	"ID": "102101",
	"NAME": "網諮部"
}, {
	"CODE": "102102",
	"PID": "102",
	"ID": "102102",
	"NAME": "媒體部"
}, {
	"CODE": "102103",
	"PID": "102",
	"ID": "102103",
	"NAME": "諮詢部"
}, {
	"CODE": "103101",
	"PID": "103",
	"ID": "103101",
	"NAME": "教員組"
}, {
	"CODE": "104101",
	"PID": "104",
	"ID": "104101",
	"NAME": "班主任組"
}, {
	"CODE": "104102",
	"PID": "104",
	"ID": "104102",
	"NAME": "就業專員組"
}, {
	"CODE": "104103",
	"PID": "104",
	"ID": "104103",
	"NAME": "學員組"
}];

function initTree(){   
   createTree(treelist);
}
//將傳入的數據構建成樹型對象
function createTree(treelist){
    // alert(treelist.length);
    // debugger;
    var treeData = new Array();
    for(var i = 0 ; i< treelist.length;i++){       
        //構建一級節點(根節點)
        if(treelist[i].PID == '0'){
            treeData.push(treelist[i]);
            console.log('構建一級節點:'+treelist[i].NAME);
            continue; //進入下一個元素處理
        }else{ //該元素非一級節點,將其掛在相應的節點下
            addNodeToTree(treelist[i],treeData);                
        }
    }
    console.log('tree對象構建完成');
    debugger;

}
//將node掛在treeData相應的節點下
function addNodeToTree(node ,treeData){
         for(var i = 0 ; i< treeData.length;i++){
             if(node.PID == treeData[i].ID){//說明是子節點
                if(typeof(treeData[i]["subnode"]) == "undefined"){
                    var subnode  = [];
                    subnode.push(node);
                    treeData[i]["subnode"] = subnode;  
                    console.log('給父節點:'+treeData[i].NAME+' 添加子節點:'+node.NAME+' 並集合化');
                    return true;
                }else{//該父節點已經存在子節點集合
                    treeData[i]["subnode"].push(node);
                    console.log('給父節點:'+treeData[i].NAME+' 添加子節點到集合:'+node.NAME);
                    return true;
                }            
             }
             //說明node節點不是該一級節點的子節點,如果該一級節點有子集合,則有可能是孫,重孫節點
            if(typeof(treeData[i]["subnode"]) != "undefined"){
                // console.log('需要檢查該節點下的子集合 ID:'+treeData[i].ID+' name:'+treeData[i].NAME);
                // debugger;
                //開始遞歸              
                if(addNodeToTree(node,treeData[i]["subnode"])){
                    return true;
                }else{
                    continue;
                }
            }
         }
         console.log('該集合下未匹配到合適的節點:'+node.NAME);
        //  debugger;
         return false;

}
//將樹型數據重新構造
</script>
</head>
<body onload="initTree()"> 
</body>
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章