背景:
在一个神秘的魔法世界里,有一棵神奇的树叫家谱树。这棵树记录了所有魔法师的家族关系,每个节点都是一位魔法师,每个魔法师最多有两个徒弟(左徒弟和右徒弟)。
规则:
-
每个魔法师(节点)可以有 0、1 或 2 个徒弟。
-
每个徒弟只能有一个师傅(父节点)。
-
最顶层的魔法师是根节点(Root),没有师傅。
例子:
-
根节点:大法师梅林(Merlin)。
-
梅林的左徒弟:魔法部长哈利(Harry)。
-
梅林的右徒弟:占卜师赫敏(Hermione)。
-
哈利的左徒弟:草药师纳威(Neville)。
-
哈利的右徒弟:魔咒师罗恩(Ron)。
-
赫敏没有徒弟。
这个家谱可以用二叉树表示:
plaintext
梅林(Merlin)
/ \
哈利(Harry) 赫敏(Hermione)
/ \
纳威(Neville) 罗恩(Ron)
二叉树的核心概念
1. 节点(Node)
每个魔法师都是一个节点,包含:
- 数据:魔法师的名字。
- 左指针:指向左徒弟。
- 右指针:指向右徒弟。
2. 根节点(Root)
整棵树的起点,没有父节点(如梅林)。
3. 叶子节点(Leaf)
没有徒弟的节点(如纳威、罗恩、赫敏)。
4. 子树(Subtree)
每个节点可以看作是一棵子树的根(如哈利及其徒弟构成一棵子树)。
Java 代码:构建二叉树
1. 定义节点类
java
class WizardNode {
String name; // 魔法师名字(数据)
WizardNode left; // 左徒弟
WizardNode right; // 右徒弟
// 构造函数:创建新节点
public WizardNode(String name) {
this.name = name;
this.left = null; // 初始没有徒弟
this.right = null;
}
}
2. 手动构建二叉树
java
public class BinaryTreeExample {
public static void main(String[] args) {
// 1. 创建节点(魔法师)
WizardNode merlin = new WizardNode("梅林(Merlin)");
WizardNode harry = new WizardNode("哈利(Harry)");
WizardNode hermione = new WizardNode("赫敏(Hermione)");
WizardNode neville = new WizardNode("纳威(Neville)");
WizardNode ron = new WizardNode("罗恩(Ron)");
// 2. 建立师徒关系(连接节点)
merlin.left = harry; // 梅林的左徒弟是哈利
merlin.right = hermione; // 梅林的右徒弟是赫敏
harry.left = neville; // 哈利的左徒弟是纳威
harry.right = ron; // 哈利的右徒弟是罗恩
// 3. 根节点是梅林
WizardNode root = merlin;
// 4. 打印二叉树结构
System.out.println("家谱树结构:");
System.out.println(" " + root.name);
System.out.println(" / \");
System.out.println(" " + root.left.name + " " + root.right.name);
System.out.println(" / \");
System.out.println(root.left.left.name + " " + root.left.right.name);
}
}
运行结果:
plaintext
家谱树结构:
梅林(Merlin)
/ \
哈利(Harry) 赫敏(Hermione)
/ \
纳威(Neville) 罗恩(Ron)
更复杂的二叉树:插入节点
故事扩展:
后来,哈利收了一个新徒弟露娜(Luna) ,作为他的右徒弟(原来的右徒弟罗恩变成露娜的左徒弟)。
插入节点代码:
java
public class BinaryTreeInsertion {
public static void main(String[] args) {
// 1. 构建原有二叉树
WizardNode root = buildOriginalTree();
// 2. 创建新节点(露娜)
WizardNode luna = new WizardNode("露娜(Luna)");
// 3. 插入节点:将露娜作为哈利的右徒弟
// 注意:先保存哈利原来的右徒弟(罗恩)
WizardNode originalRight = root.left.right;
root.left.right = luna; // 哈利的右徒弟变成露娜
luna.left = originalRight; // 露娜的左徒弟是原来的罗恩
// 4. 打印更新后的树结构
System.out.println("更新后的家谱树:");
System.out.println(" " + root.name);
System.out.println(" / \");
System.out.println(" " + root.left.name + " " + root.right.name);
System.out.println(" / \");
System.out.println(root.left.left.name + " " + root.left.right.name);
System.out.println(" /");
System.out.println(" " + luna.left.name);
}
// 辅助方法:构建原有树
private static WizardNode buildOriginalTree() {
WizardNode merlin = new WizardNode("梅林(Merlin)");
WizardNode harry = new WizardNode("哈利(Harry)");
WizardNode hermione = new WizardNode("赫敏(Hermione)");
WizardNode neville = new WizardNode("纳威(Neville)");
WizardNode ron = new WizardNode("罗恩(Ron)");
merlin.left = harry;
merlin.right = hermione;
harry.left = neville;
harry.right = ron;
return merlin;
}
}
运行结果:
plaintext
更新后的家谱树:
梅林(Merlin)
/ \
哈利(Harry) 赫敏(Hermione)
/ \
纳威(Neville) 露娜(Luna)
/
罗恩(Ron)
二叉树的应用场景
- 文件系统:目录结构像一棵倒挂的树。
- 数据库索引:B 树、B + 树用于快速查找数据。
- 游戏 AI:决策树(如走棋策略)。
- 编译原理:语法树分析代码结构。
总结:二叉树就像家族树!
-
节点 = 魔法师,每个魔法师最多有两个徒弟。
-
根节点 = 最顶层的大法师(如梅林)。
-
左 / 右指针 = 指向左 / 右徒弟的魔法纽带。
构建二叉树就是建立师徒关系的过程!如果有任何疑问,欢迎随时提问! 😊