js遍历树形结构

现在假设有一颗这样树,(是不是二叉树都没关系,原理都是一样的)

广度优先
        英文缩写为BFS即Breadth FirstSearch。其过程检验来说是对每一层节点依次访问,访问完一层进入下一层,而且每个节点只能访问一次。对于上面的例子来说,广度优先遍历的结果是:A,B,C,D,E,F,G,H,I(假设每层节点从左到右访问)。
       广度优先遍历各个节点,需要使用到队列(Queue)这种数据结构,queue的特点是先进先出,其实也可以使用双端队列,区别就是双端队列首位都可以插入和弹出节点。整个遍历过程如下:
      首先将A节点插入队列中,queue(A);
      将A节点弹出,同时将A的子节点B,C插入队列中,此时B在队列首,C在队列尾部,queue(B,C);
      将B节点弹出,同时将B的子节点D,E插入队列中,此时C在队列首,E在队列尾部,queue(C,D,E);
      将C节点弹出,同时将C的子节点F,G,H插入队列中,此时D在队列首,H在队列尾部,queue(D,E,F,G,H);
      将D节点弹出,D没有子节点,此时E在队列首,H在队列尾部,queue(E,F,G,H);
      ...依次往下,最终遍历完成

export function breadthFirst(obj){
  var queue = [];
  var node;
  queue.push(obj);
  while (queue.length !== 0) {
    node = queue.shift();
    if (node.child && node.child.length > 0) {
      node.child.forEach(function (item, index) {
        if (item.attr && /display:[\s]*?none/.test(item.attr.style)) {
            /*此处有坑,不能直接删除,需要用空对象填充,保证node.child数组长度不变*/
          node.child.splice(index, 1,{});
        } else {
          queue.push(item);
        }
      })
    }
  }
  return obj;
}

深度优先

    英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。对于上面的例子来说深度优先遍历的结果就是:A,B,D,E,I,C,F,G,H.(假设先走子节点的的左侧)。
    深度优先遍历各个节点,需要使用到堆(Stack)这种数据结构。stack的特点是是先进后出。整个遍历过程如下:
首先将A节点压入堆中,stack(A);
    将A节点弹出,同时将A的子节点C,B压入堆中,此时B在堆的顶部,stack(B,C);
    将B节点弹出,同时将B的子节点E,D压入堆中,此时D在堆的顶部,stack(D,E,C);
    将D节点弹出,没有子节点压入,此时E在堆的顶部,stack(E,C);
    将E节点弹出,同时将E的子节点I压入,stack(I,C);
    ...依次往下,最终遍历完成

export function depthFirst(obj){
	var stack = [];
	var node;
	stack.push(obj);
	while (stack.length > 0) {
        node = stack.pop();
        //获得节点的子节点,对于二叉树就是获得节点的左子结点和右子节点
        if(node.child && node.child.length>0){
        	node.child.forEach(function(item,index){
        		if(item.attr && /display:[\s]*?none/.test(item.attr.style)){
        			node.child.splice(index, 1, {});
        		}else{
        			stack.push(item);
        		}
        	})
        }
    }
    return obj;
}

测试数据:

{
  "node": "root",
  "child": [
    {
      "node": "element",
      "tag": "div",
      "child": [
        {
          "node": "element",
          "tag": "div",
          "child": [
            {
              "node": "element",
              "tag": "div",
              "attr": {
                "style": "display:none"
              },
              "child": [
                {
                  "node": "text",
                  "text": " "
                }
              ]
            },
            {
              "node": "element",
              "tag": "div",
              "attr": {
                "style": "display:none;"
              },
              "child": [
                {
                  "node": "element",
                  "tag": "div"
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "node": "element",
      "tag": "div",
      "attr": {
        "style": "display:none;"
      },
      "child": [
        {
          "node": "element",
          "tag": "div",
          "child": [
            {
              "node": "text",
              "text": " "
            }
          ]
        }
      ]
    },
    {
      "node": "element",
      "tag": "div",
      "attr": {
        "style": "display:none;"
      },
      "child": [
        {
          "node": "element",
          "tag": "div",
          "child": [
            {
              "node": "text",
              "text": " "
            }
          ]
        }
      ]
    }
  ]
}

输出结果:

{
  "node": "root",
  "child": [
    {
      "node": "element",
      "tag": "div",
      "child": [
        {
          "node": "element",
          "tag": "div",
          "child": [
            {},
            {}
          ]
        }
      ]
    },
    {},
    {}
  ]
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值