Просмотр исходного кода

docs: 更新20260731课堂笔记及README,同步代码变更——新增二叉树(BST/AVL/红黑树)知识点(Demo06)及随堂练习参考解答

WanJL 3 недель назад
Родитель
Сommit
c9d3d82f94

+ 2 - 2
README.md

@@ -36,7 +36,7 @@
 | 2026-07-28 | [Java 异常处理:异常概念、Throwable 体系结构、编译期/运行时异常、JVM 默认处理、try-catch 多 catch 块、异常常用方法、finally 资源关闭、throws 抛出、鲁棒性;自定义异常、throw/throws;Object 类:equals/hashCode/toString 重写、Objects 工具类;课后作业回顾 — String 分割去重/统计、LocalDate 天数差计算](./课堂笔记/01-JavaSE基础-笔记/20260728-笔记.md) |
 | 2026-07-29 | [包装类(Wrapper Classes)+ 集合框架入门(Collection Framework)+ 泛型(Generics):基本类型与包装类对应关系、装箱与拆箱、自动装箱/拆箱、包装类优势、缓存机制、Bean 类应用;集合 vs 数组、体系结构(Collection/List/Set/Map)、线性表数据结构(栈/队列/数组/链表)、ArrayList 底层实现详解(默认容量10、扩容机制、三个构造方法、size vs capacity、trimToSize/ensureCapacity/grow 1.5倍扩容公式、位运算符 >> <<)、ArrayList 常用方法速查;泛型概念与好处、泛型定义格式、通配符 ? / ? extends T、自定义泛型类、有界类型参数、练习参考答案(Student toString/equals/hashCode、泛型 vs 原始类型)](./课堂笔记/01-JavaSE基础-笔记/20260729-笔记.md) |
 | 2026-07-30 | [List.of / LinkedList / 自定义链表 / ArrayList 练习](./课堂笔记/01-JavaSE基础-笔记/20260730-笔记.md) |
-| 2026-07-31 | [LinkedList 多接口形态(List/Queue/Deque)+ Iterator 迭代器 + Map集合(入门/遍历/底层原理)](./课堂笔记/01-JavaSE基础-笔记/20260731-笔记.md) |
+| 2026-07-31 | [LinkedList 多接口形态(List/Queue/Deque)+ Iterator 迭代器 + Map集合(入门/遍历/底层原理)+ 二叉树(二叉搜索树/平衡二叉树/红黑树)](./课堂笔记/01-JavaSE基础-笔记/20260731-笔记.md) |
 
 ## 二、授课代码
 
@@ -59,7 +59,7 @@
 | 2026-07-28 | 异常处理(Demo01~Demo04 + Person+AgeOutOfBoundsException) + Object类(Demo01+Person 重写equals/hashCode/toString) + 课后作业回顾(String工具 + 日期数学) + Exercises | `c260728` | [`course/api`](./授课代码/c260728/src/course/api/) / [`course/exception`](./授课代码/c260728/src/course/exception/) / [`homework260727`](./授课代码/c260728/src/homework260727/) / [`exercise/exercise01`](./授课代码/c260728/src/exercise/exercise01/) / [`exercise/exercise07`](./授课代码/c260728/src/exercise/exercise07/) |
 | 2026-07-29 | 包装类 + 集合框架入门 + 泛型(Generics):装箱/拆箱、自动装箱/拆箱、包装类在 Bean 中的应用;集合 vs 数组、体系结构、线性表数据结构、ArrayList 底层实现详解(默认容量10、扩容机制、三个构造方法、size vs capacity、trimToSize/ensureCapacity/grow 1.5倍扩容公式、位移运算符)、ArrayList 常用方法速查;泛型概念与好处、定义格式、通配符、自定义泛型类、有界类型参数、练习参考答案(Student 类重写 toString/equals/hashCode、泛型 vs 原始类型) | `c260729` | [`course/packaging`](./授课代码/c260729/src/course/packaging/) / [`course/collection`](./授课代码/c260729/src/course/collection/) / [`exercises/exercise01`](./授课代码/c260729/src/exericse/exericse01/) / [`exercises/exercise02`](./授课代码/c260729/src/exericse/exericse02/) |
 | 2026-07-30 | List.of() 不可变集合 + LinkedList 双链表理论 + 手写单链表 MyLinked + Student 课程管理练习 (ArrayList 常用操作) + 课后作业回顾手写 MyArrayList | `c260730` | [`course`](./授课代码/c260730/src/course/) / [`exericse/exericse01`](./授课代码/c260730/src/exericse/exericse01/) / [`homework0729/p4`](./授课代码/c260730/src/homework0729/p4/) |
