【墨鳌】【数据结构】【AVL树】
2022/4/8 23:21:39
本文主要是介绍【墨鳌】【数据结构】【AVL树】,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
AVL Tree
- 在 Binary Search Tree 现有属性之上,依赖于可以其二分查找的特性,进行树高的调整优化
- 在每个节点多维护一个子树高度(
height
)的信息 - 每次
insert/remove
时,按照限制条件,动态旋转,以满足任意节点的平衡因子的绝对值 \(<=1\)
节点属性
- key - 可以比较的对象类型
- left,right - 左右儿子节点
- height - 子树高度
public class AVLNode<Key> { public Key key; public AVLNode<Key> left, right; int height; ... }
AVLTree 核心部分
- root - 根节点
- insert - 插入 key
- remove - 移除 key
- balance - 姿态调整
姿态调整
LL型姿态:X右旋
RR型姿态:X左旋
LR型姿态:Y左旋 再 X右旋
RL型姿态:Y右旋 再 X左旋
测试与使用
- 结合上一篇文章
- 与 BST 对比测试
package trees; import trees.objects.AVLTree; import trees.objects.BinaryTree; import java.util.Arrays; import java.util.List; public class Tests { public static void main(String[] args) { AVLTree<Integer> avl=new AVLTree<>(); BinaryTree<Integer,Integer> bst=new BinaryTree<>(); List<Integer> keys = Arrays.asList(1, 19, 30, 36, 50, 89, 101, 40, 90, 105, 103); for (int key : keys) { bst.put(key,key); avl.insert(key); System.out.println("BST:"); bst.printTree(); System.out.println("AVL Tree:"); avl.printTree(); System.out.println("**************************************"); } } }
完整Java代码实现
点击此处,访问GitHub代码仓库
public class AVLTree<T extends Comparable<T>> { private static final int MAX_HEIGHT_DIFFERENCE = 1; private AVLNode<T> root; public class AVLNode<Key> { public Key key; public AVLNode<Key> left, right; int height; public AVLNode(Key key, AVLNode<Key> left, AVLNode<Key> right) { this.key = key; this.left = left; this.right = right; this.height = 1; } } public AVLTree() { root = null; } public AVLTree(T... keys) { if (keys == null || keys.length < 1) { throw new NullPointerException(); } root = new AVLNode<>(keys[0], null, null); for (int i = 1; i < keys.length && keys[i] != null; i++) { root = insert(root, keys[i]); } } public T find(T key) { if (key == null || root == null) { return null; } return find(root, key, key.compareTo(root.key)); } private T find(AVLNode<T> node, T key, int cmp) { if (node == null) { return null; } if (cmp == 0) { return node.key; } return find( (node = cmp > 0 ? node.right : node.left), key, node == null ? 0 : key.compareTo(node.key)); } public void insert(T key) { if (key == null) { throw new NullPointerException(); } root = insert(root, key); } private AVLNode<T> insert(AVLNode<T> node, T key) { if (node == null) { return new AVLNode<>(key, null, null); } int cmp = key.compareTo(node.key); if (cmp == 0) { return node; } if (cmp < 0) { node.left = insert(node.left, key); } else { node.right = insert(node.right, key); } if (Math.abs(height(node.left) - height(node.right)) > MAX_HEIGHT_DIFFERENCE) { node = balance(node); } refreshHeight(node); return node; } private int height(AVLNode<T> node) { if (node == null) { return 0; } return node.height; } private void refreshHeight(AVLNode<T> node) { node.height = Math.max(height(node.left), height(node.right)) + 1; } private AVLNode<T> balance(AVLNode<T> node) { AVLNode<T> node1, node2; // ll if (height(node.left) > height(node.right) && height(node.left.left) >= height(node.left.right)) { node1 = node.left; node.left = node1.right; node1.right = node; refreshHeight(node); return node1; } // lr if (height(node.left) > height(node.right) && height(node.left.right) > height(node.left.left)) { node1 = node.left; node2 = node.left.right; node.left = node2.right; node1.right = node2.left; node2.left = node1; node2.right = node; refreshHeight(node); refreshHeight(node1); return node2; } // rr if (height(node.right) > height(node.left) && height(node.right.right) >= height(node.right.left)) { node1 = node.right; node.right = node1.left; node1.left = node; refreshHeight(node); return node1; } // rl if (height(node.right) > height(node.left) && height(node.right.left) > height(node.right.right)) { node1 = node.right; node2 = node.right.left; node.right = node2.left; node1.left = node2.right; node2.left = node; node2.right = node1; refreshHeight(node); refreshHeight(node1); return node2; } return node; } public void remove(T key) { if (key == null) { throw new NullPointerException(); } root = remove(root, key); } private AVLNode<T> remove(AVLNode<T> node, T key) { if (node == null) { return null; } int cmp = key.compareTo(node.key); if (cmp < 0) { node.left = remove(node.left, key); } if (cmp > 0) { node.right = remove(node.right, key); } if (cmp == 0) { if (node.left == null || node.right == null) { return node.left == null ? node.right : node.left; } T successorKey = successorOf(node).key; node = remove(node, successorKey); node.key = successorKey; } if (Math.abs(height(node.left) - height(node.right)) > MAX_HEIGHT_DIFFERENCE) { node = balance(node); } refreshHeight(node); return node; } private AVLNode<T> successorOf(AVLNode<T> node) { if (node == null) { throw new NullPointerException(); } if (node.left == null || node.right == null) { return node.left == null ? node.right : node.left; } return height(node.left) > height(node.right) ? findMax(node.left, node.left.right, node.left.right == null) : findMin(node.right, node.right.left, node.right.left == null); } private AVLNode<T> findMax(AVLNode<T> node, AVLNode<T> right, boolean rightIsNull) { if (rightIsNull) { return node; } return findMax((node = right), node.right, node.right == null); } private AVLNode<T> findMin(AVLNode<T> node, AVLNode<T> left, boolean leftIsNull) { if (leftIsNull) { return node; } return findMin((node = left), node.left, node.left == null); } // -------------------------- Print Tree -------------------------- private void printTree(AVLNode node, String prefix, boolean isLeft) { if (node == null) { System.out.println("Empty tree"); return; } if (node.right != null) { printTree(node.right, prefix + (isLeft ? "│ " : " "), false); } System.out.println(prefix + (isLeft ? "└── " : "┌── ") + node.key); if (node.left != null) { printTree(node.left, prefix + (isLeft ? " " : "│ "), true); } } private void printTree(AVLNode node) { printTree(node, "", true); } public void printTree() { System.out.println(" >> START TO PRINT THE TREE:"); printTree(root); System.out.println(" << END TO PRINT THE TREE"); } }
这篇关于【墨鳌】【数据结构】【AVL树】的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-28一步到位:购买适合 SEO 的域名全攻略
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign学习入门:轻松掌握微服务通信
- 2024-12-27OpenFeign学习入门:轻松掌握微服务间的HTTP请求
- 2024-12-27JDK17新特性学习入门:简洁教程带你轻松上手
- 2024-12-27JMeter传递token学习入门教程
- 2024-12-27JMeter压测学习入门指南
- 2024-12-27JWT单点登录学习入门指南
- 2024-12-27JWT单点登录原理学习入门