数据结构和算法(七)——树的基础知识

413 阅读6分钟

定义

不同于线性的数据结构数组、链表、栈,树是非线性的。如图所示(图片来源leetcode),树是由n(n>=1)个有限节点组成一个具有层次关系的集合。

常用术语

  1. 结点的度:结点拥有的子树的数目。例如A的度为3。
  2. 叶子:度为零的结点,如B、E、F、G
  3. 树的度:树中结点的最大的度
  4. 节点的高度:节点到叶子节点的最长路径
  5. 节点的深度:根节点到这个节点所经历的边的个数
  6. 节点的层数:节点的深度加 1
  7. 树的高度:根节点的高度

二叉树

定义

二叉树是每个节点最多有两个子树的树结构。如图所示:

二叉树是最常用的树。

满二叉树

除了叶子节点之外,每个节点都有左右两个子节点,这种二叉树就叫作满二叉树。如图:

完全二叉树

一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下一层的叶结点集中在靠左的若干位置上。这样的二叉树称为完全二叉树。一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。如图所示:

二叉查找树(或二叉搜索树)

二叉搜索树(BST)是二叉树的一种特殊表示形式,它满足如下特性:

  1. 每个节点中的值必须大于(或等于)存储在其左侧子树中的任何值。
  2. 每个节点中的值必须小于(或等于)存储在其右子树中的任何值。

如图所示:

AVL树

AVL树是一种严格的平衡的二叉树。平衡二叉树的严格定义是这样的:二叉树中任意一个节点的左右子树的高度相差不能大于1。如图:

上面的两张图片,左边的是AVL树,它的任何节点的两个子树的高度差别都<=1;而右边的不是AVL树,因为7的两颗子树的高度相差为2(以2为根节点的树的高度是3,而以8为根节点的树的高度是1)。

平衡二叉树就是AVL树,是一种特殊的二叉搜索树。

红黑树

红黑树是一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。如图所示:

红黑树需要满足的要求:

  1. 根节点是黑色的;
  2. 每个叶子节点都是黑色的空节点(NIL),也就是说,叶子节点不存储数据;
  3. 任何相邻的节点都不能同时为红色,也就是说,红色节点是被黑色节点隔开的;
  4. 每个节点,从该节点到达其可达叶子节点的所有路径,都包含相同数目的黑色节点;

哈夫曼树

路径长度:树中一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上的分支数目为路径长度。例如:节点4 到 节点5 的路径长度为 2;节点3 到节点6 的路径长度为4.

树的路径:从树根到每一个结点的路径长度之和,这种路径长度最短的树是完全二叉树. 上图中,树的路径长度为:1 + 1 + 2 + 2 + 2 + 3 = 11。

:若将树中结点赋一个有某种含义的数值,则这个数值称为该结点的权

结点的带权路径长度:从根结点到该结点间的路径长度与该结点的权的乘积,如D节点的带权路径长度为 4 * 3 = 12

树的带权路径长度(WPL):树中所有带权结点的路径长度之和 上图中,树的带权路径长度WPL为:7 X 1 + 5 X 2 + 2 X 3 + 4 X 3 = 35。

哈夫曼树就是树的带权路径长度最短的二叉树,也叫做最优树。

前缀树

N 叉树 :一棵以根节点开始,每个节点不超过 N 个子节点的树,称为 N叉树

如图,前缀树(又叫字典树) 是 N叉树 的一种特殊形式。通常来说,一个前缀树是用来 存储字符串 的。前缀树的每一个节点代表一个 字符串(前缀)。每一个节点会有多个子节点,通往不同子节点的路径上有着不同的字符。子节点代表的字符串是由节点本身的 原始字符串 ,以及 通往该子节点路径上所有的字符 组成的。

B树、B+树、B*树

背景

当我们数据量非常大,以至于必须需要磁盘来存储数据时。由于一次磁盘访问时间远远大于内存访问时间,因此减少磁盘访问的次数就可以缩短访问的时间。

如果使用之前讲过的二叉平衡搜索树,则查找的速率为logN次磁盘访问的时间;若过我们有更多的分支,那么树的高度就会降低,磁盘访问的速度就会缩小为 logMNlog_MN,这样虽然代码变得更加复杂,但是相对于磁盘访问的时间可以忽略不计。

B树

B树(也叫做 B-树) 是一种多路平衡搜索树,不是二叉搜索树,B树的 M > 2,B树的 M 可以等于 3、4、5....。例如:当 M = 3时,是三叉树;而 M = 4 时是四叉树,而二叉搜索树 M = 2。

如图(图片来源知乎)是M = 5的B树.其中 M、D、G是保存的数据。

B树特点:

  1. 所有节点的数据都是按从小到大的顺序排列
  2. 非叶子节点保存数据的个数满足[ceil(M/2) - 1,M-1]
  3. 所有叶子节点均在同一层

注:ceil()是向上取整的函数,例如 ceil(1.1) = 2

B+树

B+树是B树的一个升级版,它与B+树的不同点为:

  1. 非叶子节点不保存数据记录的指针,只进行数据索引;叶子节点用来保存数据
  2. B+树叶子节点的关键字从小到大有序排列,左边结尾数据都会保存右边节点开始数据的指针

B+树如图所示(图片来源这里):

B*树

B*树是B+树的变种,其与B+树的区别有:

  1. B*树在B+树的非根和非叶子节点再增加指向兄弟节点的指针
  2. B*树规定非叶子节点的键值个数至少为(2/3)M

B*树如图(图片来源这里

参考