二叉搜索树
1、二叉搜索树的概念
二叉搜索树(二叉排序树)若不为空,则具有以下特性:
- 每个结点有唯一的值,且每个结点的值均不相同;
- 若它的左子树不为空,则它的左子树的所有结点均小于根节点的值;
- 若它的右子树不为空,则它的右子树的所有结点均大于根结点的值;
- 它的左右子树均为二叉搜索树。
例如下图这棵二叉树就是搜索二叉树
2、搜索二叉树的操作
2.1 二叉搜索树的查找
二叉搜索树的查找比较简单,因为它的根结点总是比左子树大,比右子树小,所以它的查找过程类似于折半查找。
折半查找: 必须是有序的顺序存储结构,时间复杂度为O(logN)。
二叉搜索树的查找过程(假设根结点不为空,要查找的值为val)
- 若根结点的值 == val ,则返回 true
- 若根结点的值 > val ,则在左子树中进行查找
- 若根结点的值 < val ,则在右子树进行查找
- 循环上述过程,直到循环结束,若未查找到val 则返回false
2.2 二叉搜索树的插入
二叉搜索树的插入过程要先进行查找,当查找到合适的位置(符合二叉搜索树的特性),然后进行插入。
2.3 二叉搜索树的删除
首先查找待删除结点,若该结点查找不到,则返回false,若查找到,则删除可以分为以下四种情况:
- 情况1
待删除的结点无孩子结点
解决方法:可以直接删除 - 情况2
待删除的结点只有左孩子,没有右孩子
解决方法:待删除结点的双亲结点指向待删除结点的左孩子 - 情况3
待删除的结点只有右孩子,没有左孩子
解决方法:待删除结点的双亲结点指向待删除结点的右孩子 - 情况4
待删除的结点有左孩子和右孩子
解决方法:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,
再来处理该结点的删除问题
3、二叉搜索树的性能分析
3.1 时间复杂度
如果二叉搜索树是平衡的,则n个节点的二叉搜索树的高度为log2N+1,其查找效率为O(lon2N),近似于折半查找。
如果二叉搜索树完全不平衡,则其深度可达到n,查找效率为O(n),退化为顺序查找。
一般的,二叉搜索树的查找性能在O(log2N)到O(n)之间。因此,为了获得较好的查找性能,就要构造一棵平衡的二叉搜索树。
3.2 空间复杂度
二叉树的存储要求:需要树形结构,相比顺序存储需要占用更多的空间,但也有链接型数据结构灵活可拓展的优点。
因为需要建立排序二叉树,所以空间复杂度为O(n)。
3.3 平均查找长度
公式:ASL = [(n+1)/n] * log2(n+1) - 1
例1:假设有一颗平衡的二叉排序树,高度h=4,总结点数n=10,不是满二叉树:
根据公式,查找成功的平均查找长度为:
ASL = [(n+1)/n] * log2(n+1) - 1 = [(10+1)/10] * log2(10+1) - 1 约等于 2.8
逐个结点计数,平均查找长度为:
ASL = (1 * 1 + 2 * 2 + 3 * 4 + 4 * 3) / 10 = 29 / 10 = 2.9
例2:假设有一颗平衡的二叉排序树,高度h=:3,结点数n=7,是满二叉树:
根据公式,查找成功的平均查找长度为:
ASL = [(n+1)/n] * log2(n+1) - 1 = [(7+1)/7] * log2(7+1) - 1 约等于 2.43
逐个结点计数,平均查找长度为:
ASL = (1 * 1 + 2 * 2 + 3 * 4) / 7 = 17 / 7 约等于2.43
综上,二叉搜索树的出现是为了优化查找效率,但是当一棵二叉树不是满二叉树,并且接近于单支树数,查找效率将会退化到与顺序查找的效率相近,为了解决这个问题,提出了二叉平衡树(AVL树)。
AVL树详解