写在前面:
循环判断用成员属性 存在风险,节点本身
while(root.left)//不推荐
while(root!=null)//推荐
回溯的思想
根—叶节点的所有路径
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
var binaryTreePaths = function (root) {
if (!root) return [];
const ans = [];
const dfs = (node, path) => {
if (!node) return;
if (!node.left && !node.right) {
ans.push([...path, node.value].join('->'));//...path去除方括号
return;
}
dfs(node.left, [...path, node.value]);//分别遍历左右节点
dfs(node.right, [...path, node.value]);
};
dfs(root, []);
return ans;
};
先序和后序_递归
采用递归即可
先序
var preorderTraversal = function(root) {
let arr = [];
if(!root) {return arr}
let traver = (root) => {
arr.push(root.val);
if(root.left){ traver(root.left) };
if(root.right){ traver(root.right) };
}
traver(root);
return arr;
};
后序将递归结构改为
let traver = (root) => {
if(root.left){ traver(root.left) };
if(root.right){ traver(root.right) };
arr.push(root.val);
}
中序借助栈来实现
1.拿到一颗树的根节点,将根节点和所有左节点依次进栈
2.从栈顶取出 最底下的左节点,输出
3.将最底下的左节点的右节点作为一棵树循环123
若右节点为null,从栈顶取出的则是次底左节点
存在右节点,则右节点作为根节点进栈
n.最后root指针指向最底右节点的右节点null,且栈为空跳出循环
var inorderTraversal = function(root) {
let res = []
let stack = []
while(root!=null || stack.length!=0){//区别||是逻辑操作,|是位操作
while(root!=null){
stack.push(root);
root = root.left;
}
root = stack.pop()
res.push(root.value)
root = root.right
}
return res
};
层次遍历
root=>序列
借助栈,理通中序思路之后写这个就简单多了
var levelTraversal = function(root) {
let res = []
let queue = []
while(root||queue.length){
res.push(root);
if(root.left) queue.push(root.left);
if(root.right) queue.push(root.right);
root=queue.shift();
}
return res
};
序列=>root
利用下标的映射关系
class Node{
constructor(){
this.value=0;
this.left=null;
this.right=null;
}
}
function h(arr){
const len=arr.length;
//初始化结点
//ar i=-1;
const nodes=[];
arr.forEach(
(a,index)=>{
nodes[index]=new Node();
nodes[index].value=a;
}
);
//父i,left=i*2+1,right=2(i+1)
nodes.forEach((node,i)=>{
nodes[i].left=nodes[i*2+1];
if(2*i+2<len) nodes[i].right=nodes[2*i+2];
});
return nodes[0];
}