前端的数据结构与算法(1)-- dfs

dfs

dfs

前端在开发过程中接触到的算法最多的莫过于排序和 dfs(深度优先遍历) 。 dfs 算法广泛用于图(树是图的一种)的遍历,如:没有 querySelectorAll 的时候,根据 classname 或者 tag 查找 element。

关于 dfs 算法的遍历过程,我简略的画了一个示例图:

dfs.gif

实例:

最近在实际业务场景中,跟后端约定页面中所有组件的消息根据页面上的组件 id 聚合到一个对象中,后端返回的是类似如下的一个树形数据结构。前端需要把所有的错误信息都拿出来,按照页面上所有组件的顺序聚合显示在一个全局信息面板组件上(至于按照组件顺序排序算法本文暂且略过)

let tree = {
    'id1': {
        message: 'hello'
    },
    'id2': {
        message: 'world',
        children: {
          'id2-1': {
              message: 'haha',
              children: {
              }
          },
          'id2-2': {
              message: 'heihei'
          }
        }
    }
}

由于某些大组件可能是由多个小组件层层嵌套组合而来,且每个小组件都有相应的 message 需要展示,所以就选择了上述的树形结构来表达组件的信息。这个时候就会有人问,为什么不让后端把所有 message 都聚合到数组里面?因为前端不仅需要把这些错误信息聚合到一起展示,也需要把错误定位到具体组件上

递归版本实现

function dfs(tree = {}, messages = []) {
    let i = 0;
    if(!messages) messages = [];
    if(tree.message) messages.push(tree.message);
    
    const keys = Object.keys(tree.children || {});
    while (i < keys.length) {
        dfs(tree.children[keys[i]], messages);
        i += 1;
    }
    return messages;
}

 tree = {
    message: null,
    children: tree
 };  
 
 dfs(tree);

非递归版本实现


  function dfs(tree = {}) {
    const array = [tree];
    let messages = [];
    while (array.length) {
      const top = array.pop();
      if (top.message) {
        messages.push(top.message);
      }
      const keys = Object.keys(top.children || {});
      let i = keys.length;
      while (i > 0) {
        i -= 1;
        array.push(top.children[keys[i]]);
      }
    }
    return messages
  }
  
 tree = {
    message: null,
    children: tree
 };  
 
 dfs(tree);

在实际使用中,考虑到数据结构的层数没那么多,其实尾递归版本和非递归版本所消耗的时间在浏览器的优化下几乎可忽略了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值