1、二叉排序树
二叉排序树又称为二叉查找树。是一个具有下列属性的二叉树:
- 若左子树不为空,则左子树上所有节点值均小于它的根节点的值
- 若右子树不为空,则右子树上所有节点的值均大于它的根节点的值
当对树进行中序遍历时,我们就会得到一个从小到大的序列。
构造二叉排序树的目的:提高查找和插入删除关键字的速度。
注意:二叉排序树中不允许有重复或相等的key值出现。
1)删除操作
- 当删除的节点为叶子节点时,直接删除
- 当删除节点为中间节点时,若它只有右子树或者只有左子树,则直接使用它的右子树或左子树代替它。
- 当删除节点为中间节点,且有左子树和右子树,则使用中序遍历的前驱节点或者后继节点代替当前节点,删除原来位置的前驱或后继节点。
2)插入操作
插入操作很简单,依据二叉排序的原则,从根节点依次比较大小,小于则和左子树继续比较,大于则和右子树继续比较,直到为空时,放入该位置。
3)查找操作
从根节点依次比较查找,相等时则命中。复杂度O(logn)
存在的缺点:有时候根据初始给定的序列构造出来的树很不平衡,比如极端的左斜树或右斜树,这样查找比较的速度就很慢。我们希望能构造出比较平衡的二叉树,其深度与完全二叉树相同,那么查找的时间复杂度就为O(logn)。
2、二叉排序树的平衡算法
由于二叉排序树经过初始序列的构造,或者经过多次删除插入操作,使二叉树变得不平衡,这样查找速度就会变慢,我们希望得到最快的查找速度,即希望构造出深度与完全二叉树一样的二叉排序树,而且保证在插入删除的过程中不破坏结构,保证查找的复杂度为O(logn)。
下边介绍两种平衡二叉排序树的算法:
- 平衡二叉树(严格的平衡算法):插入删除时需要旋转的次数较多。
- 红黑树(弱平衡算法):二叉排序树的深度并不一定等于完全二叉树的深度,以牺牲查找速度为代价,降低插入删除时的旋转次数。
1)平衡二叉树(AVL树)
平衡二叉树每一个节点的左子树和右子树的高度差至多等于1.
平衡因子BF : 将二叉树上节点的左子树深度减去右子树深度的值称为平衡因子,平衡二叉树的所有节点的平衡因子只能是(-1,0,1)。
最小不平衡子树:距离插入点最近,且平衡因子的绝对值大于1的结点为根节点的子树。
平衡二叉树的创建原理
平衡二叉树在创建的过程中就一直保证他的平衡性,当插入一个节点时破坏了平衡,找到最小不平衡子树,然后调整这个子树各节点之间的连接关系,进行相应旋转,使之成为新的平衡子树。
2)红黑树
红黑树并不是完全平衡的二叉树,它只能保证没有一条路径会比其他路径长出两倍,所以它的查找会比AVL树稍微慢,但他的插入和删除会比AVL树需要较少的旋转次数。
红黑树具有以下性质
- 每一个节点要么是黑的要么是红的。
- 根节点是黑的。
- 如果一个节点时红的,那么他的根节点必须是黑的。
- 从一个节点到一个null引用的每一条路径必须包含相同数目的黑色节点。
- 每个叶子节点(NIL)是黑色。
红黑树的应用:Java集合中的TreeSet和TreeMap,C++ STL中的set、map,以及Linux虚拟内存的管理,都是通过红黑树去实现的。