資料結構之從鍊錶而來的森林

2021-07-26 02:58:37 字數 1727 閱讀 6540

公司專案有個需求,使用者通過網頁對目錄結果進行編輯後,產生了如下的陣列結構,後台需要對這個陣列轉換成乙個森林,然後方便的進行渲染。

這個陣列原型大概如下圖,

|—— 根目錄 level:-1

|—— 目錄a level:0

|—— 目錄a_1 level:1

|—— 目錄a_1_1 level:2

|—— 目錄a_2 level:1

|—— 目錄a_2_1 level:2

|—— 目錄a_2_1_1 level:3

|—— 目錄a_2_1_1_1 level:4

|—— 目錄a_3 level:1

|—— 目錄a_3_1 level:2

|—— 目錄a_3_2 level:2

|—— 目錄b level:0

|—— 目錄b_1 level:1

|—— 目錄b_1_1 level:2

|—— 目錄b_1_1_1 level:3

|—— 目錄b_2 level:1

|—— 目錄c level:0

..........

陣列結果類似下圖(上面的結構和下面的陣列並不匹配,只是乙個栗子)

[,,

,,,,

,,,,

,];

從上向下遍歷陣列然後比較,判斷父子節點的關係也可以建立這顆森林,我想的是從最深的節點開始,對樹進行收斂。中心思想是:找到最深的節點,判斷它上乙個節點,如果是它的父,則建立父子關係,然後重新尋找最深的節點;如果是它的兄弟,則建立兄弟關係,然後兄弟抱團去找他們的父親(他兩合併變成最深的節點,繼續向上找乙個節點),迴圈如此,直到找到根節點為止。

演算法使用js實現如下,buildtree是入口方法,引數就是我們需要轉換的陣列結構,返回值為結果森林。

/**

* 建立樹

*/function buildtree(source)

var index = indexofmaxlevel(source);

var target = source[index];

return restraintree(source, target, index);

}/**

* 對樹本身進行收斂拼接

* index表示當前node所在的source的位置

*/function restraintree(source, node, index)

// 從當前節點往上取乙個節點進行比較

var pre = source[preindex];

// 取出最頂上面的節點,也就是當前節點

var cur = array.isarray(node) ? node[0] : node;

if (pre.level < cur.level) else

if (pre.level == cur.level) else

}/**

* 清理樹中已經處理過的節點

*/function removefromarray(arr, index, node)

return arr.slice(0, index).concat(arr.slice(index + size, arr.length));

}// 獲得最大層數的index

function indexofmaxlevel(arr)

}return index;

}

資料結構 表之煉表

頭插法建立 尾插法建立 顯示 銷毀 include include using namespace std typedef int elemtype typedef struct lnode linklist void createlinklistf linklist l,elemtype a,in...

資料結構之鍊錶

頭結點 第乙個有效結點之前的那個結點 頭結點並不存有效資料 加頭結點的目的主要是為了方便對鍊錶的操作 頭指標 指向頭結點的指標變數 尾指標 指向尾節點的指標變數 如果希望通過乙個函式對鍊錶進行處理,只需要乙個引數 頭指標 首先要定義乙個單鏈表儲存結構 然後建立乙個空表,即初始化,我寫的這個提前設定好...

資料結構之鍊錶

鍊錶是一種基本的資料結構型別,它由乙個個結點組成。每乙個結點包括乙個資料的儲存和乙個指向下乙個結點的引用。在這個定義中,結點是乙個可能含有任意型別資料的抽象實體,它所包含的指向結點的應用顯示了它在構造鍊錶之中的作用。和遞迴程式一樣,遞迴資料結構的概念一開始也令人費解,但其實它的簡潔性賦予了它巨大的價...