AVL
来源:互联网 发布:大数据 通用 解决方案 编辑:程序博客网 时间:2024/06/05 16:54
AVL
目录
- AVL
- 概述
- 单旋转
- 右旋转
- 左旋转
- 双旋转
- 左-右旋转
- 右-左旋转
- 代码实现
- Summary
概述
二叉搜索树(BST)可能会造成如下图所示的问题:
查找的时间复杂度会达到O(N),这个时候AVL树就派上用场了。
一棵AVL树是其每个节点的左子树和右子树的高度最多差1的二叉搜索树(空树的高度定义为-1)。
把失去平衡的节点叫做α,由于任意节点最多有两个孩子,因此出现高度不平衡的α的两棵子树的高度差为2。容易看出,这种不平衡可能会出现以下四种情况:
- 对α的左孩子的左子树进行一次插入
- 对α的左孩子的右子树进行一次插入
- 对α的右孩子的左子树进行一次插入
- 对α的右孩子的右子树进行一次插入
情形1和4是对称的,2和3也是对称的。因此,理论上只有两种情形。
单旋转
右旋转
情形1如下图所示:
在k2的左孩子k1的左子树插入一个元素,导致k2的左右子树不平衡了(插入前是平衡的),此时以k1为轴,进行一次右旋转(顺时针)即可达到平衡。
左旋转
同理,就很容易得出对称的情形4:
在k1的右孩子k2的右子树插入一个元素,导致k1的左右子树不平衡(插入前是平衡的),此时以k2为轴,进行一次左旋转(逆时针)即可达到平衡。
双旋转
左-右旋转
情形2如图所示:
假设在k3的左孩子k1的右子树上k2插入一个元素,导致B或者C比D深两层,那么此时只需要:
- 以k1为轴,先做一次左旋转(情形1)
- 再次k3为轴,做一次右旋转(情形4)
即可让整棵树再次达到平衡,也就是两次单旋转即可。
右-左旋转
同样,对于情形3,如图:
在k1的右孩子k3的左子树k2上插入一个元素,导致B或者C比A深两层,那么此时只需要:
- 以k3为轴,先做一次右旋转(情形4)
- 再以k1为轴,做一次左旋转(情形1)
即可让整棵树再次达到平衡,也是两次单旋转。
代码实现
已经明白了旋转的原理,剩下的就是编码实现了,弄清楚指针指向就行了。
public class AVLTreeTest { public static void main(String[] agrs) { AVLTree tree = null; for(Integer i = 1; i < 10; i++) { tree = AVLTreeUtils.insert(i, tree); } System.out.println("preOrder: "); AVLTreeUtils.preOrder(tree); System.out.println(); System.out.println("inOrder: "); AVLTreeUtils.inOrder(tree); System.out.println(); System.out.println("postOrder: "); AVLTreeUtils.postOrder(tree); } }class AVLTree { public Integer element; public AVLTree lchild; public AVLTree rchild; public Integer height; public AVLTree() {}}class AVLTreeUtils { public static AVLTree insert(Integer ele, AVLTree root) { if(root == null) {// 如果是空节点,就插入 root = new AVLTree(); root.element = ele; root.lchild = root.rchild = null; root.height = 0; } else if(ele < root.element) {// 在左子树插入 root.lchild = insert(ele, root.lchild); // 插入后,检查一下是否已经失衡 if(getHeight(root.lchild) - getHeight(root.rchild) == 2) { if(ele < root.lchild.element) // 左孩子的左子树——情形1 root = singleRotateWithLeft(root); else // 左孩子的右子树--情形2 root = doubleRotateWithLeft(root); } } else if(ele > root.element) { root.rchild = insert(ele, root.rchild); if(getHeight(root.rchild) - getHeight(root.lchild) == 2) { if(ele > root.rchild.element) // 右孩子的左子树--情形3 root = singleRotateWithRight(root); else // 右孩子的右子树--情形4 root = doubleRotateWithRight(root); } } // 调整完成后,更新一下整棵树的高度 root.height = Math.max(getHeight(root.lchild), getHeight(root.rchild)) + 1; return root; } private static Integer getHeight(AVLTree tree) { if (tree == null) return -1; return tree.height; } // 对照几张示意图,即可弄明白指针的指向 // 情形1 private static AVLTree singleRotateWithLeft(AVLTree oldRoot) { AVLTree newRoot = oldRoot.lchild;; oldRoot.lchild = newRoot.rchild; newRoot.rchild = oldRoot; oldRoot.height = Math.max(getHeight(oldRoot.lchild), getHeight(oldRoot.rchild)) + 1; newRoot.height = Math.max(getHeight(newRoot.lchild), oldRoot.height) + 1; return newRoot; }; // 情形4 private static AVLTree singleRotateWithRight(AVLTree oldRoot) { AVLTree newRoot = oldRoot.rchild;; oldRoot.rchild = newRoot.lchild; newRoot.lchild = oldRoot; oldRoot.height = Math.max(getHeight(oldRoot.lchild), getHeight(oldRoot.rchild)) + 1; newRoot.height = Math.max(oldRoot.height, getHeight(newRoot.rchild)) + 1; return newRoot; }; // 情形2 private static AVLTree doubleRotateWithLeft(AVLTree oldRoot) { oldRoot.lchild = singleRotateWithRight(oldRoot.lchild); return singleRotateWithLeft(oldRoot); }; // 情形3 private static AVLTree doubleRotateWithRight(AVLTree oldRoot) { oldRoot.rchild = singleRotateWithLeft(oldRoot.rchild); return singleRotateWithRight(oldRoot); }; // 先序遍历 public static void preOrder(AVLTree tree) { if(tree != null) { System.out.print(tree.element + " "); preOrder(tree.lchild); preOrder(tree.rchild); } } // 中序遍历 public static void inOrder(AVLTree tree) { if(tree != null) { inOrder(tree.lchild); System.out.print(tree.element + " "); inOrder(tree.rchild); } } // 后序遍历 public static void postOrder(AVLTree tree) { if(tree != null) { postOrder(tree.lchild); postOrder(tree.rchild); System.out.print(tree.element + " "); } }}// outputpreOrder: 4 2 1 3 6 5 8 7 9 inOrder: 1 2 3 4 5 6 7 8 9 postOrder: 1 3 2 5 7 9 8 6 4
Summary
以前挺畏惧树的,可是仔细研究一下 – Just a pretty girl standing out there in the fog waiting to be saved…
0 0
- avl
- avl
- {avl}
- AVL
- AVL
- AVL
- AVL
- AVL
- AVL
- AVL
- AVL
- HDU2193-AVL-数据结构-AVL
- AVL代码
- AVL Tree
- AVL树
- AVL树
- AVL树
- avl树
- Redis Cluster集群的搭建与实践
- Unity Shaders and Effects Cookbook (7-1) 在Surface Shader 中 访问 顶点颜色
- ui-router
- eclipse中的SQLiteDatabase的两个属性的查语句
- 线程同步的几种方法
- AVL
- 怎样进行调试?
- PHP基础语法
- tamcat学习2之使用Maven新建webapp,并从HelloServlet中读取变量值
- 数据库设计简要规范
- 5.sqlMapConfig配置
- 【C语言】整型溢出和整型提升
- git的学习(各个版本之间的转换)
- hihocoder -#1043 : 完全背包