以下仅为学习krahets的 hello-aglo写的笔记

定义

  • 非线性数据结构
  • 表示“祖先”与“后代”的关系
  • 体现分治的思想
1
2
3
4
5
6
7
8
class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int x){
val = x;
}
}

基础概念回顾

  1. 根节点(root):位于二叉树顶层的节点,没有父节点
  2. 叶节点(leaf):没有子节点的节点,其两个指针指向 None
  3. 层(level):节点所在的层,从顶至底递增,根节点的层是 1
  4. 度(degree):节点所有的子节点数量,二叉树的度是 0、1、2
  5. 边(edge):连接两个节点的线段,即节点的指针引用
  6. 节点的深度(depth):从根节点到该节点所经历的边的数量
  7. 二叉树的高度(height):从根节点到最远叶节点所经历的边的数量
  8. 节点的高度(height):从距离该节点最远的叶节点到该节点所经历的边的数量

图片来自k神的hello-algo项目

二叉树的一般类型

  1. 完美二叉树(perfect binary tree)、满二叉树:所有层的二叉树被填满,二叉树达到完美状态,叶节点的度为 0,除叶节点外其他节点的度都为 2
  2. 完全二叉树(complete binary tree):只有最底层的节点未被完全填充,且左右填充节点都靠近左侧
  3. 完满二叉树(full binary tree):除叶节点外,每个节点都有两个节点
  4. 平衡二叉树(balanced binary tree):每一个节点的左子树和右子树高度之差的绝对值不超过 1

二叉树的退化

  1. 二叉树的最佳状态是完美二叉树,充分发挥了分治的思想。
  2. 退化的话,会出现只有一边有节点的情况,变成了链表,这时候各项操作都变成线性操作,时间复杂度变成 O(n)了

图片来自k神的hello-algo项目

二叉树的遍历

层序遍历

层序遍历

深度优先

前序遍历

根节点 → 左子树 → 右子树

1 → 2 → 4 → 5 → 3 → 6 → 7

核心算法:

1
2
3
4
5
前序遍历(node):
如果node为空,直接返回(递归终止条件)
访问node
前序遍历(node.left)
前序遍历(node.right)

中序遍历

左子树 → 根节点 → 右子树

4 → 2 → 5 → 1 → 6 → 3 → 7

核心算法:

1
2
3
4
5
中序遍历(node):
如果node为空,直接返回(递归终止条件)
中序遍历(node.left)
访问node
中序遍历(node.right)

后序遍历

左子树 → 右子树 → 根节点

4 → 5 → 2 → 6 → 7 → 3 → 1

核心算法:

1
2
3
4
5
后序遍历(node):
如果node为空,直接返回(递归终止条件)
后序遍历(node.left)
后序遍历(node.right)
访问node
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class BinaryTreeTraversal {
List<Integer> list = new ArrayList<Integer>(); // 类级变量,用于存储遍历结果

// 前序遍历
void preOrder(TreeNode root) {
if (root == null) {
return;
}
list.add(root.val);
preOrder(root.left);
preOrder(root.right);
}

// 中序遍历
void inOrder(TreeNode root) {
if (root == null) {
return;
}
inOrder(root.left);
list.add(root.val);
inOrder(root.right);
}

// 后序遍历
void postOrder(TreeNode root) {
if (root == null) {
return;
}
postOrder(root.left);
postOrder(root.right);
list.add(root.val);
}

// 层序遍历
void levelOrder(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);

while (!queue.isEmpty()) {
TreeNode poll = queue.poll();
list.add(poll.val);
if (poll.left != null) {
queue.offer(poll.left);
}
if (poll.right != null) {
queue.offer(poll.right);
}
}
}
}

二叉搜索树 Binary Search Tree

定义

满足以下两个条件的二叉树是二叉搜索树

  1. 对于根节点,左子树所有节点的值 < 根节点的值 < 右子树所有节点的值
  2. 对于任意节点的左子树和右子树,均满足条件 1

参考