树
树的应用
在计算机科学中,树是非常有用的抽象概念。
- 文件系统
- 算术表达式
- 搜索,特别是数据存储于磁盘时的搜索
- 数据结构的实现,如 TreeSet、TreeMap
树的定义
以递归的方式定义树。
- 树是一些节点的集合,该集合可以是空集,也可以不是空集。
- 如果不是空集,那么树由一个称为根的节点 root,以及 0 个或多个非空子树 T1, T2, ..., Tk 组成。子树都被来自根 root 的一条有向边所连结。
树的性质之点边的数量
- 如果树由
N个节点,那么树必定有N - 1条边。 - 推导:除了根节点外,每个节点都被一条来自其父节点的有向边所连结。
树的基本概念
- 叶子节点:没有子节点的节点称为叶子节点。
- 兄弟节点:有相同父节点的节点之间称为兄弟节点。
路径
如果对于一个节点序列 N1, N2, ..., Nk,存在 1<= i <= k,节点 Ni 是节点 N(i+1) 的父节点都成立,那么该序列称为从节点 N1 到节点 Nk 的路径。
路径上边的数量称为路径的长,即 k - 1。
从每一个节点到自己有一条长为 0 的路径。
节点的深度
- 对于任意节点
N,节点N的深度是从根节点到N的路径的长。 - 根节点的深度为
0。
节点的高度
- 对于任意节点
N,节点N的高度是从节点N到叶子节点的最长路径的长。 - 所有叶子节点的高度都为
0。
树的高度和树的深度
- 树的高度等于其根节点的高度。
- 树的深度等于它的最深的树叶的深度。
- 也就是说,树的高度和树的深度总是相等的。
树的前置知识
- 递归
- 对数
- 基本常识:文件系统、搜索、大自然树图、房间和储物柜
- 大自然树图:只有根、树枝、树干、叶子
- 房间和储物柜:培养目录层级思维
文件系统
- 在 UNIX 系统中,目录就是包含其所有儿子的一个文件。
- 实际上,UNIX 系统中的目录还包含了 2 项,分别指向目录本身以及父级目录。因此,从技术上说,UNIX 文件系统不是树,而是类树。
- 练习1:写出遍历打印目录内容的伪代码。分析其时间复杂度。
- 练习2:写出统计文件占用的磁盘区块的个数的伪代码。
// 练习1
public void list() {
listRecursive(0);
}
public void listRecursive(int depth) {
// 打印文件名,需要控制缩进
print(depth);
// 如果当前文件是一个目录,那么递归处理目录里的文件
if (isDirectory) {
for (File child: getChildren()) {
child.listRecursive(depth + 1);
}
}
}
// 练习2
public long size() {
// 获取当前文件的大小
long totalSize = getSize();
// 如果当前文件是一个目录,那么递归处理目录里的文件
if (isDirectory()) {
for (File child : getChildren()) {
totalSize += child.size();
}
}
return totalSize;
}
树的遍历
-
先序遍历(preorder traversal):先处理节点,再处理子节点。
-
后续遍历(postorder traversal):先处理子节点,再处理节点本身。
二叉树的定义
- 二叉树是一颗树,其任意节点的子节点不超过 2 个。
- 二叉树的左右子树都可能为空。
二叉树的平均深度
如果二叉树的节点数为 N,那么根据二叉树的不同形态,得到的二叉树的深度是不同的。
定义:节点数为 N 的二叉树的平均深度,是指不同形态二叉树的深度的平均值。
这个是我自己定义的二叉树平均深度。求所有形态下二叉树的平均深度。
-
一颗平均二叉树的深度要比节点数 N 小得多,即
O(根号 N)。没见过这个定义。 -
二叉查找树的平均深度为
O(log(N)),但最大深度可达N-1。 -
一颗二叉树的节点数为
N,那么二叉树有N+1条null链。
二叉树的实现
class BinaryNode {
Object element;
BinaryNode left;
BinaryNode right;
}
表达式树
-
叶子节点表示操作数,如常数或变量。
-
非叶子节点表示操作符。
表达式树的练习
-
将中缀表达式转为表达式树
-
将后缀表达式转为表达式树
-
将表达式树转为中缀表达式
-
将表达式树转为后缀表达式
-
将中缀表达式转为后缀表达式
二叉查找树
当二叉树满足以下性质时,二叉树就变成了二叉查找树。
浙公网安备 33010602011771号