-| 2026-07-31 | LinkedList 多接口形态(List / Queue / Deque)+ Iterator 迭代器遍历(ArrayList/LinkedList 迭代器)+ Map集合:入门(HashMap:put/keySet/values/containsKey)、遍历(keySet+get / entrySet)、HashMap底层原理(数组+链表/红黑树、hashCode/equals、5个关键常量) | `c260731` | [`course`](./授课代码/c260731/src/course/) |
+| 2026-07-31 | LinkedList 多接口形态(List / Queue / Deque)+ Iterator 迭代器遍历(ArrayList/LinkedList 迭代器)+ Map集合:入门(HashMap:put/keySet/values/containsKey)、遍历(keySet+get / entrySet)、HashMap底层原理(数组+链表/红黑树、hashCode/equals、5个关键常量)+ 二叉树(二叉搜索树/平衡二叉树AVL/红黑树规则与旋转)+ 随堂练习参考解答(自定义Key/词频统计) | `c260731` | [`course`](./授课代码/c260731/src/course/) / [`exericse/exericse01`](./授课代码/c260731/src/exericse/exericse01/) / [`exericse/exericse02`](./授课代码/c260731/src/exericse/exericse02/) |
 
 ## 三、课堂练习题
 

+ 97 - 0
授课代码/c260731/src/course/Demo06.java

@@ -0,0 +1,97 @@
+package course;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title Demo06
+ * @description 二叉树
+ * @create 2026/7/31
+ */
+public class Demo06 {
+    /*
+
+        二叉树 是一种特殊的树形结构
+        在二叉树中,任意一个节点的度小于等于2
+        节点:在树结构中,每一个元素称为节点
+        度:每一个节点的子节点数量称为度
+
+        二叉搜索树(二叉查找树、二叉排序树)是一种特殊的二叉树
+        每一个节点最多有两个子节点
+        左子树上的所有节点都是小于根节点的值
+        右子树上的所有节点都是大于根节点的值
+
+        二叉搜索树的添加节点的规则:
+            比根节点小的,存左边
+            比根节点大的,存右边
+            一样的不存
+            7   4   10  5   6
+
+                        7
+                   4        10
+                       5
+                          6
+
+        平衡二叉树 AVL   --平衡二叉树也是一种特殊的二叉搜索树
+            二叉树左右的子节点的高度差不超过1
+            【任意节点的左右两个子树的都是一棵平衡二叉树】
+            【为了保证高度差不超过1】
+            触发旋转的时机:
+                当添加一个子节点后,这个树不再是平衡二叉树了。
+            旋转的方式:左旋 和 右旋
+                7                                       7
+             4      10              左旋->            4     11
+                        11                                10  12
+                            12
+            左旋 就是把根节点的右侧往左拉,原先的右子节点变为新的根节点,并且把多余的左子节点让出来,给已经降级的根节点当右子节点。
+            右旋
+                7                                       7
+             4      10              右旋->           2     10
+          2                                     1     4
+        1
+
+          右旋:将根节点的左侧往右拉,左子节点变为新的父节点,并且把多余的右子节点让出来,给已经降级的父节点当左子节点。
+
+          平衡二叉树的旋转的四种情况:
+
+          左左:
+            当根节点左子树的左子树有节点插入,导致的二叉树不平衡
+            怎么旋转?直接对整体进行右旋就可以。
+          左右:
+            根节点左子树的右子树有节点插入,导致的二叉树不平衡
+            先在左子树对应的节点位置进行左旋,再对整体进行右旋
+          右右:
+            当根节点右子树的右子树有节点插入,导致的二叉树不平衡
+            怎么旋转?直接对整体进行左旋就可以。
+          右左:
+            当根节点右子树的左子树有节点插入,导致的二叉树不平衡
+            先在右子树对应的节点位置进行右旋,再对整体进行左旋
+
+          红黑树---一种特殊的平衡二叉树
+            红黑树也是一种平衡二叉树
+            每一个节点要么是红色的,要么是黑色的。
+            红黑树不是高度平衡,它的平衡是通过自己的“红黑规则”来实现的。
+          红黑树的红黑规则:
+            1、每一个节点要么是红色的,要么是黑色的。
+            2、根节点必须是黑色的。
+            3、如果一个节点没有子节点或者没有父节点,那么该节点响应的指针属性值就是Nil,这些Nil视为叶子节点,
+            每个也自己节点都是黑色的。
+            4、如果某一个节点是红色的,那么它的子节点必须是黑色的。并且不能出现两个红色节点相连的情况。
+            5、对于每一个节点,从该节点到它所有的后代叶子节点的【简单路径上】,都包含相同数量的黑色节点。
+            6、当向红黑树插入子节点的时候,默认节点是红色的,除非不满足红黑规则。效率更高。
+
+        当红黑树添加节点的时候,如何保持红黑规则?
+            1、根节点位置,直接变为黑色。
+            2、非根节点位置,父节点为黑色,那么新节点就默认红色。
+            3、非根节点位置,如果父节点为红色,那么要判断:
+                |-叔叔节点如果是红色
+                    1、将父节点设置为黑色,将叔叔节点设置为黑色
+                    2、将祖父节点设置为红色
+                    3、如果祖父节点是根节点,那么则根节点再次变为黑色。
+                |-叔叔节点如果是黑色
+                    1、将父节点设置为黑色
+                    2、将祖父节点设置为红色
+                    3、以祖父节点为支点进行旋转
+          Java集合中完全使用红黑树实现的,是TreeMap
+
+     */
+}

