前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >AVL树—-java

AVL树—-java

作者头像
全栈程序员站长
发布于 2022-07-13 08:37:54
发布于 2022-07-13 08:37:54
75300
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

AVL树—-java

AVL树是高度平衡的二叉查找树

1.单旋转LL旋转

理解记忆:1.在不平衡的节点的左孩子的左孩子插入导致的不平衡,所以叫LL

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private AVLTreeNode<T> leftLeftRotation(AVLTreeNode<T> k2) {
    AVLTreeNode<T> k1;

    k1 = k2.left;
    k2.left = k1.right;
    k1.right = k2;

    k2.height = max( height(k2.left), height(k2.right)) + 1;
    k1.height = max( height(k1.left), k2.height) + 1;

    return k1;
}

2.单旋转RR

理解记忆:1.不平衡节点的右孩子的有孩子插入导致的不平衡,所以叫RR

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private AVLTreeNode<T> rightRightRotation(AVLTreeNode<T> k1) {
    AVLTreeNode<T> k2;

    k2 = k1.right;
    k1.right = k2.left;
    k2.left = k1;

    k1.height = max( height(k1.left), height(k1.right)) + 1;
    k2.height = max( height(k2.right), k1.height) + 1;

    return k2;
}

3.双旋转LR

理解记忆:1.不平衡节点的左孩子的有孩子导致的不平衡,所以叫LR

2.须要先对k1 RR,再对根K3 LL

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private AVLTreeNode<T> leftRightRotation(AVLTreeNode<T> k3) {
    k3.left = rightRightRotation(k3.left);

    return leftLeftRotation(k3);
}

4.双旋转RL

理解记忆:1.不平衡节点的右孩子的左孩子导致的不平衡,所以叫RL

2.须要先对k3 LL,在对k1 RR

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private AVLTreeNode<T> rightLeftRotation(AVLTreeNode<T> k1) {
    k1.right = leftLeftRotation(k1.right);

    return rightRightRotation(k1);
}

5.AVL的样例

