多層次清單標號處理,樹的建構與有序節點遍歷(深度優先) - 建構篇


Posted by monoserve174 on 2024-07-16

最近工作遇到有關多層次清單標號的資料處理,經某主管說要自己處理之後,程式碼丟上來,稍微理解程式邏輯後,發現在處理多層次清單標號,需要樹的建構與有序遍歷節點的概念。那個說要處理的,最後還是把程式碼來後,還是需要後續處理。但...筆者雖然有聽過樹也知道要遍歷,可是...當時就是生不出來程式才退選演算法與資料結構阿...。最後,還是如期完成了工作,就做個筆記紀錄一下吧。

問題定義

多層次清單標號處理是一種對分層結構中的每一個層級進行編號的方法。要先了解層級與標號之間的關係。
層級 : 每一層級表示一個節點在樹結構中的深度。第一層是根節點,第二層是根節點的子節點...
標號 : 每個節點根據其在層級中的順序進行編號,並且這個編號是層次化的。例如,第一層的第一個節點可能標號為 1,第二層的第一個節點可能標號為 1.1,第二層的第二個節點則標號為 1.2。
範例

1. 第一章
1.1 第一節
1.1.1 第一段
1.2 第二節
1.2.1 第一段
2. 第二章
2.1 第一節
2.2 第二節
2.2.1 第一段
2.2.2 第二段

建構樹

節點處理

範例中,一共有三個層級,第一層層級為章,第二層層級為節,第三層層級為段,每個層級的標號皆為有序的一、二...,了解範例結構後,開始建構樹結構。
每個節點都有

  1. 父節點(parent)
  2. 子節點(children)
  3. 節點資訊(content) - 非必要
    開始按此節點結構生成樹

結構生成

level_info = ['章', '節', '段']
此時將整篇文章看做一顆樹的根節點 (root_node) 後

  1. parent: None 空值
  2. children: [] 空陣列
  3. content: 'root' 字串

在讀資料之前,先設定參考值

  1. 前層層級(prev_level): -1
  2. 前層節點(prev_node): root_node

開始逐行將資料讀入,
第一行 (1. 第一章),可以透過對 level_info 做迴圈,找到"章"這個關鍵字後紀錄其指標序號,此序號即為當前層級(cur_level),此時範例為 0。
cur_level = 0
並建構當前節點(cur_node)

  1. parent: None 空值
  2. children: [] 空陣列
  3. content: '第一章' 字串
    判斷1: 若當前層級(cur_node = 0)大於先前層級(prev_level = -1),則當前層級為前層層級的子節點
    此時處理兩件事 1. 將本層節點放入前層的子節點列表中 2. 將本層節點 parent 指定為前層節點
    最後將調整前層層級、前層節點,設定為本節點資訊即
    prev_level = cur_level
    prev_node = cur_node

第二行 (1.1 第一節),判斷1

第三行 (1.1.1 第一段),判斷1

第四行 (1.2 第二節)
cur_level = 1
cur_node 建構如下

  1. parent: None 空值
  2. children: [] 空陣列
  3. content: '第二節' 字串
    判斷2: 若當前層級(cur_level = 1)小於先前層級(prev_level = 2),則當前節點不屬於前層節點的子節點,此時需要先將前層節點找出來,循環下列步驟,直當前層級(cur_level)大於先前層級(prev_level)
  4. prev_level = prev_level - 1
  5. prev_node = prev_node.parent
    經上述步驟,會將得到
    prev_level = 0
    prev_node 的結構為
    prev_node.parent = root_node
    prev_node.children = [第一節_node]
    prev_node.content = '第一章' 字串
    找出正確前層節點後,再處理兩件事 1. 將本層節點放入前層的子節點列表中 2. 將本層節點 parent 指定為前層節點
    最後將調整前層層級、前層節點,設定為本節點資訊即
    prev_level = cur_level
    prev_node = cur_node

第五行(1.2.1 第一段),判斷1
第六行(2. 第二章),判斷2
第七行(2.1 第一節),判斷1
第八行(2.2 第二節),先確認前層資訊
prev_level = 1
prev_node 結構如下
prev_node.parent = 第二章_node
prev_node.children = [第一節_node]
prev_node.content = '第二章' 字串
本層資訊為
cur_level = 1
cur_node 建構如下

  1. parent: None 空值
  2. children: [] 空陣列
  3. content: '第二節' 字串
    判斷3: 若當前層級(cur_level = 1)等於先前層級(prev_level = 1),則當前節點屬於前層節點的父節點的子節點,也就是判斷2的特例,因此,改寫判斷2的小於轉為小於等於。

第九行(2.2.1 第一段),判斷1
第十行(2.2.2 第二段),判斷2
按此作法即可構建出文章的多層次清單標號處理轉為樹結構。

待續...


#data structure #multi-level-label







Related Posts

從 V8 bytecode 探討 let 與 var 的效能問題

從 V8 bytecode 探討 let 與 var 的效能問題

CH5. 大師級函式:閉包與範圍

CH5. 大師級函式:閉包與範圍

CSS保健室|opacity

CSS保健室|opacity


Comments