バランスの取れたバイナリツリー(バランス探索木)

 

バランスの取れたバイナリツリー(AVL木)

(バイナリ・ソートツリーは、問題を示すことができる)場合を見てください

既存のBST分析の上に:

  1. すべての左部分木は、ビューの正式な観点から、より多くの単独リンクリストのように、空です。

  2. 挿入速度は効果がありません

  3. (ターン必要に比べて)クエリの速度が大幅に低下し、BSTを再生することはできません

基本的な導入

  1. バランスの取れたバイナリツリーもバランスと呼ばれる二分探索木が高いクエリの効率を確保することができ、また、AVLツリーとして知られている(平衡二分探索木)。

  2. それは空のツリーまたは1以下の左と右の部分木の高さの差の絶対値であり、左右のサブツリーは:それは、次のような特徴を有しています。

バランスの取れたバイナリツリー。平衡二分木を達成するために使用される方法は、赤黒木、AVL、身代わりツリー、Treap、スプレー木などを有しています。

アプリケーション - 一回転(左回転)

//左旋转方法



private void leftRotate() {





//创建新的结点,以当前根结点的值



Node newNode = new Node(value);



//把新的结点的左子树设置成当前结点的左子树



newNode.left = left;



//把新的结点的右子树设置成带你过去结点的右子树的左子树



newNode.right = right.left;



//把当前结点的值替换成右子结点的值



value = right.value;



//把当前结点的右子树设置成当前结点右子树的右子树



right = right.right;



//把当前结点的左子树(左子结点)设置成新的结点



left = newNode;



}

アプリケーション - 一回転(右回転)

//右旋转



private void rightRotate() {



Node newNode = new Node(value); 

newNode.right = right; 

newNode.left = left.right;

value = left.value; 

left = left.left; 

right = newNode;

}

アプリケーション - ダブル回転

解析ソリューション

  1. 右の条件に沿って回転させたとき

  2. その高さは左のサブツリーより右の部分木は高さのその左部分木に大きい場合は

  3. まず、現在のノードの左ノードが残っている回転

  4. 現在のノードの右回転操作することが

コードの実装[コード(完全なコード)のAVL木の概要]

package com.kyrie.avl;



public class AVLTreeDemo {



    public static void main(String[] args) {

//        int[] arr = { 4, 3, 6, 5, 7, 8 };

        int[] arr = { 10, 11, 7, 6, 8, 9 };



        // AVLTree

        AVLTree avlTree = new AVLTree();

        // 添加节点

        for (int i = 0; i < arr.length; i++) {

            avlTree.add(new Node(arr[i]));

        }



        // 遍历

        System.out.println("中序遍历");

        avlTree.infixOrder();



        System.out.println("平衡处理后:");

        System.out.println("树高 = " + avlTree.getRoot().height());

        System.out.println("左子树高度 = " + avlTree.getRoot().leftHeight());

        System.out.println("右子树高度 = " + avlTree.getRoot().rightHeight());

        System.out.println("根节点为 = " + avlTree.getRoot());



    }



}



//创建AVL树    AVL:平衡二叉树 (平衡查找树)

class AVLTree {

    private Node root;// 根节点



    public Node getRoot() {

        return root;

    }



    // 添加节点的方法

    public void add(Node node) {

        if (root == null) {

            root = node;

        } else {

            root.add(node);

        }

    }



    // 中序遍历

    public void infixOrder() {

        if (root != null) {

            root.infixOrder();

        } else {

            // 此树为空

            System.out.println("此树为空,无法遍历");

        }

    }



}



class Node {

    int value; // 当前节点的值

    Node left; // 左孩子

    Node right; // 右孩子



    public Node(int value) {

        this.value = value;

    }



    @Override

    public String toString() {

        return "Node [value = " + value + "]";

    }



    // 左子树树高

    public int leftHeight() {

        if (left == null) {

            return 0;

        }

        return left.height();

    }



    // 右子树树高

    public int rightHeight() {

        if (right == null) {

            return 0;

        }

        return right.height();

    }



    // 得到树高

    public int height() {

        return Math.max(left == null ? 0 : left.height(), right == null ? 0 : right.height()) + 1;

    }



    // 左旋转方法

    private void leftRotate() {

        // 创建心得节点,值为当前树的根节点的值

        Node newNode = new Node(value);

        // 把新的节点的左孩子设置成当前节点的左孩子

        newNode.left = left;

        // 把新的节点的右孩子设置成当前节点的右孩子的左孩子

        newNode.right = right.left;

        // 把当前节点的值替换成右孩子的值

        value = right.value;

        // 把当前节点的右孩子设置成当前节点右孩子的右孩子

        right = right.right;

        // 把当前节点的左孩子设置成新的节点

        this.left = newNode;

    }



    // 右旋转方法

    private void rightRotate() {

        Node newNode = new Node(value);

        newNode.right = right;

        newNode.left = left.right;

        value = left.value;

        left = left.left;

        this.right = newNode;

    }



    // 添加节点的方法

    // 递归实现,且需要满足二叉查找树的特点,左子树全小于根节点,右子树全大于根节点

    public void add(Node node) {

        if (node == null) {

            return;

        }

        // 判断传入节点的值与当前子树的根节点的值的关系

        if (node.value < this.value) {// 向左子树深入

            if (this.left == null) {// 当前根节点尚未有左孩子

                this.left = node;

            } else {

                // 递归地向左子树添加

                this.left.add(node);

            }

        } else {// 向右子树深入

            if (this.right == null) {// 当前根节点尚未有右孩子

                this.right = node;

            } else {

                // 递归地向右子树添加

                this.right.add(node);

            }

        }



        // 判断是否满足AVL的定义 : 左右子树的高度差的绝对值不能超过1

        // 1.左旋转 : 右子树高度 - 左子树高度 > 1

        if ((rightHeight() - leftHeight()) > 1) {

            // 根节点的右孩子的 左子树的高度 > 根节点的右孩子的右子树高度

            if (right != null && right.leftHeight() > right.rightHeight()) {

                // 先进行右旋转

                right.rightRotate();

                // 再对根节点进行左旋转

                leftRotate();

            } else {

                // 直接进行左旋转

                leftRotate();

            }



            return; // 很关键,假如这个已经旋转过了,直接返回就可以了,避免节外生枝

        }



        // 2 右旋转 : 左子树高度 - 右子树高度 > 1

        if ((leftHeight() - rightHeight()) > 1) {

            if (left != null && left.rightHeight() > right.leftHeight()) {

                left.leftRotate();



                rightRotate();

            } else {

                rightRotate();

            }



        }



    }



    // 中序遍历

    public void infixOrder() {

        if (this.left != null) {

            this.left.infixOrder();

        }

        System.out.println(this);

        if (this.right != null) {

            this.right.infixOrder();

        }

    }



}

 

 

おすすめ

転載: www.cnblogs.com/kyrie211/p/10994772.html