+ 55 - 0
授课代码/c260731/src/exericse/exericse01/Student.java

@@ -0,0 +1,55 @@
+package exericse.exericse01;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+public class Student {
+    private String id;    // 学号
+    private String name;  // 姓名
+
+    public Student(String id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+
+    // TODO: 补全 getter / setter 方法
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    // TODO: 重写 hashCode()
+    //   规则:属性值完全相同时,必须返回相同的哈希值
+    //   提示:return Objects.hash(id, name);
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, name);
+    }
+
+    // TODO: 重写 equals(Object o)
+    //   规则:id 和 name 都相同时返回 true
+    //   提示:使用 Objects.equals(id, student.id) 判断
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || getClass() != o.getClass()) return false;
+        Student student = (Student) o;
+        return Objects.equals(id, student.id) && Objects.equals(name, student.name);
+    }
+
+    @Override
+    public String toString() {
+        return "Student{id='" + id + "', name='" + name + "'}";
+    }
+}

+ 39 - 0
授课代码/c260731/src/exericse/exericse01/StudentKeyTest.java

@@ -0,0 +1,39 @@
+package exericse.exericse01;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title StudentKeyTest
+ * @description
+ * @create 2026/7/31
+ */
+public class StudentKeyTest {
+    public static void main(String[] args) {
+        Map<Student, String> map = new HashMap<>();
+
+        // 1. 创建两个属性完全相同的 Student 对象
+        Student s1 = new Student("x001", "张三");
+        Student s2 = new Student("x001", "张三");
+
+        // 2. 判断 s1 和 s2 是否相等(不重写 equals 时是 false)
+        System.out.println("s1.equals(s2):" + s1.equals(s2));  // 期望 true
+
+        // 3. 判断 s1 和 s2 的哈希值是否相同
+        System.out.println("s1.hashCode():" + s1.hashCode());
+        System.out.println("s2.hashCode():" + s2.hashCode());  // 期望相同
+
+        // 4. 分别用 s1、s2 作为 Key 存入
+        map.put(s1, "学员A");
+        map.put(s2, "学员B");
+
+        // 5. 思考:如果不重写 hashCode/equals,size 是几?重写后 size 是几?
+        System.out.println("map 大小:" + map.size());  // 期望 1(s1、s2 视为同一个键)
+
+        // 6. 用 get 取出:new 一个属性相同的对象 s3 去查找
+        Student s3 = new Student("x001", "张三");
+        System.out.println("用 s3 查找:" + map.get(s3));  // 期望 "学员B"
+    }
+}

+ 74 - 0
授课代码/c260731/src/exericse/exericse02/WordCountDemo.java

