理论
文章链接
手写二叉树
class TreeNode{
public val:number
public left:TreeNode|null
public right:TreeNode|null
constructor(val?:number,left?:TreeNode,right?:TreeNode){
this.val=(val===undefined)?0:val
this.left=(left===undefined)?null:left
this.right=(right===undefined)?null:right
}
}
二叉树的递归写法
文章链接
写递归函数的步骤
- 确定递归函数的参数和返回值
- 确定终止条件
- 确定单层递归的逻辑
二叉树的前中后遍历
前序遍历
function preorderTraversal(root: TreeNode | null): number[] {
let res:number[]=[]
const foo:(root:TreeNode|null)=>void=(root: TreeNode | null)=>{
//终止条件
if(root==null) return
//中
res.push(root.val)
//左
foo(root.left)
//右
foo(root.right)
}
foo(root)
return res
};
后序遍历
function postorderTraversal(root: TreeNode | null): number[] {
let res:number[]=[]
const foo:(root: TreeNode | null)=>void=(root: TreeNode | null)=>{
//终止条件
if(root==null) return
//左
foo(root.left)
//右
foo(root.right)
//中
res.push(root.val)
}
foo(root)
return res
};
中序遍历
function inorderTraversal(root: TreeNode | null): number[] {
let res:number[]=[]
const foo:(root: TreeNode | null)=>void=function(root: TreeNode | null){
//终止条件
if(root==null) return
//左
foo(root.left)
//中
res.push(root.val)
//右
foo(root.right)
}
foo(root)
return res
};
二叉树的迭代法
文章链接
迭代写法
前序遍历
看完文章后前序遍历比较简单,因为处理顺序和压入栈的顺序一致,前序遍历是中左右,但是利用单调栈的话,要变成中右左,因为栈是后进先出的。代码如下:
function preorderTraversal(root: TreeNode | null): number[] {
if(!root) return []
let res:number[]=[]
let stack:TreeNode[]=[]
stack.push(root)
while(stack.length!=0){
let node:TreeNode=stack.pop()!
res.push(node.val)//中
if(node.right) stack.push(node.right);//右
if(node.left) stack.push(node.left);//左
}
return res
};
后序遍历
后序遍历与前序遍历类似,后序是左右中,所以可以把前序遍历的代码变一下,例如代码随想录中的这张图:
代码如下:
function postorderTraversal(root: TreeNode | null): number[] {
if(!root) return []
let res:number[]=[]
let stack:TreeNode[]=[]
stack.push(root)
while(stack.length!=0){
let node:TreeNode=stack.pop()!
res.push(node.val)//中
//把中右左的遍历顺序变为中左右 (栈是后进先出的)
if(node.left) stack.push(node.left);//左
if(node.right) stack.push(node.right);//右
}
return res.reverse()
};
中序遍历
中序遍历比较复杂,因为处理节点的顺序和入栈的顺序不一致,所以需要利用指针来完成中序遍历,代码如下:
function inorderTraversal(root: TreeNode | null): number[] {
if(!root) return []
let res:number[]=[]
let stack:TreeNode[]=[]
let curr:TreeNode=root
stack.push(root)
while(stack.length>0||curr){
if(curr!=null){//左
if(curr.left) stack.push(curr.left);
curr=curr.left!
}else{
let node:TreeNode=stack.pop()!
res.push(node.val)//中
curr=node.right! //右
if(curr) stack.push(curr)
}
}
return res
};
二叉树的统一迭代法
文章链接
统一的迭代法其实就是用了null作为标记,null的前一个就是要输出的节点
中序遍历
function inorderTraversal(root: TreeNode | null): number[] {
let res:number[]=[]
let stack:(TreeNode|null)[]=[]
if(root!=null)stack.push(root)
while(stack.length>0){
let node:TreeNode|null=stack.pop() as (TreeNode|null)
if(node!=null){
if(node.right) stack.push(node.right) //右
stack.push(node) //中
stack.push(null) //标记
if(node.left) stack.push(node.left)//左
}else{
node=stack.pop()!
res.push(node.val)
}
}
return res
};
前序遍历
function preorderTraversal(root: TreeNode | null): number[] {
let res:number[]=[]
let stack:(TreeNode|null)[]=[]
if(root!=null)stack.push(root)
while(stack.length>0){
let node:TreeNode|null=stack.pop() as (TreeNode|null)
if(node!=null){
if(node.right) stack.push(node.right) //右
if(node.left) stack.push(node.left)//左
stack.push(node) //中
stack.push(null) //标记
}else{
node=stack.pop()!
res.push(node.val)
}
}
return res
};
后序遍历
function postorderTraversal(root: TreeNode | null): number[] {
let res:number[]=[]
let stack:(TreeNode|null)[]=[]
if(root!=null)stack.push(root)
while(stack.length>0){
let node:TreeNode|null=stack.pop() as (TreeNode|null)
if(node!=null){
stack.push(node) //中
stack.push(null) //标记
if(node.right) stack.push(node.right) //右
if(node.left) stack.push(node.left)//左
}else{
node=stack.pop()!
res.push(node.val)
}
}
return res
};
今日总结
今日主要以理论为主,主要是熟悉二叉树中的迭代法和递归法,其中统一的迭代法得多加练习和查看,今日耗时2.5小时