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); } } } //广度优先遍历的非递归写法,遍历到k-1层,适用于限定遍历到第几层的情况,同时可以获取第k层的节点数量 function BFT(root,fVistor,k) { fVistor = fVistor || console.log; if (root != null) { //兼容root为数组情况 var queue = [].concat(root); var level = 1; while (queue.length != 0) { var levelSize = queue.length; if(level == k){ return levelSize; //可以获取第k层的节点数量,同时遍历到第k-1层就停止遍历 } while(levelSize > 0){ var item = queue.shift(); //找到就break,使得方法兼具广度优先搜索功能,找到就停止遍历 if(fVistor(item)) break; if(item.children) queue.push(...item.children); levelSize--; } level++; } } } </script> </body> </html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具