iT邦幫忙

2024 iThome 鐵人賽

DAY 12
0
Software Development

六邊形戰士程式設計系列 第 12

D12 - 樹狀搜尋問題 效能分析篇

  • 分享至 

  • xImage
  •  

請搭配 D10 - 樹狀搜尋問題 實作篇 閱讀。

從演算法的角度上來看,假設 N 為樹的節點數量,「結構化」與「函數式」兩種時作方式在空間複雜度,以及時間複雜度上都是相等的 O(N)。

function getNameById(target:string){
    let queue = [tree]
    while(queue.length > 0){
        let node = queue[0]
        if(node.id === target){
            return node.text // 如果是目標點就結束並返回
        }
        for(let child of node.children){ 
            queue.push(child)
        }
        queue.shift()
    }
    return undefined
}

然而透過實際執行的流程來看,結構式會在執行的時候,在找到目標的當下。就會跳出迴圈、結束函示,直接顯示結果。

const getNameById = (target:string)=>(tree:Tree):string | undefined =>
    tree.id === target 
        ? tree.text 
        : tree.children
            .map(getNameById(target)) // 全部遍歷過
            .find(text=>text!==undefined) 

函數式程式設計中,上面的做法卻會把目標全部遍歷過再找出結果。這種效能差距雖然在函式只有一個的時候看不出來,但是隨著層層疊疊的函式呼叫,累積起來也可能造成很可觀的效能損失。

const getNameById = (target:string)=>(tree:Tree):string | undefined =>
    tree.id === target 
        ? tree.text 
        : tree.children
            .map(getNameById(target)) 
            .find(text=>text!==undefined)  

即使在 index 0 就找到,還是必須把後面的流程全部跑完,想想實在是不舒服! 因此我們可以再對函數式的實作做一些小小的優化

const getNameById = (target:string)=>(tree:Tree):string | undefined =>
    tree.id === target 
        ? tree.text
        : tree.children
            .reduce(
                (accumulator,current)=>
                    accumulator??getNameById(target)(current),
                "" as string | undefined
            )

藉由 reduce 取代 map,就可以達到類似結構式程式設計的實作中 early return 的效果囉!


上一篇
D11 - 樹狀搜尋問題 複雜度分析篇
系列文
六邊形戰士程式設計12
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言