zoukankan      html  css  js  c++  java
  • AVL树(C++&Java)

    AVL Tree精讲专题

    前言

    因为AVL树之前写过一次,但是感觉左右旋转弄反了,这次重新整理了下,参照数据结构——陈越著,分别进行列举c++版本的AVL树和Java版本的AVL树,供参考和互相学习。图片来源,我们老师的PPT。

    一、AVL Tree for CPP(Coding)

    1.AVL树原型

    C++ coding:

    //AVL节点,一个左子树,一个右子树
    struct node{
        int val;
        struct node *left,*right;
    };
    

    Java coding:

    /**
     * AVL节点类
     */
    public class AVLNode<T extends Comparable> {
        public T val;
        public AVLNode left;
        public AVLNode right;
    
        /**
         * constructor
         * @param val
         */
        public AVLNode(T val) {
            this.val = val;
        }
    }
    

    2.旋转的四种方式

    1.singleLeftRotation LL旋转

    将3,2节点对换,但是,要注意,2节点右子树可能有其他树

    C++ coding:

    node *singleLeftRotation(node *root){
        node *t=root->left;
        root->left=t->right;
        t->right=root;
        return t;
    }
    

    Java coding:

    /**
     * 左单旋
     * @param root
     * @return
     */
    public AVLNode singleLeftRotation(AVLNode root){
        AVLNode t=root.left;
        root.left=t.right;
        t.right=root;
        return t;
    }
    
    2.singleRightRotation RR旋转

    将1,2节点对换,但是,要注意,2节点左子树可能有其他树

    C++ coding:

    node *singleRightRotation(node *root){
        node *t=root->right;
        root->right=t->left;
        t->left=root;
        return t;
    }
    

    Java coding:

    /**
     * 右单旋
     * @param root
     * @return
     */
    public AVLNode singleRightRotation(AVLNode root){
        AVLNode t=root.right;
        root.right=t.left;
        t.left=root;
        return t;
    }
    
    3.doubleLeftRightRotation LR旋转

    注意双旋转,先进行下方节点旋转,所以,首先,1,2进行RR旋转,之后对3和3的左子树进行LL旋转。

    C++ coding:

    node *doubleLeftRightRotation(node *root){
        root->left=singleRightRotation(root->left);
        return singleLeftRotation(root);
    }
    

    Java coding:

    /**
     * 左右双旋
     * @param root
     * @return
     */
    public AVLNode doubleLeftRightRotation(AVLNode root){
        root.left=singleRightRotation(root.left);
        return singleLeftRotation(root);
    }
    
    4.doubleRightLeftRotation RL旋转

    首先,2,3进行LL旋转,之后对1和1的右子树进行LL旋转。

    C++ coding:

    node *doubleRightLeftRotation(node *root){
        root->right=singleLeftRotation(root->right);
        return singleRightRotation(root);
    }
    
    

    Java coding:

    /**
     * 右左双旋
     * @param root
     * @return
     */
    public AVLNode doubleRightLeftRotation(AVLNode root){
        root.right=singleLeftRotation(root.right);
        return singleRightRotation(root);
    }
    
    

    插入代码

    我们插入时,首先判断是否是空树,是空树就进行填充。之后进行左右递归插入(与BST树插入效果一样),紧接着我们需要进行一次判断,在左侧插入时,如果插入值比左孩子值还要小,那么,是LL了,进行LL旋转,如果比左孩子值大,那么进行LR旋转。右侧插入同理。

    C++ coding:

    node *insert(node *root,int val){
        if(root==NULL){
            root=new node();
            root->val=val;
            root->left=NULL;
            root->right=NULL;
        }else if(val<root->val){
            root->left=insert(root->left,val);
            if(getHeight(root->left)-getHeight(root->right)==2)
                root=val<root->left->val ? singleLeftRotation(root):doubleLeftRightRotation(root);
        }else{
            root->right=insert(root->right,val);
            if(getHeight(root->left)-getHeight(root->right)==-2)
                root=val>root->right->val ? singleRightRotation(root):doubleRightLeftRotation(root);
        }
        return root;
    }
    
    

    Java coding:

    /**
     * 插入方法
     * @param val 插入变量
     */
    public void insert(T val){
        root=insert(root,val);
    }
    
    /**
     * 插入辅助方法
     * @param root
     * @param val
     * @return
     */
    private AVLNode<T> insert(AVLNode root, T val) {
        if(root==null){
            //空树插入
            root=new AVLNode(val);
        }else if(val.compareTo(root.val)<0){
            //小于根进行左插入
            root.left=insert(root.left,val);
            //旋转操作
            if((getHeight(root.left)-getHeight(root.right))==2){
                root=val.compareTo(root.left.val)<0 ? singleLeftRotation(root):doubleLeftRightRotation(root);
            }
        }else{
            //大于根进行右插入
            root.right=insert(root.right,val);
            //旋转操作
            if((getHeight(root.left)-getHeight(root.right))==-2) {
                root = val.compareTo(root.right.val) > 0 ? singleRightRotation(root) : doubleRightLeftRotation(root);
            }
        }
        return root;
    }
    
    

    二、完整版AVL Tree的CPP和JAVA实现

    AVL Tree CPP FULL Coding

    这边加入了先序遍历和高度检测,代码可直接运行。

    #include <iostream>
    
    using namespace std;
    
    struct node{
        int val;
        struct node *left,*right;
    };
    
    node *singleLeftRotation(node *root){
        node *t=root->left;
        root->left=t->right;
        t->right=root;
        return t;
    }
    
    node *singleRightRotation(node *root){
        node *t=root->right;
        root->right=t->left;
        t->left=root;
        return t;
    }
    
    node *doubleLeftRightRotation(node *root){
        root->left=singleRightRotation(root->left);
        return singleLeftRotation(root);
    }
    
    node *doubleRightLeftRotation(node *root){
        root->right=singleLeftRotation(root->right);
        return singleRightRotation(root);
    }
    
    int getHeight(node *root){
        if(root==NULL) return 0;
        return max(getHeight(root->left),getHeight(root->right))+1;
    }
    
    node *insert(node *root,int val){
        if(root==NULL){
            root=new node();
            root->val=val;
            root->left=NULL;
            root->right=NULL;
        }else if(val<root->val){
            root->left=insert(root->left,val);
            if(getHeight(root->left)-getHeight(root->right)==2)
                root=val<root->left->val ? singleLeftRotation(root):doubleLeftRightRotation(root);
        }else{
            root->right=insert(root->right,val);
            if(getHeight(root->left)-getHeight(root->right)==-2)
                root=val>root->right->val ? singleRightRotation(root):doubleRightLeftRotation(root);
        }
        return root;
    }
    
    void preOrder(node *root){
        if(root==NULL) return;
        printf("%d ",root->val);
        preOrder(root->left);
        preOrder(root->right);
    }
    int main(){
        int n,val;
        scanf("%d",&n);
        node *root=NULL;
        for(int i=0;i<n;i++){
            scanf("%d",&val);
            root=insert(root,val);
        }
        preOrder(root);
        system("pause");
        return 0;
    }
    
    

    AVL Tree JAVA FULL Coding

    1.AVL节点类
    package test;
    
    /**
     * AVL节点类
     */
    public class AVLNode<T extends Comparable> {
        public T val;
        public AVLNode left;
        public AVLNode right;
    
        /**
         * constructor
         * @param val
         */
        public AVLNode(T val) {
            this.val = val;
        }
    }
    
    
    2.AVL树类
    package test;
    
    /**
     * AVL Tree类
     * 维持平衡的AVL树
     * @param <T>
     */
    public class AVLTree<T extends Comparable> {
    
        public AVLNode<T> root;
    
    /**
     * 插入方法
     * @param val 插入变量
     */
    public void insert(T val){
        root=insert(root,val);
    }
    
    /**
     * 插入辅助方法
     * @param root
     * @param val
     * @return
     */
    private AVLNode<T> insert(AVLNode root, T val) {
        if(root==null){
            //空树插入
            root=new AVLNode(val);
        }else if(val.compareTo(root.val)<0){
            //小于根进行左插入
            root.left=insert(root.left,val);
            //旋转操作
            if((getHeight(root.left)-getHeight(root.right))==2){
                root=val.compareTo(root.left.val)<0 ? singleLeftRotation(root):doubleLeftRightRotation(root);
            }
        }else{
            //大于根进行右插入
            root.right=insert(root.right,val);
            //旋转操作
            if((getHeight(root.left)-getHeight(root.right))==-2) {
                root = val.compareTo(root.right.val) > 0 ? singleRightRotation(root) : doubleRightLeftRotation(root);
            }
        }
        return root;
    }
    
        /**
         * 左单旋
         * @param root
         * @return
         */
        public AVLNode singleLeftRotation(AVLNode root){
            AVLNode t=root.left;
            root.left=t.right;
            t.right=root;
            return t;
        }
    
        /**
         * 右单旋
         * @param root
         * @return
         */
        public AVLNode singleRightRotation(AVLNode root){
            AVLNode t=root.right;
            root.right=t.left;
            t.left=root;
            return t;
        }
    
        /**
         * 左右双旋
         * @param root
         * @return
         */
        public AVLNode doubleLeftRightRotation(AVLNode root){
            root.left=singleRightRotation(root.left);
            return singleLeftRotation(root);
        }
    
        /**
         * 右左双旋
         * @param root
         * @return
         */
        public AVLNode doubleRightLeftRotation(AVLNode root){
            root.right=singleLeftRotation(root.right);
            return singleRightRotation(root);
        }
    
        /**
         * 获取树的高度
         * @param root 传入根节点
         * @return
         */
        private int getHeight(AVLNode root){
            if(root==null) {
                return 0;
            }
            return (getHeight(root.left)>getHeight(root.right) ? getHeight(root.left):getHeight(root.right))+1;
        }
    
        /**
         * 先序遍历
         */
        public void preOrderTraserve(){
            preOrderTraserve(root);
        }
    
        /**
         * 先序遍历辅助方法
         * @param root
         */
        public void preOrderTraserve(AVLNode root){
            if(root==null){
                return;
            }
            System.out.print(root.val+" ");
            preOrderTraserve(root.left);
            preOrderTraserve(root.right);
        }
    }
    
    
    3.测试用例
    package test;
    
    import java.util.Scanner;
    
    public class TestDemo {
        public static void main(String[] args) {
            AVLTree<Integer> avlTree=new AVLTree();
            Scanner sc=new Scanner(System.in);
            System.out.println("输入你要插入节点个数:");
            int num=sc.nextInt();int tmp;
            while(num--!=0){
                tmp=sc.nextInt();
                avlTree.insert(tmp);
            }
            avlTree.preOrderTraserve();
            sc.close();
        }
    }
    
    
    4.测试结果截图

  • 相关阅读:
    【SpringCloud构建微服务系列】分布式链路跟踪Spring Cloud Sleuth
    【算法】LRU算法
    细说分布式锁
    【Python】Python3.4+Matplotlib详细安装教程
    LoRaWAN协议(二)--LoRaWAN MAC数据包格式
    LoRaWAN移植笔记(一)__RTC闹钟链表的实现
    cJSON_json包的C语言解析库
    LoRaWAN协议(一)--架构解析
    STM32L051 PVD的调试
    以帧为存储单位的循环stack
  • 原文地址:https://www.cnblogs.com/littlepage/p/11714512.html
Copyright © 2011-2022 走看看