Dom的深度優先遍歷和廣度優先遍歷


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>深度遍歷和廣度遍歷測試</title>
    <style type="text/css">
        
    </style>
</head>
<body>
<div class="box">
   <ul class="menus">
      <li class="item1"><i class="item1-icon"></i><span class="item1-content">菜單1</span></li>
      <li class="item2"><i class="item2-icon"></i><span class="item2-content">菜單2</span></li>
      <li class="item3"><i class="item3-icon"></i><span class="item3-content">菜單3</span></li>
   </ul>
</div>
<script>
console.log('深度優先遞歸');
DFTRecur(document.body,[],function(item){
    console.log(item);
});


console.log('深度優先非遞歸');
let res = DFT(Array.from(document.body.children),function(item){
    // if(item.className == 'item2-content'){
    //     console.log('taget item', item);
    //     return true;
    // }
    console.log(item);
});


console.log('廣度優先遞歸');
BFTRec(document.body,[]);


console.log('廣度優先非遞歸');
BFT(Array.from(document.body.children));

 
//深度優先搜索的遞歸寫法
function DFSRecur(root,stack,fVistor) {
    let b = false;
    if (root != null) {  
        stack.push(root);  
        //函數fVistor,節點傳入函數,節點一旦滿足某種條件,就返回true
        //可以在找到第一個滿足條件的節點后,就停止遍歷
        if(fVistor(root))return true;
    
        var children = root.children;  
        if(children){
            for (var i = 0; i < children.length; i++){
                b = DFTRecur(children[i],stack,fVistor);  
                //有一個子節點滿足條件就停止循環
                if(b) break;
            } 
        }
        //當前節點及其子節點都不滿足條件就出棧
        if(!b) stack.pop();
    }  
    return b;
}

//深度優先遍歷的遞歸寫法,深度優先遍歷遞歸,不需要使用棧,通常是使用先序遍歷,即先遍歷根節點,再遍歷所有子節點
function DFSRecur(root,stack,fVistor) {
    if (root != null) {  
        fVistor(root)
    
        var children = root.children;  
        if(children){
            for (var i = 0; i < children.length; i++){
                DFTRecur(children[i],stack,fVistor);  
            } 
        }
    }  
}

//深度優先遍歷的非遞歸寫法
function DFT(root,fVistor) {
    fVistor = fVistor || console.log;
    if (root != null) {
        //兼容root為數組,且從前往后深度遍歷
        var stack = [].concat(root).reverse();
        
        while (stack.length != 0) {
            var item = stack.pop();
            //滿足條件就break,使得方法兼具深度優先搜索的功能,找到就跳出循環,停止查找
            if(fVistor(item)) break;if(item.children) stack.push(...Array.from(item.children).reverse());
        }
    }  
}

//廣度優先遍歷的遞歸寫法,廣度優先的遞歸和非遞歸寫法都需要隊列
function BFTRec(root,queue,fVistor){
    fVistor = fVistor || console.log;
    if(root != null){
       queue.push(root);
       //滿足條件return,使該方法兼具廣度優先搜索的功能,找到就停止遍歷
       if(fVistor(root)) return;
       //先訪問下一個兄弟節點,遞歸會一直橫向訪問,直至橫向訪問完畢
       BFTRec(root.nextElementSibling,queue,fVistor);
       //回到本行的第一個節點root
       root = queue.shift();
       //跳到root節點的下一行的第一個節點,又會開始橫向遍歷
       BFTRec(root.firstElementChild,queue,fVistor);
    }
}

//廣度優先遍歷的非遞歸寫法
function BFT(root,fVistor) {
    fVistor = fVistor || console.log;
    if (root != null) {
        //兼容root為數組情況
        var queue = [].concat(root);
        while (queue.length != 0) {
            var item = queue.shift();
            //找到就break,使得方法兼具廣度優先搜索功能,找到就停止遍歷
            if(fVistor(item)) break;
            if(item.children) queue.push(...item.children);
        }
    }
}
</script>
</body>
</html>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM