二叉树 是树的一种,即树中每个节点最多只能有两个子节点。
二叉树 常见考点有深度优先遍历、广度优先遍历。其中,深度优先遍历又分为前序、中序、后序遍历。
二叉树的存储方式:
1、链式存储:用指针把各个节点串联起来;
2、顺序存储:用数组把树的节点从上往下一层一层存起来(广度优先遍历);
二叉搜索树是二叉树的一种,表现为有值且有序。具体特点为:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉搜索树。
Code Part
二叉树的先中后序遍历,有递归和迭代(栈+非递归)两种方法。
递归法
二叉树先序遍历 – 递归版
const preOrder = (root) => {
let res = []
let dfs = (root) => {
if(!root) return;
res.push(root.val) //先序遍历从根节点开始
dfs(root.left) //递归左子树
dfs(root.right) //再递归右子树
}
dfs(root)
return res
}
二叉树中序遍历 – 递归版
var inOrder = (root) => {
let res = []
let dfs = (root) => {
if(!root) return;
dfs(root.left)
res.push(root.val)
dfs(root.right)
}
dfs(root)
return res
}
二叉树后序遍历 – 递归版
var postOrder = (root) => {
let res = []
let dfs = (root) => {
if(!root) return;
dfs(root.left)
dfs(root.right)
res.push(root.val)
}
dfs(root)
return res
}
二叉树先序遍历 – 非递归版
var preOrder = (root) => {
if(!root) return;
let stack = [root] //新建栈,并把根节点入栈
let res = []
while(stack.length > 0){
let n = stack.pop() //栈顶元素出栈
res.push(n.val)
n.right && stack.push(n.right) //注意!栈是后进先出,所以右节点先入栈
n.left && stack.push(n.left) //如果左节点存在,也入栈
}
return res
}
二叉树中序遍历 – 非递归版
var inOrder = (root) => {
if(!root) return;
let stack = []
let p = root
let res = []
while(stack.length || p){
while(p){
stack.push(p)
p = p.left //中序先遍历左子树
}
let n = stack.pop()
res.push(n.val) //得到根节点的值
p = n.right //再遍历右子树
}
return res
}
二叉树后序遍历 – 非递归版
var postOrder = (root) => {
if(!root) return
let stack = [root]
let outputStack = []
let res = []
while(stack.length){
let n = stack.pop()
outputStack.push(n) //多加一个栈,先按照先序存值,再反转pop出来
n.left && outputStack.push(n.left)
n.right && outputStack.push(n.right)
}
while(outputStack.length){
let n = outputStack.pop()
res.push(n.val)
}
return res
}
广度优先遍历 bfs
let res = []
const bfs = (root) => {
const q = [root]
while(q.length > 0){
const n = q.shift()
res.push(n.val)
//二叉树
// n.left && q.push(n.left)
// n.right && q.push(n.right)
//树
n.children.forEach((child) => {
q.push(child)
})
}
}
bfs(root)
层序遍历,一层一层遍历二叉树得到节点值。
//利用队列
var levelOrder = function(root) {
let queue = [root]
let res = []
if(!root) return res;
while(queue.length !== 0){
//当前层的节点数,单独拿出来,for循环会改变queue结构!!
let nodeLength = queue.length
let curLevel = [] //存放每一层的节点
for(let i = 0;i < nodeLength;i++){
let n = queue.shift()//队头出队
curLevel.push(n.val)
n.left && queue.push(n.left)
n.right && queue.push(n.right)
}
res.push(curLevel) //把每一层的结果放到数组
}
return res
};
总结下面试常考的也是围绕下面几种方式进行:
深度优先遍历进一步拓展,有了下面几种遍历方式
1、先序遍历(递归、非递归+栈)
2、中序遍历(递归、非递归+栈)
3、后序遍历(递归、非递归+栈)
广度优先遍历进一步拓展为
1、层序遍历(队列)
1万+



被折叠的 条评论
为什么被折叠?



