/**
* 节点类
*/
class TreeNode {
constructor (val) {
this.val = val
this.left = null
this.right = null
}
}
/**
* 树类
*/
class Tree {
constructor () {
this.root = null
}
/**
* 层序按顺序插入
* @param {*} val
* @returns
*/
insert (val) {
const node = new TreeNode(val)
if (!this.root) {
this.root = node
return true
}
const queue = [] // 队列
queue.push(this.root)
while (queue.length > 0) {
const curNode = queue.shift() // 出队列
if (curNode.left) { // 有左孩子,左孩子入队列,否则新节点就是左孩子
queue.push(curNode.left)
} else {
curNode.left = node
break
}
if (curNode.right) { // 有右孩子,右孩子入队列,否则新节点就是右孩子
queue.push(curNode.right)
} else {
curNode.right = node
break
}
}
}
/**
* 先序遍历-递归
* @param {*} node
*/
recrusionPreorder (node) {
console.log(node.val)
if (node.left) {
this.recrusionPreorder(node.left)
}
if (node.right) {
this.recrusionPreorder(node.right)
}
}
/**
* 中序遍历-递归
* @param {*} node
*/
recrusionMesorder (node) {
if (node.left) {
this.recrusionMesorder(node.left)
}
console.log(node.val)
if (node.right) {
this.recrusionMesorder(node.right)
}
}
/**
* 后序遍历-递归
*/
recrusionHouxu (node) {
if (node.left) {
this.recrusionHouxu(node.left)
}
if (node.right) {
this.recrusionHouxu(node.right)
}
console.log(node.val)
}
/**
* 先序-非递归
*/
xianXu () {
const stack = []
stack.push(this.root)
while (stack.length > 0) {
const node = stack.pop()
console.log(node.val)
if (node.right) {
stack.push(node.right)
}
if (node.left) {
stack.push(node.left)
}
}
}
/**
* 中序-非递归
*/
zhongXu () {
const stack = []
let tmp = this.root
while (stack.length > 0 || tmp) {
if (tmp) {
// tmp不为空就入栈
stack.push(tmp)
tmp = tmp.left
} else {
// 出栈
const node = stack.pop()
console.log(node.val)
tmp = node.right
}
}
}
/**
* 后序-非递归(将先序左右节点的入栈顺序调换,最后反转结果)
*/
houxu () {
const stack = []
stack.push(this.root)
let arr = []
while (stack.length > 0) {
const node = stack.pop()
arr.push(node.val)
if (node.left) {
stack.push(node.left)
}
if (node.right) {
stack.push(node.right)
}
}
arr = arr.reverse()
arr.forEach((item) => {
console.log(item)
})
}
/**
* 后序-非递归
*/
houxu1 () {
const stack = []
let p = this.root
let last = null
while (p || stack.length > 0) {
if (p) {
stack.push(p)
p = p.left
} else {
p = stack.pop()
if (p.right === last || !p.right) {
// 若上一个被访问节点为该节点的右孩子,表明该节点有孩子已被访问过,则访问该节点
console.log(p.val)
last = p
p = null
} else {
// 重新入栈
stack.push(p)
p = p.right
}
}
}
}
}
// 使用
const tree1 = new Tree()
tree1.insert('a')
tree1.insert('b')
tree1.insert('c')
tree1.insert('d')
tree1.insert('e')
tree1.insert('f')
tree1.insert('g')
tree1.insert('h')
tree1.insert('i')
tree1.insert('j')
tree1.insert('k')
tree1.insert('l')
tree1.insert('m')
console.log(tree1)
console.log('***递归先序:')
tree1.recrusionPreorder(tree1.root)
console.log('***递归中序:')
tree1.recrusionMesorder(tree1.root)
console.log('***递归后序:')
tree1.recrusionHouxu(tree1.root)
console.log('先序:')
tree1.xianXu()
console.log('中序:')
tree1.zhongXu()
console.log('后序:')
tree1.houxu()
console.log('后序1:')
tree1.houxu1()
二叉树基本操作之深度遍历(前序、中序、后序)-js版
于 2022-11-15 16:33:02 首次发布