一.树的导览
二.二叉搜索树
二叉搜索树首先是一棵二叉树,即每个节点只有两个或两个以下的节点数,其次满足二叉搜索树自身的性质:任何节点的键值一定大于其左子树中每一个节点的键值,一定小于其右子树中每一个节点的键值(注意是键值不是实值)。
二叉搜索树可提供对数时间的元素插入和访问。
元素插入时,从根节点开始比较一直到找到自己合适的位置(新插入的肯定是叶节点),元素删除时,若删除的节点只有一个子节点,则把子节点连到删除节点的父节点即可,若有两个子节点,则把右子树中的最小值(即右子树最左边的叶节点)移到删除节点的位置。
三.平衡二叉搜索树
在一般的二叉搜索树中可能出现一种极端情况,即由于输入值不够随机,找出某一子树深度过大,甚至只有一条路相当于线性序列了的情况,一些特殊结构AVL-tree,RB-tree,AA-tree可以避免这种情况,这些结构虽然查找的平均时间长了点,但最坏情况却好得多。
四.AVL tree
AVL tree就是一种平衡二叉搜索树,它保证平衡(即深度为O(logn))的访问是要求任何节点的左右子树高度相差最多1。
插入一个节点后,若某个节点的左右子树高度为2了,则表式平衡被破坏,假设该节点为X,平衡被破坏有四种情况:
1.插入点位于X左子节点的左子树 左左
2.插入点位于X左子节点的右子树 左右
3.插入点位于X右子节点的左子树 右左
4.插入点位于X右子节点的右子树 右右
其中1,4对称,称为外侧插入,采用单旋转操作调整解决
2,3对称,称为内侧插入,采用双旋转操作调整解决
单旋转
如果由于外侧插入而导致不平衡,那么情况就只有一种,所以其实很好讨论
使其再次平衡的方法也很简单,就是想办法让A提高一层,C降低一层,把K1提起来,让K2自然滑下去,并把B子树成为K2的左子树(这种主要是因为二叉搜索树的特性,即B的键值在K1K2之间),这些操作到时候只需要改指针即可(情况固定,方法固定,比较简单)。
双旋转
在内侧插入造成不平衡的情况下,双旋转就是利用两次单旋转完成平衡
单旋转双旋转的补充
其实书上对单旋转双旋转的介绍很粗略,去网上和教材找了找资料,不过网上和教材的资料都很复杂,在我看来,这个单旋转和双旋转并没有那么复杂,可归结为下面的方法。
1.判断是单旋转还是双旋转
2.判断旋转轴
3.判断旋转方向
4.判断其余要移动的节点
1:由插入点回溯,找到第一个不符合平衡树的节点(我们把它叫做原根节点),以及回溯路径上原根节点的直接子节点,看插入点的键值是否在原根节点和直接子节点之间,如果不在,则为单旋转,如果在,则为双旋转。接下来分类讨论
单旋转
2:单旋转的旋转轴就是原根节点的直接子节点(把它叫做新根节点)
3:单旋转的旋转方向是新根节点往原根节点方向旋转(即原根节点在右边就顺时针旋转,原根节点在左边就逆时针旋转)
4:新根节点靠近原根节点的那边子树作为原根节点的相应子树(例如新根节点是原根节点的左子树,那新根节点的右子树就靠近原根节点,那即把新根节点的右子树作为原根节点的左子树)
双旋转
2:双旋转的旋转轴是插入点的直接父节点
3,4:把直接父节点作为旋转轴连续进行两次单旋转的3,4步骤
为原根节点的左子树)
双旋转
2:双旋转的旋转轴是插入点的直接父节点
3,4:把直接父节点作为旋转轴连续进行两次单旋转的3,4步骤