js 非递归深度优先遍历树结构数据
使用递归方法实现对树的遍历效率非常低,下面利用栈的特性来实现对树的深度优先遍历;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>tree</title>
</head>
<body>
<script>
var tree = {
name : '中国',
children : [
{
name : '北京',
children : [
{
name : '朝阳群众'
},
{
name : '海淀区'
},
{
name : '昌平区'
}
]
},
{
name : '浙江省',
children : [
{
name : '杭州市',
code : 0571,
},
{
name : '嘉兴市'
},
{
name : '绍兴市'
},
{
name : '宁波市'
}
]
}
]
};
// 深度遍历 --- 使用栈
function dfs(tree, name){
var stack = [];
// 从根节点往下遍历
while (tree) {
if (tree.name === name) {
return tree;
}
// 若节点有孩子节点,继续遍历
if (hasProperty(tree, 'children') && tree.children.length > 0) {
// 若节点有不止一个孩子节点,则将孩子节点非第一个节点全部压入栈中
// 因为栈是先进后出,为了实现按序访问,需要将孩子节点倒序压入栈
for (var i = tree.children.length - 1; i > 0; i--) {
stack.push(tree.children[i])
}
// 访问当前节点的第一个子节点
tree = tree.children[0];
} else {
// 节点没有孩子节点,则当前节点为叶子节点
// 判断栈中是否有节点, 若有则继续遍历
if (stack.length > 0) {
tree = stack.pop();
} else {
// 栈中已经不存在节点,退出遍历,节点不存在
return ;
}
}
}
return ;
}
// 广度遍历 --- 使用队列
function bfs(tree, name) {
var queue = [];
// 从根节点往下遍历
while (tree) {
if (tree.name === name) {
return tree;
}
// 若节点有孩子节点,继续遍历
if (hasProperty(tree, 'children') && tree.children.length > 0) {
// 将该节点的非第一个子节点顺序加入队列中
for (var i = 1; i < tree.children.length; i++) {
queue.push(tree.children[i])
}
// 直接访问当前节点的第一个子节点
tree = tree.children[0];
} else {
// 节点没有孩子节点,则当前节点为叶子节点
// 判断栈中是否有节点, 若有则继续遍历
if (queue.length > 0) {
tree = queue.shift();
} else {
// 栈中已经不存在节点,退出遍历,节点不存在
return ;
}
}
}
return ;
}
function hasProperty(node, prop) {
if (node && node.hasOwnProperty(prop)) {
return true;
}
return false;
}
const node = dfs(tree, '杭州市');
console.log(node); // { name: '杭州市', code: 0571 }
</script>
</body>
</html>