JavaScript遍历树

725 阅读1分钟

遍历树的几种方式: 递归遍历,非递归深度优先遍历,非递归广度优先遍历。

recursiveTree.png

如上图,在 JavaScript 中可以用 object 表示如下:

let tree = {
  value: 10,
  children: [
    {
      value: 15,
      children: [
        {
          value: 7,
          children: []
        },
        {
          value: 18,
          children: []
        }
      ]
    },
    {
      value: 4,
      children: []
    },
    {
      value: 8,
      children: [
        {
          value: 23,
          children: []
        }
      ]
    }
  ]
};

递归遍历

const recursiveTraverse = function(node, action) {
	if (!node || !node.children) {return;}
	action(node.value);
	node.children.forEach(function(item, index) {
		recursiveTraverse(item, action)
	})
}

recursiveTraverse(tree, console.info)
// 输出结果: 
10
15
7
18
4
8
23

非递归深度优先遍历(借助栈实现)

const nonRecursiveDepthFirstTraversal = function (node, action) {
	if (!node || !node.children) { return; }
	let _stack = []; // 借助一个栈
	_stack.unshift(node);
	while (_stack.length) {
		let _curNode = _stack.shift(); // 推出栈顶元素
		action(_curNode.value);
		// 将子节点依次放入到栈顶
		// _curNode.children.forEach(function (item, index) {
		// 	_stack.unshift(item);
		// })
		if (_curNode.children.length) {
			_stack = _curNode.children.concat(_stack);
		}
	}
}
// 非递归深度优先遍历
nonRecursiveDepthFirstTraversal(tree, console.log);

// 输出结果:
10
15
7
18
4
8
23

非递归广度优先遍历(借助队列实现)

const nonRecursiveWidthFirstTraversal = function (node, action) {
	if (!node || !node.children) { return; }
	let _queue = []; // 借助一个队列
	_queue.push(node);
	while (_queue.length) {
		let _curNode = _queue.shift(); // 推出队头元素
		action(_curNode.value);
		// 将子节点依次推入队列中
		// _curNode.children.forEach(function (item, index) {
		// 	_queue.push(item);
		// })
		if (_curNode.children.length) {
			_queue = _queue.concat(_curNode.children);
		}
	}
}
// 非递归宽度优先遍历
nonRecursiveWidthFirstTraversal(tree, console.log);
// 输出结果:
10
15
4
8
7
18
23