遍历,查找等和二叉查找树一样就不在列出,主要是 插入删除

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class AVLTree<T extends Comparable<T>> {
    private AVLTreeNode<T> mRoot;    // 根结点

    // AVL树的节点(内部类)
    class AVLTreeNode<T extends Comparable<T>> {
        T key;                // keyword(键值)
        int height;         // 高度
        AVLTreeNode<T> left;    // 左孩子
        AVLTreeNode<T> right;    // 右孩子

        public AVLTreeNode(T key, AVLTreeNode<T> left, AVLTreeNode<T> right) {
            this.key = key;
            this.left = left;
            this.right = right;
            this.height = 0;
        }
    }

    // 构造函数
    public AVLTree() {
        mRoot = null;
    }

    /*
     * 获取树的高度
     */
    private int height(AVLTreeNode<T> tree) {
        if (tree != null)
            return tree.height;

        return 0;
    }

    public int height() {
        return height(mRoot);
    }

    /*
     * 比較两个值的大小
     */
    private int max(int a, int b) {
        return a>b ? a : b;
    }

    /*
     * 前序遍历"AVL树"
     */
    private void preOrder(AVLTreeNode<T> tree) {
        if(tree != null) {
            System.out.print(tree.key+" ");
            preOrder(tree.left);
            preOrder(tree.right);
        }
    }

    public void preOrder() {
        preOrder(mRoot);
    }

    /*
     * 中序遍历"AVL树"
     */
    private void inOrder(AVLTreeNode<T> tree) {
        if(tree != null)
        {
            inOrder(tree.left);
            System.out.print(tree.key+" ");
            inOrder(tree.right);
        }
    }

    public void inOrder() {
        inOrder(mRoot);
    }

    /*
     * 后序遍历"AVL树"
     */
    private void postOrder(AVLTreeNode<T> tree) {
        if(tree != null) {
            postOrder(tree.left);
            postOrder(tree.right);
            System.out.print(tree.key+" ");
        }
    }

    public void postOrder() {
        postOrder(mRoot);
    }

    /*
     * (递归实现)查找"AVL树x"中键值为key的节点
     */
    private AVLTreeNode<T> search(AVLTreeNode<T> x, T key) {
        if (x==null)
            return x;

        int cmp = key.compareTo(x.key);
        if (cmp < 0)
            return search(x.left, key);
        else if (cmp > 0)
            return search(x.right, key);
        else
            return x;
    }

    public AVLTreeNode<T> search(T key) {
        return search(mRoot, key);
    }

    /*
     * (非递归实现)查找"AVL树x"中键值为key的节点
     */
    private AVLTreeNode<T> iterativeSearch(AVLTreeNode<T> x, T key) {
        while (x!=null) {
            int cmp = key.compareTo(x.key);

            if (cmp < 0)
                x = x.left;
            else if (cmp > 0)
                x = x.right;
            else
                return x;
        }

        return x;
    }

    public AVLTreeNode<T> iterativeSearch(T key) {
        return iterativeSearch(mRoot, key);
    }

    /* 
     * 查找最小结点:返回tree为根结点的AVL树的最小结点。
     */
    private AVLTreeNode<T> minimum(AVLTreeNode<T> tree) {
        if (tree == null)
            return null;

        while(tree.left != null)
            tree = tree.left;
        return tree;
    }

    public T minimum() {
        AVLTreeNode<T> p = minimum(mRoot);
        if (p != null)
            return p.key;

        return null;
    }
     
    /* 
     * 查找最大结点:返回tree为根结点的AVL树的最大结点。
     */
    private AVLTreeNode<T> maximum(AVLTreeNode<T> tree) {
        if (tree == null)
            return null;

        while(tree.right != null)
            tree = tree.right;
        return tree;
    }

    public T maximum() {
        AVLTreeNode<T> p = maximum(mRoot);
        if (p != null)
            return p.key;

        return null;
    }

    /*
     * LL:左左相应的情况(左单旋转)。
     *
     * 返回值:旋转后的根节点
     */
    private AVLTreeNode<T> leftLeftRotation(AVLTreeNode<T> k2) {
        AVLTreeNode<T> k1;

        k1 = k2.left;
        k2.left = k1.right;
        k1.right = k2;

        k2.height = max( height(k2.left), height(k2.right)) + 1;
        k1.height = max( height(k1.left), k2.height) + 1;

        return k1;
    }

    /*
     * RR:右右相应的情况(右单旋转)。
     *
     * 返回值:旋转后的根节点
     */
    private AVLTreeNode<T> rightRightRotation(AVLTreeNode<T> k1) {
        AVLTreeNode<T> k2;

        k2 = k1.right;
        k1.right = k2.left;
        k2.left = k1;

        k1.height = max( height(k1.left), height(k1.right)) + 1;
        k2.height = max( height(k2.right), k1.height) + 1;

        return k2;
    }

    /*
     * LR:左右相应的情况(左双旋转)。
     *
     * 返回值:旋转后的根节点
     */
    private AVLTreeNode<T> leftRightRotation(AVLTreeNode<T> k3) {
        k3.left = rightRightRotation(k3.left);

        return leftLeftRotation(k3);
    }

    /*
     * RL:右左相应的情况(右双旋转)。
     *
     * 返回值:旋转后的根节点
     */
    private AVLTreeNode<T> rightLeftRotation(AVLTreeNode<T> k1) {
        k1.right = leftLeftRotation(k1.right);

        return rightRightRotation(k1);
    }

    /* 
     * 将结点插入到AVL树中,并返回根节点
     *
     * 參数说明:
     *     tree AVL树的根结点
     *     key 插入的结点的键值
     * 返回值:
     *     根节点
     */
    private AVLTreeNode<T> insert(AVLTreeNode<T> tree, T key) {
        if (tree == null) {
            // 新建节点
            tree = new AVLTreeNode<T>(key, null, null);
            if (tree==null) {
                System.out.println("ERROR: create avltree node failed!");
                return null;
            }
        } else {
            int cmp = key.compareTo(tree.key);

               if (cmp < 0) {    // 应该将key插入到"tree的左子树"的情况
                tree.left = insert(tree.left, key);
                // 插入节点后,若AVL树失去平衡,则进行相应的调节。
                if (height(tree.left) - height(tree.right) == 2) {
                    if (key.compareTo(tree.left.key) < 0)
                        tree = leftLeftRotation(tree);
                    else
                        tree = leftRightRotation(tree);
                }
            } else if (cmp > 0) {    // 应该将key插入到"tree的右子树"的情况
                tree.right = insert(tree.right, key);
                // 插入节点后,若AVL树失去平衡,则进行相应的调节。
                if (height(tree.right) - height(tree.left) == 2) {
                    if (key.compareTo(tree.right.key) > 0)
                        tree = rightRightRotation(tree);
                    else
                        tree = rightLeftRotation(tree);
                }
            } else {    // cmp==0
                System.out.println("加入�失败:不同意加入�同样的节点!");
            }
        }

        tree.height = max( height(tree.left), height(tree.right)) + 1;

        return tree;
    }

    public void insert(T key) {
        mRoot = insert(mRoot, key);
    }

    /* 
     * 删除结点(z),返回根节点
     *
     * 參数说明:
     *     tree AVL树的根结点
     *     z 待删除的结点
     * 返回值:
     *     根节点
     */
    private AVLTreeNode<T> remove(AVLTreeNode<T> tree, AVLTreeNode<T> z) {
        // 根为空 或者 没有要删除的节点,直接返回null。
        if (tree==null || z==null)
            return null;

        int cmp = z.key.compareTo(tree.key);
        if (cmp < 0) {        // 待删除的节点在"tree的左子树"中
            tree.left = remove(tree.left, z);
            // 删除节点后,若AVL树失去平衡,则进行相应的调节。
            if (height(tree.right) - height(tree.left) == 2) {
                AVLTreeNode<T> r =  tree.right;
                if (height(r.left) > height(r.right))
                    tree = rightLeftRotation(tree);
                else
                    tree = rightRightRotation(tree);
            }
        } else if (cmp > 0) {    // 待删除的节点在"tree的右子树"中
            tree.right = remove(tree.right, z);
            // 删除节点后,若AVL树失去平衡,则进行相应的调节。
            if (height(tree.left) - height(tree.right) == 2) {
                AVLTreeNode<T> l =  tree.left;
                if (height(l.right) > height(l.left))
                    tree = leftRightRotation(tree);
                else
                    tree = leftLeftRotation(tree);
            }
        } else {    // tree是相应要删除的节点。
            // tree的左右孩子都非空
            if ((tree.left!=null) && (tree.right!=null)) {
                if (height(tree.left) > height(tree.right)) {
                    // 假设tree的左子树比右子树高;
                    // 则(01)找出tree的左子树中的最大节点
                    //   (02)将该最大节点的值赋值给tree。
                    //   (03)删除该最大节点。
                    // 这相似于用"tree的左子树中最大节点"做"tree"的替身;
                    // 採用这样的方式的优点是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
                    AVLTreeNode<T> max = maximum(tree.left);
                    tree.key = max.key;
                    tree.left = remove(tree.left, max);
                } else {
                    // 假设tree的左子树不比右子树高(即它们相等,或右子树比左子树高1)
                    // 则(01)找出tree的右子树中的最小节点
                    //   (02)将该最小节点的值赋值给tree。
                    //   (03)删除该最小节点。
                    // 这相似于用"tree的右子树中最小节点"做"tree"的替身;
                    // 採用这样的方式的优点是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。
                    AVLTreeNode<T> min = maximum(tree.right);
                    tree.key = min.key;
                    tree.right = remove(tree.right, min);
                }
            } else {
                AVLTreeNode<T> tmp = tree;
                tree = (tree.left!=null) ? tree.left : tree.right;
                tmp = null;
            }
        }

        return tree;
    }

    public void remove(T key) {
        AVLTreeNode<T> z; 

        if ((z = search(mRoot, key)) != null)
            mRoot = remove(mRoot, z);
    }

    /* 
     * 销毁AVL树
     */
    private void destroy(AVLTreeNode<T> tree) {
        if (tree==null)
            return ;

        if (tree.left != null)
            destroy(tree.left);
        if (tree.right != null)
            destroy(tree.right);

        tree = null;
    }

    public void destroy() {
        destroy(mRoot);
    }

    /*
     * 打印"二叉查找树"
     *
     * key        -- 节点的键值 
     * direction  --  0,表示该节点是根节点;
     *               -1,表示该节点是它的父结点的左孩子;
     *                1,表示该节点是它的父结点的右孩子。
     */
    private void print(AVLTreeNode<T> tree, T key, int direction) {
        if(tree != null) {
            if(direction==0)    // tree是根节点
                System.out.printf("%2d is root\n", tree.key, key);
            else                // tree是分支节点
                System.out.printf("%2d is %2d's %6s child\n", tree.key, key, direction==1?"right" : "left");

            print(tree.left, tree.key, -1);
            print(tree.right,tree.key,  1);
        }
    }

    public void print() {
        if (mRoot != null)
            print(mRoot, mRoot.key, 0);
    }
}

