以下所有代码的测试用例:
// 1
// / \
// 2 3
// / / \
// 4 5 6
// / \
// 7 8
var tree = {
value: 1,
left: {
value: 2,
left: {
value: 4
}
},
right: {
value: 3,
left: {
value: 5,
left: {
value: 7
},
right: {
value: 8
}
},
right: {
value: 6
}
}
}
中序遍历
中序遍历:左根右,所以结果应为4 2 1 7 5 8 3 6
递归法——结果推入数组:
// 1
// / \
// 2 3
// / / \
// 4 5 6
// / \
// 7 8
function inorderTraversal(root,array){
if(root){
inorderTraversal(root.left,array);
array.push(root.value);
inorderTraversal(root.right,array);
}
return array;
}
let res=[];
console.log(inorderTraversal(tree,res))//[4, 2, 1, 7, 5, 8, 3, 6]
递归法:结果单独输出
function inorderTraversal(root){
if(root){
inorderTraversal(root.left);
console.log(root.value);
inorderTraversal(root.right);
}
}
inorderTraversal(tree);//4, 2, 1, 7, 5, 8, 3, 6 单独输出而不是数组
非递归实现:
// 1
// / \
// 2 3
// / / \
// 4 5 6
// / \
// 7 8
//取跟节点为目标节点,开始遍历
//1.左孩子入栈 -> 直至左孩子为空的节点
// 2.节点出栈 -> 访问该节点
// 3.以右孩子为目标节点,再依次执行1、2、3
//中序遍历:左根右,所以结果应为4 2 1 7 5 8 3 6
function inorderTraversal(root){
const result=[];
const stack=[];
let current=root;
while(current||stack.length>0){
while(current){//1.左孩子入栈 -> 直至左孩子为空的节点
stack.push(current);
current=current.left;
}
current=stack.pop();// 2.节点出栈
result.push(current.value);//-> 访问该节点
current=current.right;// 3.以右孩子为目标节点,再依次执行1、2、3
}
return result;
}
console.log(inorderTraversal(tree));//[4, 2, 1, 7, 5, 8, 3, 6]
前序遍历
前序遍历:根左右,所以结果应为1 2 4 3 5 7 8 6
递归法:
// 1
// / \
// 2 3
// / / \
// 4 5 6
// / \
// 7 8
function preorderTraversal(root,array){
if(root){
array.push(root.value);
preorderTraversal(root.left,array);
preorderTraversal(root.right,array);
}
return array;
}
let res=[];
console.log(preorderTraversal(tree,res));//[1, 2, 4, 3, 5, 7, 8, 6]
非递归实现:
// 1
// / \
// 2 3
// / / \
// 4 5 6
// / \
// 7 8
// 取根节点为目标节点,开始遍历
// 1.访问目标节点
// 2.左孩子入栈 -> 直至左孩子为空的节点
// 3.节点出栈,以右孩子为目标节点,再依次执行1、2、3
function preorderTraversal(root) {
const result=[];
const stack=[];
let current=root;
while(current||stack.length>0){
while(current){
result.push(current.value);// 1.访问目标节点
stack.push(current);
current=current.left;//2.左孩子入栈 -> 直至左孩子为空的节点
}
current=stack.pop();// 3.节点出栈
current=current.right;
}
return result;
}
console.log(preorderTraversal(tree));//[1, 2, 4, 3, 5, 7, 8, 6]
后序遍历
后序遍历:左右根,所以结果应为4 2 7 8 5 6 3 1
递归法:
// 1
// / \
// 2 3
// / / \
// 4 5 6
// / \
// 7 8
function postorderTraversal(root,array){
if(root){
postorderTraversal(root.left,array);
postorderTraversal(root.right,array);
array.push(root.value);
}
return array;
}
let res=[];
console.log(postorderTraversal(tree,res));//[4, 2, 7, 8, 5, 6, 3, 1]
非递归实现:
// 1
// / \
// 2 3
// / / \
// 4 5 6
// / \
// 7 8
//取根节点为目标节点,开始遍历
// 1.左孩子入栈 -> 直至左孩子为空的节点
// 2.栈顶节点的右节点为空或右节点被访问过 -> 节点出栈并访问他,将节点标记为已访问
// 3.栈顶节点的右节点不为空且未被访问,以右孩子为目标节点,再依次执行1、2、3
function postorderTraversal(root){
const result=[];
const stack=[];
let last=null;//标记上一个访问的节点
let current=root;
while(current||stack.length>0){
while(current){// 1.左孩子入栈 -> 直至左孩子为空的节点
stack.push(current);
current=current.left;
}
current=stack[stack.length-1];
// 2.栈顶节点的右节点为空或右节点被访问过 -> 节点出栈并访问他,将节点标记为已访问
if(!current.right||current.right==last){
current=stack.pop();// 节点出栈
result.push(current.value);//并访问他
last=current;
current=null;//继续弹栈
}else{// 3.栈顶节点的右节点不为空且未被访问,以右孩子为目标节点,再依次执行1、2、3
current=current.right;
}
}
return result;
}
console.log(postorderTraversal(tree));//[4, 2, 7, 8, 5, 6, 3, 1]