Day14打卡! 时长:1.5h
今日感想:今天开启二叉树篇章!主要学习了递归法的遍历,之前学的有一点“浮于表面”,要注重学习基本逻辑,尽量把问题的根本理解透彻。
二叉树重点理论基础
二叉树主要形式:满二叉树(只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,深度为k,有2^k-1个节点的二叉树)和完全二叉树(除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点。)
优先级队列其实是一个堆,堆就是一棵完全二叉树,同时保证父子节点的顺序关系。
二叉搜索树:一个有序树,
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉排序树
平衡二叉搜索树(AVL):是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
二叉树的存储方式:链式存储(指针)或顺序存储(数组,如果父节点的数组下标是 i,那么它的左孩子就是 i * 2 + 1,右孩子就是 i * 2 + 2)。
二叉树的遍历:
- 深度优先遍历(先往深走,遇到叶子节点再往回走,前中后指中间节点的遍历顺序)
- 前序遍历(递归法,迭代法)
- 中序遍历(递归法,迭代法)
- 后序遍历(递归法,迭代法)
- 广度优先遍历(一层一层的去遍历)
- 层次遍历(迭代法)
深度优先遍历经常使用递归的方式实现,也可以借助栈使用非递归的方式。
广度优先遍历的实现一般使用队列来实现,这也是队列先进先出的特点所决定的,因为需要先进先出的结构,才能一层一层的来遍历二叉树。
二叉树的定义:
Java:
public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } }C++:
struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} };
递归遍历
递归三要素:
-
确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
-
确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
-
确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
以前序遍历为例,1.递归函数需要传入节点的数值,不需要返回值,返回类型为void。2.当前遍历节点为空,本层遍历完毕,直接return。3.前序遍历单层递归逻辑为中左右。
Leetcode144二叉树的前序遍历
题目链接:Leetcode144二叉树的前序遍历
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
preorder(root, result);
return result;
}
public void preorder(TreeNode root, List<Integer> result) {
if (root == null) {
return;
}
result.add(root.val);
preorder(root.left, result);
preorder(root.right, result);
}
}
Leetcode145二叉树的后序遍历
题目链接:Leetcode145二叉树的后序遍历
代码:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
postorder(root, res);
return res;
}
void postorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
postorder(root.left, list);
postorder(root.right, list);
list.add(root.val); // 注意这一句
}
}
Leetcode94二叉树的中序遍历
题目链接:Leetcode94二叉树的中序遍历
代码:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
inorder(root, res);
return res;
}
void inorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
inorder(root.left, list);
list.add(root.val); // 注意这一句
inorder(root.right, list);
}
}
本文主要介绍了二叉树的理论基础,包括满二叉树、完全二叉树、二叉搜索树和AVL树的概念。重点讲解了二叉树的链式存储和顺序存储方法,以及深度优先遍历(前序、中序、后序)和广度优先遍历的递归和迭代实现。还探讨了递归的三要素,并通过LeetCode题目144、145和94实践了二叉树的前序、后序和中序遍历。


2201

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