文章大量參考: http://www.cnblogs.com/skywang12345/p/3577479.html

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/118277.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021年12月,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
linux CentOS7 下 Docker安装
Docker在CentOS安装介绍地址:https://docs.docker.com/install/linux/docker-ce/centos/
Lansonli
2021/10/09
3970
2019年9月23日 Linux学习笔记
Markdown 命令教程
用户6318323
2019/09/23
8380
2019年9月23日 Linux学习笔记
centos7 docker安装详解
查看内核和操作系统版本 [root@prod3 ~]# uname -r 3.10.0-327.el7.x86_64 [root@prod3 ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 1、安装yum源 yum install -y epel-release 2、yum安装docker yum install docker -y 3、启动docker并将其设置为开机启动 systemctl start docker.service
程序员同行者
2018/06/22
6770
1-Docker概述
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
Ywrby
2022/10/27
3570
1-Docker概述
【学习笔记】Docker学习笔记
Docker 安装 # 1、yum 包更新到最新 yum update # 2、安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的 yum install -y yum-utils device-mapper-persistent-data lvm2 # 3、 设置yum源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docke
Karos
2023/02/02
1.3K0
【学习笔记】Docker学习笔记
Linux下Docker的安装及使用
类似于电脑,要在朋友的电脑上跑你写的Java程序,就得检查他电脑有没有安装Java环境.
玖柒的小窝
2021/09/08
9350
Linux下Docker的安装及使用
centos7安装docker
Docker从1.13版本之后采用时间线的方式作为版本号,分为社区版CE和企业版EE。
周小董
2019/03/25
1.2K0
centos7安装docker
Docker入门:Docker安装与基本使用
Docker支持主流的Linux Server、也支持Windows Server,同时为了方便开发者在开发环境中使用Docker,Docker官方也提供了支持Windows以及macOS的Docker Desktop。
KenTalk
2023/04/07
1.6K0
Docker入门:Docker安装与基本使用
【云原生实战】Docker基本概念以及命令实战
Install Docker Engine on CentOS | Docker Documentation
陶然同学
2023/02/27
3350
【云原生实战】Docker基本概念以及命令实战
Docker入门与简单使用
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows机器上。近几年来,Docker 在国内发展的如火如荼,特别是在互联网公司, Docker 的使用是十分普遍的,极大提高了应用的维护效率,降低了云计算应用开发的成本。本篇文章主要是带你入门Docker,介绍Docker的安装及简单使用。
MySQL技术
2019/11/07
6750
docker高级教程_docker到底怎么用
可以看见右侧有docker pull command拉取镜像的命令,以windows为例,打开cmd输入以上命令即可下载docker镜像
全栈程序员站长
2022/11/03
1.4K0
docker高级教程_docker到底怎么用
CentOS7 安装 Docker
使用 cat /etc/os-release 命令查看Linux 发行版名称和版本号
草帽lufei
2022/07/29
3560
CentOS7 安装 Docker
在Centos7上安装Docker
在Centos7上安装Docker-ce直接用yum install docker -y安装的docker版本为1.12,但是docker发展很快,现在都18.03.1了。docker-ce是指docker的社区版。1、安装 yum-utils,它提供了 yum-config-manager,可用来管理yum源yum install -y yum-utils
Dream城堡
2018/09/10
1.4K0
基于Docker构建安装Git/GitLab,以及制作springboot工程镜像
本地离线存储:绝大多数操作都只需要访问本地文件和资源,不用连网,在本地磁盘上就保存着所有当前项目的历史更新,所以处理起来速度飞快。
艾编程
2020/06/10
4.6K0
CentOS 7安装Docker
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
青衫染红尘
2021/01/19
6740
Docker常用命令
学习Docker有段时间了,所有的操作都是在命令行下,如果不是每天都在使用,很容易忘记命令。本文将以学习Docker的角度,从前到后,将一些常用的Docker命令记录下来,算是个备忘。
oec2003
2019/07/19
6050
Docker常用命令
Centos7安装docker18
Docker从1.13版本之后采用时间线的方式作为版本号,分为社区版CE和企业版EE。 社区版是免费提供给个人开发者和小型团体使用的,企业版会提供额外的收费服务,比如经过官方测试认证过的基础设施、容器、插件等。 社区版按照stable和edge两种方式发布,每个季度更新stable版本,如17.06,17.09;每个月份更新edge版本,如17.09,17.10。 1、Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker 。通过 uname -r 命令查看你当前的内核版本 2、使用 root 权限登录 Centos。确保 yum 包更新到最新。 yum update 3、卸载旧版本(如果安装过旧版本的话) yum remove docker  docker-common docker-selinux docker-engine 如果之前已经安装过旧版本的docker 卸载旧版本的包 yum erase docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64 4、安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的 yum install -y yum-utils device-mapper-persistent-data lvm2 5、设置yum源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 6、可以查看所有仓库中所有docker版本,并选择特定版本安装 yum list docker-ce --showduplicates | sort -r 7、安装docker yum install docker-ce  #由于repo中默认只开启stable仓库,故这里安装的是最新稳定版17.12.0 yum install <FQPN>  # 例如:sudo yum install docker-ce-17.12.0.ce 8、启动并加入开机启动 systemctl start docker systemctl enable docker 9、验证安装是否成功(有client和service两部分表示docker安装启动都成功了) docker version
似水的流年
2019/12/06
1K0
docker必会知识(常用)
:Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
编程张无忌
2021/01/26
2.2K0
docker必会知识(常用)
Centos7下安装Docker(详细安装教程)[通俗易懂]
百科说:Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。
全栈程序员站长
2022/07/25
10.5K0
Docker
以前我们开发项目有专门的开发环境,做测试时有测试环境,而产品上线就会有生产环境,这个过程经常要迁移项目,不同的环境配置可能导致不可预估的错误,要经常性的改动
晚上没宵夜
2020/04/30
1.1K1
Docker
相关推荐
linux CentOS7 下 Docker安装
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档