【数据结构】AVL树
来源:互联网 发布:js数组地址指向 编辑:程序博客网 时间:2024/06/18 13:10
1.AVL树的定义
平衡二叉树是一种高度平衡的二叉排序树(父节点大于左子树、小于右子树)。
平衡二叉树的每一个节点的左子树和右子树的高度差至多等于1 。
二叉树上结点的左子树深度减去右子树深度的值称为平衡因子BF ,取值为-1,0,或1
最小不平衡子树:距离插入结点最近的,且平衡因子的绝对值大于1 的结点为根的子树
2.AVL树失衡调整
数组a[]={4,5,6,3,2,8,7,0,1}构建一棵AVL树
(1)左单旋转(BF<-1)
首先插入{4,5,6},在插入元素6后出现不平衡的情况:
单左旋代码
public Node leftRotation(Node root) { Node p = root.right; root.right = p.left; p.left = root; return p; }
(2)右单旋转
插入元素{3,2},出现了不平衡的情况。
单右旋代码:
public Node rightRotation(Node root) { Node p = root.left; root.left = p.right; p.right = root; return p; }
(3)先右旋后左旋
继续插入元素{8,7},第一次旋转后,AVL树仍旧处于不平衡的状态,第二次旋转再次进行调整。即BF一负一正。
(4)先左旋后右旋
接着插入节点{0,1},首先对最小不平衡子树的根节点(也就是节点2)的左孩子(也就是0)进行左旋操作,再对节点2进行一次右旋操作。即BF一正一负。
3.AVL树的插入与删除
(1)插入
//将结点插入到AVL树中,并返回根节点private AVLTreeNode<T> insert(AVLTreeNode<T> tree, T key) { if (tree == null) { // 新建节点 tree = new AVLTreeNode<T>(key, null, null); if (tree==null) { System.out.println("ERROR: create avltree node failed!"); return null; } } else { int cmp = key.compareTo(tree.key); if (cmp < 0) { // 应该将key插入到"tree的左子树"的情况 tree.left = insert(tree.left, key); // 插入节点后,若AVL树失去平衡,则进行相应的调节。 if (height(tree.left) - height(tree.right) == 2) { if (key.compareTo(tree.left.key) < 0) tree = leftLeftRotation(tree); else tree = leftRightRotation(tree); } } else if (cmp > 0) { // 应该将key插入到"tree的右子树"的情况 tree.right = insert(tree.right, key); // 插入节点后,若AVL树失去平衡,则进行相应的调节。 if (height(tree.right) - height(tree.left) == 2) { if (key.compareTo(tree.right.key) > 0) tree = rightRightRotation(tree); else tree = rightLeftRotation(tree); } } else { // cmp==0 System.out.println("添加失败:不允许添加相同的节点!"); } } tree.height = max( height(tree.left), height(tree.right)) + 1; return tree;}public void insert(T key) { mRoot = insert(mRoot, key);}
(2)删除
//删除结点(z),返回根节点treeprivate AVLTreeNode<T> remove(AVLTreeNode<T> tree, AVLTreeNode<T> z) { // 根为空 或者 没有要删除的节点,直接返回null。 if (tree==null || z==null) return null; int cmp = z.key.compareTo(tree.key); if (cmp < 0) { // 待删除的节点在"tree的左子树"中 tree.left = remove(tree.left, z); // 删除节点后,若AVL树失去平衡,则进行相应的调节。 if (height(tree.right) - height(tree.left) == 2) { AVLTreeNode<T> r = tree.right; if (height(r.left) > height(r.right)) tree = rightLeftRotation(tree); else tree = rightRightRotation(tree); } } else if (cmp > 0) { // 待删除的节点在"tree的右子树"中 tree.right = remove(tree.right, z); // 删除节点后,若AVL树失去平衡,则进行相应的调节。 if (height(tree.left) - height(tree.right) == 2) { AVLTreeNode<T> l = tree.left; if (height(l.right) > height(l.left)) tree = leftRightRotation(tree); else tree = leftLeftRotation(tree); } } else { // tree是对应要删除的节点。 // tree的左右孩子都非空 if ((tree.left!=null) && (tree.right!=null)) { if (height(tree.left) > height(tree.right)) { // 如果tree的左子树比右子树高; // 则(01)找出tree的左子树中的最大节点 // (02)将该最大节点的值赋值给tree。 // (03)删除该最大节点。 // 这类似于用"tree的左子树中最大节点"做"tree"的替身; // 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。 AVLTreeNode<T> max = maximum(tree.left); tree.key = max.key; tree.left = remove(tree.left, max); } else { // 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1) // 则(01)找出tree的右子树中的最小节点 // (02)将该最小节点的值赋值给tree。 // (03)删除该最小节点。 // 这类似于用"tree的右子树中最小节点"做"tree"的替身; // 采用这种方式的好处是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。 AVLTreeNode<T> min = maximum(tree.right); tree.key = min.key; tree.right = remove(tree.right, min); } } else { AVLTreeNode<T> tmp = tree; tree = (tree.left!=null) ? tree.left : tree.right; tmp = null; } } return tree;}public void remove(T key) { AVLTreeNode<T> z; if ((z = search(mRoot, key)) != null) mRoot = remove(mRoot, z);}
本人才疏学浅,若有错,请指出
谢谢!
参考资料:
1.平衡二叉树,AVL树之图解篇
2.数据结构图文解析之:AVL树详解
3.AVL树(三)之 Java的实现
阅读全文
0 0
- AVL 树数据结构
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构 - AVL树
- 数据结构:avl树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构: AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 在ssh框架下将数据生成Excel文件导出
- I/O会一直占用CPU吗?【转载】
- 本地 Services(服务)
- 浅谈汇编,认识汇编(一)
- 前端开发的一些实践规范
- 【数据结构】AVL树
- 2017 四川省赛 D.Dynamic Graph【拓扑排序+bitset优化】好题!
- 简析Java字节流和字符流
- java的path和classpath
- 1037: 四则运算
- I/O性能分析-对问题的分析不能只看表象
- 7-16 paper reading
- Kotlin流程控制
- poj1182食物链(并查集)