L、D、R分别表示遍历左子树、访问根结点和遍历右子树
仅有前序和后序遍历,不能确定一个二叉树,必须有中序遍历的结果
深度为k,且有2^k-1个节点称之为满二叉树;
深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中,序号为1至n的节点对应时,称之为完全二叉树。
//n 表示当前结点字符
Node* tree(vector data, int n) {
Node* node;
if (n >= data.size())
return NULL;
if (data[n] == '#')
return NULL;
node = new Node;
node->data = data[n];
node->left = tree(data, n + 1);
node->right = tree(data, n + 2);
return node;
}
堆通常是一个可以被看做一棵树的数组对象。堆的实现通过构造二叉堆(binary heap),实为二叉树的一种;
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
通常堆是通过一维数组来实现的。在数组起始位置为1的情形中:
霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的路径长度是从树根到每一结点的路径长度之和,记为WPL=(W1L1+W2L2+W3L3+…+WnLn),N个权值Wi(i=1,2,…n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,…n)。可以证明霍夫曼树的WPL是最小的。
定理:对于具有n个叶子节点的霍夫曼树,共有2n-1个节点。这是由于霍夫曼树只有度为0和度为2的结点,根据二叉树的性质 n0 = n2 + 1,因此度为2的结点个数为n-1个,总共有2n-1个节点。
对于一个霍夫曼树,所有左链接取’0’、右链接取’1’。从树根至树叶依序记录所有字母的编码。
二叉查找树,也称二叉搜索树、有序二叉树,排序二叉树,是指一棵空树或者具有下列性质的二叉树:
二分查找的时间复杂度是O(log(n)),最坏情况下的时间复杂度是O(n)(相当于顺序查找)
平衡树是计算机科学中的一类改进的二叉查找树。一般的二叉查找树的查询复杂度是跟目标结点到树根的距离(即深度)有关,因此当结点的深度普遍较大时,查询的均摊复杂度会上升,为了更高效的查询,平衡树应运而生了。平衡指所有叶子的深度趋于平衡,更广义的是指在树上所有可能查找的均摊复杂度偏低。
AVL树是最先发明的 自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。
增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。
高度为k的AVL树,节点数N最多2^k -1,即满二叉树;
红黑树是一种自平衡二叉查找树,每个节点都带有颜色属性的二叉查找树,颜色为红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
如果一条路径上的顶点除了起点和终点可以相同外,其它顶点均不相同,则称此路径为一条简单路径;起点和终点相同的简单路径称为回路(或环)。
红黑树相对于AVL树来说,牺牲了部分平衡性以换取插入/删除操作时少量的旋转操作,整体来说性能要优于AVL树。
这些约束确保了红黑树的关键特性:从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的。因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限 允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。
在很多树数据结构的表示中,一个节点有可能只有一个子节点,而叶子节点包含数据。用这种范例表示红黑树是可能的,但是这会改变一些性质并使算法复杂。为此,本文中我们使用”nil叶子”或”空(null)叶子”,如上图所示,它不包含数据而只充当树在此结束的指示。这些节点在绘图中经常被省略,导致了这些树好像同上述原则相矛盾,而实际上不是这样。与此有关的结论是所有节点都有两个子节点,尽管其中的一个或两个可能是空叶子。
因为每一个红黑树也是一个特化的二叉查找树,因此红黑树上的只读操作与普通二叉查找树上的只读操作相同。然而,在红黑树上进行插入操作和删除操作会导致不再符合红黑树的性质。恢复红黑树的性质需要少量(O(log n))的颜色变更(实际是非常快速的)和不超过三次树旋转(对于插入操作是两次)。虽然插入和删除很复杂,但操作时间仍可以保持为O(log n)次。
是一种多路搜索树(并不是二叉的):
| n | p0 | k1 | p1 | k2 | p2 | … | kn | pn | >n
为该节点中的关键字个数,除根节点外,其他所有非叶子节点的关键字个数n:[m/2]-1 <= n <= m-1
;ki(i <= i <=n)为该节点的关键字且满足ki < ki+1
pi(0 <= i <=n)为该节点的孩子节点指针pi(0 <= i <=n-1)所指节点上的关键字大于等于ki且小于ki+1,pn所指节点上的关键字大于kn.
B-树的阶:所有节点的孩子节点数的最大值
在B-树中的查找给定关键字的方法 类似于二叉排序树上的查找,不同的是在每个节点上确定向下查找的路径不一定是二路的,而是n+1路的。因为节点内的关键字序列key[1…n]有序,故既可以使用顺序查找,也可以使用二分查找。在一棵B-树上查找关键字为k的方法为:将k与根节点中的key[i]进行比较: 1. 若k=key[i],则查找成功; 2. 若kkey[n],则沿着指针ptr[n]所指的子树继续查找。
将关键字k插入到B-树的过程分两步完成:
首先查找B树中需删除的元素,如果该元素在B树中存在,则将该元素在其结点中进行删除;如果删除该元素后,首先判断该元素是否有左右孩子结点,如果有,则上移孩子结点中的某相近元素到父节点中,然后是移动之后的情况;如果没有,直接删除后,然后是移动之后的情况。
删除元素,移动相应元素之后,如果某结点中元素数目(即关键字数)小于Min(m/2)-1,则需要看其某相邻兄弟结点是否丰满,如果丰满,则向父节点借一个元素来满足条件;如果其相邻兄弟都刚脱贫,即借了之后其结点数目小于Min(m/2)-1,则该结点与其相邻的某一兄弟结点进行“合并”成一个结点,
是一种自平衡二叉树,通常用于数据库和操作系统的文件系统中。B+树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+树元素自底向上插入,这与二叉树恰好相反。B+树不需要象其他自平衡二叉查找树那样经常的重新平衡。
B+树是B-树的变体,也是一种多路搜索树:
m阶的B+树和B-树的主要差异如下:
在B+树中可以采用两种查找方式:
在B+树中,不管查找是否成功,每次查找都是经历一条树从根节点到叶子节点的路径。
B-树和B+树 主要用于外部查找,即数据在外存中。
为什么说B+树比B-树更适合实际应用中操作系统的文件索引和数据库索引?
Trie树,又称前缀树,字典树, 是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。
Trie树查询和插入时间复杂度都是 O(n),是一种以空间换时间的方法。当节点树较多的时候,Trie 树占用的内存会很大。
Trie树常用于搜索提示。如当输入一个网址,可以自动搜索出可能的选择。当没有完全匹配的搜索结果,可以返回前缀最相似的可能。