今天是十五周算法训练营的第四周,主要讲二叉树遍历专题,包含:前序遍历、中序遍历、后续遍历、DFS、BFS。(欢迎加入十五周算法训练营,与小伙伴一起卷算法)
前序遍历
/**
* 二叉树先序遍历
*
* 遍历顺序:根——左——右
*
* 前序位置的代码在刚刚进入一个二叉树节点的时候执行
* 后续位置的代码在将要离开一个二叉树节点的时候执行
* 中序位置的代码在一个二叉树节点左子树都遍历完,即将开始遍历右子树的时候执行
* 这篇文章对前序位置、中序位置、后续位置的解释好好理解https://mp.weixin.qq.com/s?__biz=MzAxODQxMDM0Mw==&mid=2247496551&idx=1&sn=c6859fe37229a39e240a3b9323106bb4&scene=21#wechat_redirect
*/
function preOrderTraverse(head) {
if (head == null) {
return;
}
console.log(head.val);
preOrderTraverse(head.left);
preOrderTraverse(head.right);
}
// 对于先序遍历的非递归版,准备一个栈,然后将头压入栈中,循环弹出一个值,有右孩子的先压右孩子,再压左孩子
function preOrderTraverseUnRecur(head) {
if (head == null) {
return;
}
const stack = [];
stack.push(head);
while (stack.length > 0) {
head = stack.pop();
console.log(head.val);
if (head.right != null) {
stack.push(head.right);
}
if (head.left != null) {
stack.push(head.left);
}
}
}
const binaryTree = {
val: 10,
left: {
val: 8,
right: {
val: 9
}
},
right: {
val: 15
}
};
preOrderTraverse(binaryTree);
preOrderTraverseUnRecur(binaryTree);
中序遍历
/**
* 中续遍历
*
* 遍历顺序:左——根——右
*/
function inOrderTraverse(head) {
if (head == null) {
return;
}
inOrderTraverse(head.left);
console.log(head.val);
inOrderTraverse(head.right);
}
/**
* 非递归版本实现
* 准备一个栈
* 先将左节点全压入栈中
* 当前节点为空,则从栈中拿一个打印,当前节点往右跑
*/
function inOrderTraverseUnRecur(head) {
if (head == null) {
return;
}
const stack = [];
while (stack.length > 0 || head != null) {
if (head != null) {
stack.push(head);
head = head.left;
} else {
head = stack.pop();
console.log(head.val);
head = head.right;
}
}
}
const binaryTree = {
val: 10,
left: {
val: 8,
right: {
val: 9
}
},
right: {
val: 15
}
};
inOrderTraverse(binaryTree);
inOrderTraverseUnRecur(binaryTree);
后续遍历
/**
* 后续遍历
*
* 遍历顺序:左——右——根
*/
function posOrderTraverse(head) {
if (head == null) {
return;
}
posOrderTraverse(head.left);
posOrderTraverse(head.right);
console.log(head.val);
}
// 对于后续遍历的非递归版,后续左-右-根,但我们可以根据根-右-左,然后将其存入一个栈中,弹出就是左-右-根
function posOrderTraverseUnRecur(head) {
if (head == null) {
return;
}
const stack = [];
const stack1 = [];
stack.push(head);
while (stack.length > 0) {
head = stack.pop();
stack1.push(head.val);
if (head.left != null) {
stack.push(head.left);
}
if (head.right != null) {
stack.push(head.right);
}
}
while (stack1.length > 0) {
console.log(stack1.pop());
}
}
const binaryTree = {
val: 10,
left: {
val: 8,
right: {
val: 9
}
},
right: {
val: 15
}
};
posOrderTraverse(binaryTree);
posOrderTraverseUnRecur(binaryTree);
DFS
function DFS1(head) {
if (head == null) {
return;
}
console.log(head.val);
DFS1(head.left);
DFS1(head.right);
}
// 对于二叉树的深度优先就是二叉树的先序遍历,用一个栈实现
function DFS2(head) {
if (head == null) {
return;
}
const stack = [head];
while (stack.length > 0) {
head = stack.pop();
console.log(head.val);
if (head.right != null) {
stack.push(head.right);
}
if (head.left != null) {
stack.push(head.left);
}
}
}
const binaryTree = {
val: 10,
left: {
val: 8,
right: {
val: 9
}
},
right: {
val: 15
}
};
DFS1(binaryTree);
DFS2(binaryTree);
BFS
function BFS(head) {
if (head == null) {
return;
}
const list = [head];
while (list.length > 0) {
head = list.shift();
console.log(head.val);
if (head.left != null) {
list.push(head.left);
}
if (head.right != null) {
list.push(head.right);
}
}
}
const binaryTree = {
val: 10,
left: {
val: 8,
right: {
val: 9
}
},
right: {
val: 15
}
};
BFS(binaryTree);