树
集合有三个重要的分类,树就属于其中的层级结构。大多数编程语言并没有将树作为一种标准类型包含其中,尽管如此,树还是得到了广泛的应用,它可以很自然的表示物体的集合,例如,一个文件的目录结构和一本书的目录。
树的两个主要特征:
(1)每个项都有多个子节点
(2)除了叫做根的特殊的项,所有其他的项都只有一个父节点
二叉树
这里有两种极端情况:
(1)分叉状,带有N个节点并且高度为N-1
这样的树类似于链表列表中的一个线性链,因此,在这种结构中,访问、插入或删除一个节点,最坏情况下的时间代价都是线性的。
(2)满二叉树,包含了给定高度H下的最大数目的节点
现在我们来计算下,一个高度为H的满二叉树包含的节点数目N是多少?
N = 1 + 2 + ... + 2H = 2^(H+1) - 1
那么也可以求得包含N个节点的满二叉树的高度H:
H = log2(N+1) - 1
由于在从根节点到一个叶子节点的给定路径上,节点的数目接近于log2(N),如果要访问一个满二叉树上的一个给定的节点的话,所需的最大工作量为O(logN)。
一般来说,二叉树越平衡,访问、插入和删除的性能也就会越高。
完美二叉树(满二叉树)、完全二叉树、完满二叉树比较
完美二叉树:一个深度为k(>=-1)且有2^(k+1) - 1个结点的二叉树称为完美二叉树。 (注: 国内的数据结构教材大多翻译为"满二叉树")
完全二叉树:完全二叉树从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充,其叶子结点都靠左对齐。
完满二叉树:所有非叶子结点的度都是2。(只要你有孩子,你就必然是有两个孩子。)
遍历二叉树
前序遍历
前序遍历算法先访问树的根节点,然后以类似的方式分别遍历左子树和右子树。
中序遍历
中序遍历的算法先遍历左子树,然后访问根节点,最后遍历右子树,这个算法先尽量移动到树的最左边,然后才开始访问节点。
后序遍历
后续遍历算法会先遍历左子树,然后是右子树,最后访问根节点。
层序遍历
层序遍历算法会首先从0层级开始,在每一个层级按照从左向右的顺序访问节点。
二叉搜索树
二叉搜索树(BST)在其节点上施加了一种排序的顺序。在一个BST中,给定节点的左子树中的节点要小于它,其右子树中的节点要大于给定的节点。
由于列表是有序的,搜索算法在每一次比较之后,都将搜索空间减少了一半,一个完美的平衡二叉树的搜索时间是对数级的。
链表实现二叉搜索树
二叉搜索树接口
二叉搜索树的接口应该包含一个构造方法和适用于所有集合的基本操作(isEmpty、len、str、+、==、in和add)。与包集合一样,插入和删除是通过add和remove方法来实现的,当Python识别到in操作符的时候,它会运行__contains__方法以在任何BST实现上执行一次二叉搜索。
为了允许用户访问和替换二叉搜索树中的项,接口还包含了find和replace方法。
由于有四种方法来遍历一个二叉树,我们针对每种遍历包含了一个方法,每个遍历方法都会返回一个迭代器。树的__iter__方法支持前序遍历。