第七节:二叉树的先序、中序、后续遍历的多种递归写法
一. 先序遍历
1. 题目分析
根节点→左子树→右子树 (先、中、后 指的是根节点的位置,然后都是先左后右)
leetcode:https://leetcode.cn/problems/binary-tree-preorder-traversal/
难度:【简单】
2. 递归的几种写法
(1). 函数内部声明递归调用的方法
(2). 函数外部声明递归调用的方法
(3). 函数自身递归调用了
TreeNode:
class TreeNode {
val: number;
left: TreeNode | null;
right: TreeNode | null;
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
this.val = val === undefined ? 0 : val;
this.left = left === undefined ? null : left;
this.right = right === undefined ? null : right;
}
}
三种递归:
/**
* 先序遍历-递归写法1
* (在内部声明递归调用的方法)
* @param root
* @returns
*/
function preorderTraversal1(root: TreeNode | null): number[] {
let result: number[] = [];
//1. 前置判断
if (!root) return [];
//2.递归的方法声明在内部,可以保证result始终是一个
function traversal(node: TreeNode | null) {
//1. 递归结束的条件
if (node === null) {
return;
}
//2. 执行业务
result.push(node.val);
//3. 递归调用1
traversal(node.left);
//4. 递归调用2
traversal(node.right);
}
//3.调用递归方法
traversal(root);
return result;
}
/**
* 先序遍历-递归写法2
* (在外部声明递归调用的方法)
* @param root
* @returns
*/
function preorderTraversal2(root: TreeNode | null): number[] {
let result: number[] = [];
//前置判断
if (!root) return [];
//调用递归方法
traversal(root, result);
return result;
}
//递归的方法声明在外部,每次都需要将result传入进去,保证是同一个result
function traversal(node: TreeNode | null, result: number[]) {
//1. 递归结束的条件
if (node === null) {
return;
}
//2. 执行业务
result.push(node.val);
//3. 递归调用1
traversal(node.left, result);
//4. 递归调用2
traversal(node.right, result);
}
/**
* 先序遍历-递归写法3
* (自身递归调用)
* @param root
* @returns
*/
function preorderTraversal3(root: TreeNode | null): number[] {
if (root === null) {
return [];
}
const left = preorderTraversal3(root.left);
const right = preorderTraversal3(root.right);
return [root.val, ...left, ...right];
}
二. 中序遍历
1. 题目分析
左子树→根节点→右子树
leetcode:https://leetcode.cn/problems/binary-tree-inorder-traversal/description/
难度:【简单】
2. 递归的几种写法
同上,下面只写了其中两种代码
2种递归:
/**
* 中序遍历--递归1
* (函数内部声明递归方法)
* @param root 根节点
* @returns 中序遍历后的数组
*/
function inorderTraversal1(root: TreeNode | null): number[] {
//1. 前置判断
if (root === null) return [];
let res: number[] = [];
//2. 声明递归方法
function traversal(node: TreeNode | null) {
//递归结束条件
if (node === null) return;
traversal(node.left);
res.push(node.val);
traversal(node.right);
}
//3. 调用递归
traversal(root);
return res;
}
/**
* 中序遍历--递归2
* (函数自身递归)
* @param root 根节点
* @returns 中序遍历后的数组
*/
function inorderTraversal2(root: TreeNode | null): number[] {
//1. 前置判断
if (root === null) return [];
//2.递归调用
let leftNums: number[] = inorderTraversal2(root.left);
let rightNums: number[] = inorderTraversal2(root.right);
return [...leftNums, root.val, ...rightNums];
}
三. 后续遍历
1. 题目分析
左子树→右子树→根节点
leetcode:https://leetcode.cn/problems/binary-tree-postorder-traversal/description/
难度:【简单】
2. 递归的几种写法
同上,下面只写了其中两种代码
2种递归:
/**
* 后序遍历--递归1
* (自身递归调用)
* @param root 根节点
* @returns 中序遍历后的数组
*/
function postorderTraversal(root: TreeNode | null): number[] {
//1. 前置判断
if (root === null) return [];
//2. 递归调用
let leftNums: number[] = postorderTraversal(root.left);
let rightNums: number[] = postorderTraversal(root.right);
return [...leftNums, ...rightNums, root.val];
}
/**
* 后序遍历--递归2
* (函数内部声明方法)
* @param root 根节点
* @returns 中序遍历后的数组
*/
function postorderTraversal2(root: TreeNode | null): number[] {
//1. 前置判断
if (root === null) return [];
let res: number[] = [];
//2. 声明递归方法
function traversal(node: TreeNode | null) {
//递归结束条件
if (node === null) return null;
traversal(node.left);
traversal(node.right);
res.push(node.val);
}
//3.调用递归方法
traversal(root);
return res;
}
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。