基础算法-AVL平衡二叉树(五)

基础算法-AVL平衡二叉树(五)

一路学习下来才发现,算法是最难学的东西,其他什么jvm,jdk源码啊,看起来都比较简单。这里写的文章并不好,因为很多分析都是参照网上博客的,没有太多自己的东西,所以只有代码,介绍部分很少,分析部分没有。想要了解更多分析方面的知识请参看下面给出的参考地址。

普通树很容易不平衡,比如随便插入一个1,2,3……10就会发现,全部偏向了右边,就和单链表差不多了,这个时候我们通过一种手段来保证树的平衡。比如,红黑树,B+树,AVL树,都是平衡树。

AVL树的定义

来源:平衡二叉树是G.M. Adelson-Velsky 和 E.M. Landis在1962年在论文中发表的,因此又叫AVL树。
定义:一棵AVL树是其每个结点的左子树和右子树的高度最多相差1的二叉查找树(空树的高度为-1),这个差值也称为平衡因子,所以AVL树每个节点都多了一个参数—高度。

导致AVL树不平衡的原因?

  1. 在结点X的左孩子结点的左子树中插入元素
  2. 在结点X的左孩子结点的右子树中插入元素
  3. 在结点X的右孩子结点的左子树中插入元素
  4. 在结点X的右孩子结点的右子树中插入元素

解决问题:
1,4是同一类问题,我们只需要:左左右旋转,右右左旋转即可。
2,3是同一类问题,我们只需要:左右插入,左,右旋转;右左插入,右,左旋转。(不要颠倒旋转次序哦)

代码实现


/** * AVL二叉树(平衡二叉树): 一棵AVL树是其每个结点的左子树和右子树的高度最多相差1的二叉查找树(空树的高度为-1),这个差值也称为平衡因子 * 参考地址:http://blog.csdn.net/javazejian/article/details/53892797 * bww */
public class AVLBinaryTree {


    private TreeNode root = null;


    //左旋转
    public TreeNode rightRightLeftRotate(TreeNode node) {
        TreeNode w = node.rightChild;
        node.rightChild = w.leftChild;
        w.leftChild = node;
        node.height = Math.max(getNodeHeight(node.leftChild), getNodeHeight(node.rightChild)) + 1;
        w.height = Math.max(getNodeHeight(w.leftChild), getNodeHeight(w.rightChild)) + 1;
        return w;
    }

    //右旋转
    public TreeNode leftLeftRightRotate(TreeNode node) {
        TreeNode w = node.leftChild;
        node.leftChild = w.rightChild;
        w.rightChild = node;
        node.height = Math.max(getNodeHeight(node.leftChild), getNodeHeight(node.rightChild)) + 1;
        w.height = Math.max(getNodeHeight(w.leftChild), getNodeHeight(w.rightChild)) + 1;
        return w;
    }

    //左右插入,先左后右
    public TreeNode doubleRotateWithLeftRight(TreeNode node) {
        node.leftChild = rightRightLeftRotate(node.leftChild);
        return leftLeftRightRotate(node);
    }

    //右左插入,先右后左
    public TreeNode doubleRotateWithRightLeft(TreeNode node) {
        node.rightChild = leftLeftRightRotate(node.rightChild);
        return rightRightLeftRotate(node);
    }


    public void insert(int data) {
        root = insert(data, root);
    }

    public TreeNode insert(int data, TreeNode node) {
        if (node == null) {
            node = new TreeNode(data);
        } else {
            //左
            if (data < node.value) {
               //左插入
                node.leftChild = insert(data, node.leftChild);
                if (getNodeHeight(node.leftChild) - getNodeHeight(node.rightChild) == 2) {
                    //左左,右旋转
                    if (data < node.leftChild.value) {
                        node = leftLeftRightRotate(node);
                    } else {
                        //左右,左右旋转
                        node = doubleRotateWithLeftRight(node);
                    }
                }

            } else {
                node.rightChild = insert(data, node.rightChild);
                if (getNodeHeight(node.rightChild) - getNodeHeight(node.leftChild) == 2) {
                    //右右,左旋转
                    if (data > node.rightChild.value) {
                        node = rightRightLeftRotate(node);
                    } else {
                        //右左,右左旋转
                        node = doubleRotateWithRightLeft(node);
                    }
                }
            }
        }
        node.height = Math.max(getNodeHeight(node.leftChild), getNodeHeight(node.rightChild)) + 1;
        return node;
    }





    public Integer find(int value) {
        TreeNode currentNode = root;
        if (currentNode == null) {
            return null;
        }
        Integer temp;
        while ((temp = currentNode.value) != value) {
            System.out.println("pass=" + temp);

            if (temp > value) {
                currentNode = currentNode.rightChild;
            } else {
                currentNode = currentNode.leftChild;
            }
            if (currentNode == null) {
                return null;
            }
        }
        return temp;
    }


    //中序遍历,这样遍历出来的数据是递增的,从小到大
    public void inOrder(TreeNode currentNode) {
        if (currentNode != null) {
            inOrder(currentNode.leftChild);
            System.out.println("---" + currentNode.value);
            inOrder(currentNode.rightChild);
        }
    }

    int count = 15;

    //前序遍历,这样遍历出来的数据是
    public void printlnOrder(TreeNode currentNode, boolean point) {

        if (currentNode != null) {
            if (point) {
                count++;
            } else {
                count--;
            }
            String k = " ";
            for (int i = 0; i < count; i++) {
                k += " ";
            }
            System.out.println(k + currentNode.value);
            printlnOrder(currentNode.leftChild, false);


            printlnOrder(currentNode.rightChild, true);
        }
    }

    public void spanFirst(TreeNode root) {
        System.out.println("--广度优先---");
        if (root == null) {
            return;
        }
        LinkedList<TreeNode> linkedList = new LinkedList<TreeNode>();
        linkedList.offer(root);

        while (linkedList.size() > 0) {
            TreeNode node = linkedList.poll();//出队列,队列先进先出,记住:出队列后元素就会被废弃掉哦。这就是出队列。
            System.out.println(node.value);
            if (node.leftChild != null) {
                linkedList.offer(node.leftChild);
            }
            if (node.rightChild != null) {
                linkedList.offer(node.rightChild);
            }
        }

    }

    public int getNodeHeight(TreeNode node) {
        if (node == null) {
            return 0;
        }
        int leftHeight = getNodeHeight(node.leftChild);
        int rightHeight = getNodeHeight(node.rightChild);
        return Math.max(leftHeight, rightHeight) + 1;
    }


    private class TreeNode {
        private int value;
        private int height;//当前结点的高度

        private TreeNode leftChild = null;
        private TreeNode rightChild = null;


        public TreeNode(int value) {
            this.value = value;
            this.leftChild = null;
            this.rightChild = null;
        }
    }

    public static void main(String[] args) {
        AVLBinaryTree tree = new AVLBinaryTree();
        for (int i = 1; i <= 10; i++) {
            tree.insert(i);
        }
        tree.printlnOrder(tree.root, false);

        tree.spanFirst(tree.root);

        System.out.println("tree height----");
        System.out.println(tree.getNodeHeight(tree.root));


    }


}

1-10顺序插入后的效果图:
《基础算法-AVL平衡二叉树(五)》

动态演示网站:http://www.cs.usfca.edu/~galles/visualization/AVLtree.html

参考

http://blog.csdn.net/javazejian/article/details/53892797

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/piaoslowly/article/details/81870606
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