扁平数据转tree

测试数据:

const data = [
	  { id: 1, pid: 0 },
		{ id: 2, pid: 1 },
		{ id: 3, pid: 1 },
		{ id: 4, pid: 3 },
		{ id: 5, pid: 4 },
]

// 转换为
{
  id: 1, 
  pid: 0,
  children:[
    {
      id: 2,
      pid: 1,
      children:[]
    },
    {
      id: 3,
      pid: 1,
      children:[
        {
          id: 4,
           pid: 3,
          children:[
            {
              id: 5,
              pid: 4,
              children:[]
            }
          ]
        }
      ]
    }
  ]
}

思路:首先找到父级元素,然后遍历数组往父元素的children中push数据,通过递归向下一层数据中继续添加。

// 1.先遍历获取最外层的父元素
const parentArr = data.filter(item => !item.pid);

// 2.递归生成树结构
const toTree = (parent, child) => {
  parent.forEach(item => {
    // 添加children属性
    item.children = [];
    let list = [];
    child.forEach(i => { 
      if(i.pid && i.pid===item.id) {
        item.children.push(i);
        list.push(i);
      }
    })
    toTree(list, child);
  })
  return parent
}

toTree(parentArr, data);

然而,递归算法虽然简洁,但是效率却很低O(2^n),通常不作为推荐算法。

补充:

如何衡量算法的效率呢:一般从算法时间复杂度空间复杂度来衡量。

  • 时间复杂度:算法执行语句的次数。

    计算方法:

    1. 找出算法中的基本语句:算法中执行次数最多的那条语句就是基本语句,通常是最内层循环的循环体

    2. 计算基本语句的执行次数的数量级:只需保留f(n)中的最高次幂正确即可,可以忽略所有低次幂和最高次幂的系数

      如果算法中包含嵌套的循环,则基本语句通常是最内层的循环体,如果算法中包含并列的循环,则将并列循环的时间复杂度相加, 例如:

      for(i=1; i<n; i++) x++;

      for(i=1, i<n; i++){

      for(j=1; j<n; j++) x++;

      }

      第一个for循环的时间复杂度为Ο(n),第二个for循环的时间复杂度为Ο(n²),则整个算法的时间复杂度为Ο(n+n²)=Ο(n²)。

      注、加法原则:T(n)=O(f(n))+O(g(n))=O(max(fn,gn))

      常见的算法时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n²)<Ο(n³)<…<Ο(2^n)<Ο(n!)<O(n^n)

  • 空间复杂度:对一个算法在运行过程中临时占用存储空间的大小

    计算方法:

    1. 忽略常数,用O(1)表示

    2. 递归算法的空间复杂度=(递归深度n)*(每次递归所要的辅助空间)

非递归来, 使用Map结构实现。

const toTree = (list = [], { rootid = 0 } = {}) => {
	const parentMap = new Map();
	const topNodes = [];
	list.forEach(item => {
		// list数据不是递增顺序,先将parentMap赋值,防止后面取不到
		parentMap.set(item.id, item);
	})

	list.forEach(item => {
		if(parentMap.has(item.id)) {
			item.children = parentMap.get(item.id).children || [];
		} else {
			item.children = [];
		}

		if(parentMap.has(item.pid)) {
		(	parentMap.get(item.pid).children ||[]).push(item);
		} else {
			parentMap.set(item.pid,{children:[item]})
		}

		if(item.pid === robotId){
			topNodes.push(item)
		}
	})
		
    return topNodes;
}
	
	toTree(data, { rootid: 0 })

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值