@@ -0,0 +1,74 @@
+package exericse.exericse02;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+/**
+ * @author WanJl
+ * @version 1.0
+ * @title WordCountDemo
+ * @description
+ * @create 2026/7/31
+ */
+public class WordCountDemo {
+    public static void main(String[] args) {
+        // 1. 定义一个字符串数组,模拟一段文本中的单词(含重复)
+        //    "apple", "banana", "apple", "orange", "banana", "apple", "grape"
+        String[] words={"apple", "banana", "apple", "orange", "banana", "apple", "grape"};
+        // 2. 创建一个 HashMap<String, Integer>,单词 → 出现次数
+        HashMap<String, Integer> map=new HashMap<>();
+        // 3. 遍历单词数组,统计每个单词出现的次数
+        //    核心逻辑:
+            for (String word : words) {
+                if (map.containsKey(word)) {
+                    map.put(word, map.get(word) + 1);   // 已出现过,次数 +1
+                } else {
+                    map.put(word, 1);                    // 第一次出现
+                }
+            }
+
+
+
+        // 4. 使用 entrySet() 遍历输出统计结果
+        //    输出格式:"单词:apple,出现次数:3"
+        Set<Map.Entry<String, Integer>> entries = map.entrySet();
+        for (Map.Entry<String, Integer> me:entries){
+            String word = me.getKey();
+            Integer count = me.getValue();
+            System.out.println("单词:"+word+",出现次数:"+count);
+        }
+        // 5. 进阶:找出出现次数最多的单词
+        //    提示:遍历 entrySet,用变量记录 maxCount 和对应单词
+        Integer maxCount= 0;
+        Map.Entry<String, Integer> MaxMe=null;
+        for (Map.Entry<String, Integer> me:entries){
+            if (me.getValue()>maxCount){
+                MaxMe=me;
+                maxCount=me.getValue();
+            }
+        }
+        System.out.println("单词:"+MaxMe.getKey()+",出现次数:"+MaxMe.getValue());
+
+        System.out.println("--------------------------");
+        // 6. 拓展:使用 Scanner 从键盘输入一句话(用空格分隔),统计每个单词的出现次数
+        //    提示:String[] inputWords = scanner.nextLine().split(" ");
+        Scanner sc=new Scanner(System.in);
+        String[] inputWords = sc.nextLine().split(" ");
+
+        HashMap<String, Integer> map1=new HashMap<>();
+
+        for (String word : inputWords) {
+            if (map1.containsKey(word)) {
+                map1.put(word, map1.get(word) + 1);   // 已出现过,次数 +1
+            } else {
+                map1.put(word, 1);                    // 第一次出现
+            }
+        }
+        Set<Map.Entry<String, Integer>> entries02 = map1.entrySet();
+        for (Map.Entry<String, Integer> me:entries02){
+            String word = me.getKey();
+            Integer count = me.getValue();
+            System.out.println("单词:"+word+",出现次数:"+count);
+        }
+    }
+}

+ 122 - 5
课堂笔记/01-JavaSE基础-笔记/20260731-笔记.md

@@ -1,4 +1,4 @@
-# 20260731 课堂笔记 — LinkedList 多接口形态 / Iterator 迭代器 / Map集合(入门·遍历·底层原理)
+# 20260731 课堂笔记 — LinkedList 多接口形态 / Iterator 迭代器 / Map集合(入门·遍历·底层原理)/ 二叉树(BST·AVL·红黑树)
 
 - **日期**:2026-07-31
 - **项目**:`c260731`
