平衡二叉树(AVL)代码笔记
来源:互联网 发布:福岛正则 知乎 编辑:程序博客网 时间:2024/05/22 05:31
一棵AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1)。
重点在于:
插入和删除可能破坏AVL树的平衡特性,需要进行平衡
分为四种情况:
假设重新平衡的节点为a
需要进行单旋转
(1)a的左儿子的左子树插入
(2)a的右儿子的右子树插入需要进行双旋转
(3)a的左儿子的右子树插入
(4)a的右儿子的左子树插入
package com.base;public class AvlTree<Item extends Comparable<? super Item>> { private static class Node<Item> { Node(Item item) { this(item, null, null); } Node(Item item, Node<Item> lt, Node<Item> rt) { this.item = item; this.left = lt; this.right = rt; this.height = 0; } private Item item; private Node<Item> left; private Node<Item> right; private int height; // 高度 } private Node<Item> root; public AvlTree() { root = null; } public void clear() { root = null; } public boolean isEmpty() { return root == null; } /* * 查找最小 */ public Item min() throws Exception { if (isEmpty()) // 树为空的情况 throw new Exception(); return min(root).item; } private Node<Item> min(Node<Item> t) { if (t == null) return t; while (t.left != null) // 非递归方法 t = t.left; return t; } /* * 查找最大 */ public Item max() throws Exception { if (isEmpty()) throw new Exception(); return max(root).item; } private Node<Item> max(Node<Item> t) { // 递归方法 if (t.left == null) return t; else return min(t.left); } /* * 是否包含 */ public boolean contains(Item x) { return contains(x, root); } private boolean contains(Item x, Node<Item> t) { while (t != null) { // 非递归方式 int cmp = x.compareTo(t.item); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return true; // 匹配 } return false; // 不包含 } // 遍历 public void printTree() { if (isEmpty()) System.out.println("Empty tree"); else printTree(root); } private void printTree(Node<Item> t) { // 左根右--中序 if (t != null) { printTree(t.left); System.out.println(t.item); printTree(t.right); } } /* * 插入 */ public void insert(Item x) { root = insert(x, root); } private Node<Item> insert(Item x, Node<Item> t) { if (t == null) // root为null的情况 return new Node<>(x, null, null); int cmp = x.compareTo(t.item); if (cmp < 0) t.left = insert(x, t.left); else if (cmp > 0) t.right = insert(x, t.right); else ; // 正常二叉树插入 return balance(t); // 再平衡 } /* * 删除 */ public void remove(Item x) { root = remove(x, root); } private Node<Item> remove(Item x, Node<Item> t) { if (t == null) return t; int cmp = x.compareTo(t.item); if (cmp < 0) t.left = remove(x, t.left); else if (cmp > 0) t.right = remove(x, t.right); else { if (t.right == null) return t.left; if (t.left == null) return t.right; t.item = min(t.right).item; t.right = remove(t.item, t.right); } return balance(t); // 正常二叉树删除后再平衡 } // AVL平衡树 // 每个节点的左子树和右子树的高度最多差 1 private static final int ALLOWED_IMBALANCE = 1; // 平衡二叉树 private Node<Item> balance(Node<Item> t) { if (t == null) return t; if (height(t.left) - height(t.right) > ALLOWED_IMBALANCE) // 左儿子 if (height(t.left.left) >= height(t.left.right)) t = rotateWithLeftChild(t); // 左儿子的左子树(单旋转) else t = doubleWithLeftChild(t); // 左儿子的右子树(双旋转) else if (height(t.right) - height(t.left) > ALLOWED_IMBALANCE) // 右儿子 if (height(t.right.right) >= height(t.right.left)) t = rotateWithRightChild(t); // 右儿子的右子树(单旋转) else t = doubleWithRightChild(t); // 右儿子的左子树(双旋转) t.height = Math.max(height(t.left), height(t.right)) + 1; // 更新二叉树高度 return t; } /* * 二叉树高度--树null,高度为-1 */ private int height(Node<Item> t) { return t == null ? -1 : t.height; } /* * 把左边的树变成右边的树 */ private Node<Item> rotateWithLeftChild(Node<Item> k2) { Node<Item> k1 = k2.left; k2.left = k1.right; k1.right = k2; // k1 变为根 k2.height = Math.max(height(k2.left), height(k2.right)) + 1; // k2 高度 k1.height = Math.max(height(k1.left), k2.height) + 1; // 根k1 高度 return k1; } /* * 右边的树变为左边的树 */ private Node<Item> rotateWithRightChild(Node<Item> k1) { Node<Item> k2 = k1.right; k1.right = k2.left; k2.left = k1; k1.height = Math.max(height(k1.left), height(k1.right)) + 1; k2.height = Math.max(height(k2.right), k1.height) + 1; return k2; } /* * 左儿子的右子树 */ private Node<Item> doubleWithLeftChild(Node<Item> k3) { k3.left = rotateWithRightChild(k3.left); return rotateWithLeftChild(k3); } /* * 右儿子的左子树 */ private Node<Item> doubleWithRightChild(Node<Item> k1) { k1.right = rotateWithLeftChild(k1.right); return rotateWithRightChild(k1); } /* * 检查二叉树是否平衡 */ public void checkBalance() { checkBalance(root); } private int checkBalance(Node<Item> t) { if (t == null) return -1; if (t != null) { int hl = checkBalance(t.left); int hr = checkBalance(t.right); if (Math.abs(height(t.left) - height(t.right)) > 1 || height(t.left) != hl || height(t.right) != hr) System.out.println("不平衡"); } return height(t); }}
一点一点补充吧
-
1 0
- 平衡二叉树(AVL)代码笔记
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- AVL(平衡二叉树)(含代码)
- 手写代码 AVL 二叉平衡树(插入 删除)
- AVL平衡二叉树图+代码详解
- 算法学习笔记(七) 平衡二叉树 AVL树
- AVL树(二叉平衡树)笔记
- 平衡二叉树AVL的笔记
- 平衡二叉树AVL的笔记
- [学习笔记]AVL平衡二叉树
- AVL 平衡二叉树
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- AVL 平衡二叉树
- avl平衡二叉树
- 二叉平衡树AVL
- 使用xshell下载sz,上传文件 rz
- 关于C#中抽象类的一些感想
- Win10安装火狐浏览器,点击标签页会自动关闭当前页面的问题
- Java拆装箱问题
- 最大子序列问题
- 平衡二叉树(AVL)代码笔记
- C语言中内存分配
- 第一次面试失败总结
- 目前找到的硬盘安装最简单的方法
- 一个C#代码优化的案例
- 一个hive小案例:使用HIVE进行单词统计, 并把结果存入mysql
- MAC下安装与配置MySQL
- 关于tomcat配置下server location在部署项目后不能修改的问题
- ubuntu16.04 + caffe +python