ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【墨鳌】【数据结构】【AVL树】

2022-04-08 22:03:21  阅读:171  来源: 互联网

标签:node right key null height AVL 墨鳌 数据结构 left


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右旋

image-20220408210427631 image-20220408210725023

RR型姿态:X左旋

image-20220408210131025 image-20220408210817298

LR型姿态:Y左旋 再 X右旋

image-20220408211154186 image-20220408211758142

RL型姿态:Y右旋 再 X左旋

image-20220408211414594 image-20220408211758142

测试与使用

  • 结合上一篇文章
  • 与 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");
    }
}

标签:node,right,key,null,height,AVL,墨鳌,数据结构,left
来源: https://www.cnblogs.com/JasonCow/p/16120013.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有