@@ -15,8 +15,9 @@
 4. [Map 集合(双列集合)与 HashMap 入门](#4-map-集合双列集合与-hashmap-入门)
 5. [Map 集合的遍历(keySet + get / entrySet)](#5-map-集合的遍历keyset--get--entryset)
 6. [HashMap 底层原理(哈希表结构)](#6-hashmap-底层原理哈希表结构)
-7. [随堂练习要点](#7-随堂练习要点)
-8. [拓展阅读](#8-拓展阅读)
+7. [二叉树(二叉搜索树 / 平衡二叉树 / 红黑树)](#7-二叉树二叉搜索树--平衡二叉树--红黑树)
+8. [随堂练习要点](#8-随堂练习要点)
+9. [拓展阅读](#9-拓展阅读)
 
 ---
 
@@ -467,7 +468,96 @@ public class Demo05 {
 
 ---
 
-## 7. 随堂练习要点
+## 7. 二叉树(二叉搜索树 / 平衡二叉树 / 红黑树)
+
+### 概念
+
+**二叉树**是一种特殊的树形结构,在二叉树中,**任意一个节点的度小于等于 2**。
+
+- **节点**:在树结构中,每一个元素称为节点
+- **度**:每一个节点的子节点数量称为度
+
+二叉树是集合底层结构(如 HashMap 的红黑树)的基础,演进路线为:**二叉树 → 二叉搜索树 → 平衡二叉树(AVL)→ 红黑树**。
+
+### 二叉搜索树(Binary Search Tree)
+
+二叉搜索树(二叉查找树、二叉排序树)是一种特殊的二叉树:
+
+- 每一个节点最多有两个子节点
+- **左子树**上的所有节点都**小于**根节点的值
+- **右子树**上的所有节点都**大于**根节点的值
+
+**添加节点的规则**:
+- 比根节点小的,存左边
+- 比根节点大的,存右边
+- 一样的不存
+
+示例:依次添加 `7  4  10  5  6`
+
+```
+        7
+    4     10
+       5
+          6
+```
+
+### 平衡二叉树(AVL)
+
+平衡二叉树也是一种特殊的二叉搜索树:
+
+- 二叉树**左右的子节点的高度差不超过 1**
+- 任意节点的左右两个子树都是一棵平衡二叉树(递归定义)
+- **触发旋转的时机**:当添加一个子节点后,这棵树不再是平衡二叉树了
+- 旋转方式:**左旋** 和 **右旋**
+
+**左旋**:把根节点的右侧往左拉,原先的右子节点变为新的根节点,并且把多余的左子节点让出来,给已经降级的根节点当右子节点。
+
+```
+     7                                      7
+  4     10             左旋 ->           4     11
+           11                                10  12
+             12
+```
+
+**右旋**:将根节点的左侧往右拉,左子节点变为新的父节点,并且把多余的右子节点让出来,给已经降级的父节点当左子节点。
+
+**平衡二叉树的四种旋转情况**:
+
+| 情况 | 不平衡原因(插入位置) | 旋转方式 |
+|------|------------------------|----------|
+| **左左(LL)** | 根节点左子树的左子树插入节点 | 直接对整体进行**右旋** |
+| **左右(LR)** | 根节点左子树的右子树插入节点 | 先在左子树对应节点位置**左旋**,再对整体**右旋** |
+| **右右(RR)** | 根节点右子树的右子树插入节点 | 直接对整体进行**左旋** |
+| **右左(RL)** | 根节点右子树的左子树插入节点 | 先在右子树对应节点位置**右旋**,再对整体**左旋** |
+
+### 红黑树(Red-Black Tree)
+
+红黑树是一种特殊的平衡二叉树。它不是**高度平衡**的,它的平衡是通过自己的**红黑规则**来实现的。
+
+**红黑规则**:
+1. 每一个节点要么是红色的,要么是黑色的
+2. **根节点必须是黑色的**
+3. 如果一个节点没有子节点或没有父节点,那么该节点相应的指针属性值就是 `Nil`,这些 Nil 视为**叶子节点**,每个叶子节点都是黑色的
+4. 如果某一个节点是红色的,那么它的子节点必须是黑色的——**不能出现两个红色节点相连**的情况
+5. 对于每一个节点,从该节点到它所有后代叶子节点的**简单路径**上,都包含**相同数量的黑色节点**
+6. 当向红黑树插入子节点的时候,默认节点是**红色**的(除非不满足红黑规则),效率更高
+
+**添加节点时如何保持红黑规则**:
+1. **根节点位置**:直接变为黑色
+2. **非根节点位置,父节点为黑色**:新节点默认红色,无需调整
+3. **非根节点位置,父节点为红色**,需要判断:
+   - **叔叔节点是红色**:① 将父节点设置为黑色 ② 将叔叔节点设置为黑色 ③ 将祖父节点设置为红色 ④ 如果祖父节点是根节点,根节点再次变为黑色
+   - **叔叔节点是黑色**:① 将父节点设置为黑色 ② 将祖父节点设置为红色 ③ 以祖父节点为支点进行旋转
+
+**与集合框架的联系**:Java 集合中**完全使用红黑树实现的,是 `TreeMap`**。
+
+### 与 HashMap 的联系
+
+在上一节(HashMap 底层原理)我们了解到:JDK 1.8 之后的 HashMap 在链表长度 > 8 且数组长度 > 64 时,会把链表**树化**为红黑树。本节深入讲解了红黑树的理论基础——它由 二叉树 → 二叉搜索树 → 平衡二叉树(AVL)→ 红黑树 一步步演进而来。
+
+---
+
+## 8. 随堂练习要点
 
 ### 练习一:LinkedList 多接口引用
 
@@ -531,9 +621,31 @@ public class Demo05 {
 2. 为什么 JDK1.8 要引入红黑树?—— 防止哈希冲突导致链表过长、查询退化为 O(n),红黑树保证 O(log n) 的查询效率
 3. 负载因子 0.75 的含义?—— 当已存元素个数超过容量 × 0.75 时触发扩容(默认 16 → 扩容后约 32)
 
+### 练习六:二叉树理论理解(二叉搜索树 / 红黑树)
+
+**核心步骤**:
+1. 阅读 Demo06 的注释,画出二叉搜索树的构建过程(`7 4 10 5 6`)
+2. 手写一段数字序列,演示二叉搜索树的添加规则(小左大右、相同不存)
+3. 说出 AVL 平衡二叉树的四种旋转情况(LL/LR/RR/RL)分别如何旋转
+4. 记住红黑树的 6 条红黑规则,说明 HashMap 树化的原因
+
+**思考**:
+1. 二叉搜索树和普通二叉树的区别?—— 二叉搜索树多了「左小右大」的排序约束,查找效率可达 O(log n)
+2. 为什么要引入 AVL / 红黑树?—— 防止二叉搜索树退化成链表(如按顺序插入 1~10),保证树的高度平衡、性能稳定
+3. 红黑树相比 AVL 的优势?—— 红黑树不是高度平衡,插入/删除的旋转次数更少,综合性能更优;TreeMap 完全用红黑树实现
+
+### 随堂练习参考解答(已提供代码)
+
+对应课堂练习题的参考解答已写入授课代码:
+
+| 练习 | 参考代码路径 |
+|------|-------------|
+| 进阶 1:自定义类作为 HashMap 的 Key | [`exericse/exericse01/Student.java`](./../授课代码/c260731/src/exericse/exericse01/Student.java) + [`StudentKeyTest.java`](./../授课代码/c260731/src/exericse/exericse01/StudentKeyTest.java) |
+| 进阶 2:单词词频统计器 | [`exericse/exericse02/WordCountDemo.java`](./../授课代码/c260731/src/exericse/exericse02/WordCountDemo.java) |
+
 ---
 
-## 8. 拓展阅读
+## 9. 拓展阅读
 
 ### 官方文档
 
@@ -544,15 +656,19 @@ public class Demo05 {
 - [Deque (JDK 17)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Deque.html)
 - [Map 接口 (JDK 17)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html)
 - [HashMap (JDK 17)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/HashMap.html)
+- [TreeMap (JDK 17)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/TreeMap.html)
 - [Map.Entry (JDK 17)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.Entry.html)
 - [Object.hashCode() (JDK 17)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#hashCode())
 - [红黑树 Red-Black Tree(Wikipedia)](https://zh.wikipedia.org/wiki/%E7%BA%A2%E9%BB%91%E6%A0%91)
+- [二叉搜索树 Binary Search Tree(Wikipedia)](https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91)
+- [平衡二叉树 AVL 树(Wikipedia)](https://zh.wikipedia.org/wiki/AVL%E6%A0%91)
 
 ### 推荐阅读
 
 - 《Java 核心技术 卷 I》第 9 章 集合 —— 迭代器与 foreach 的关系、Map 集合
 - 《Effective Java》第 3 版 第 58 条:优先使用 foreach 循环而非传统 for 循环
 - 《Java 编程思想》第 17 章 容器深入研究 —— 散列与哈希码
+- 《算法(第 4 版)》第 3.3 节 红黑二叉查找树 —— 红黑树原理与实现
 
 ### 相关知识点
 
@@ -563,3 +679,4 @@ public class Demo05 {
 | 泛型与集合体系(0729) | Iterable → Collection 继承体系 | Set 集合与 Map 迭代 |
 | Collection 单列集合体系 | Map 集合 / HashMap 入门 | Map 遍历(entrySet)、HashMap 底层哈希表 |
 | equals/hashCode 重写(0728) | HashMap 底层原理(数组+链表/红黑树) | HashMap 扩容机制、哈希冲突优化 |
+| HashMap 红黑树(本节 6) | 二叉树 / 二叉搜索树 / AVL / 红黑树 | TreeMap 与 Set 集合、树结构源码分析 |