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.测试结果截图

AVL树(C++&Java)的更多相关文章

  1. AVL树之 Java的实现

    AVL树的介绍 AVL树是高度平衡的而二叉树.它的特点是:AVL树中任何节点的两个子树的高度最大差别为1. 上面的两张图片,左边的是AVL树,它的任何节点的两个子树的高度差别都<=1:而右边的不 ...

  2. AVL树的JAVA实现及AVL树的旋转算法

    1,AVL树又称平衡二叉树,它首先是一颗二叉查找树,但在二叉查找树中,某个结点的左右子树高度之差的绝对值可能会超过1,称之为不平衡.而在平衡二叉树中,任何结点的左右子树高度之差的绝对值会小于等于 1. ...

  3. AVL树的Java实现

    AVL树:平衡的二叉搜索树,其子树也是AVL树. 以下是我实现AVL树的源码(使用了泛型): import java.util.Comparator; public class AVLTree< ...

  4. AVL树(三)之 Java的实现

    概要 前面分别介绍了AVL树"C语言版本"和"C++版本",本章介绍AVL树的Java实现版本,它的算法与C语言和C++版本一样.内容包括:1. AVL树的介绍 ...

  5. 数据结构——二叉查找树、AVL树

    二叉查找树:由于二叉查找树建树的过程即为插入的过程,所以其中序遍历一定为升序排列! 插入:直接插入,插入后一定为根节点 查找:直接查找 删除:叶子节点直接删除,有一个孩子的节点删除后将孩子节点接入到父 ...

  6. AVL树原理及实现(C语言实现以及Java语言实现)

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. AVL定义 AVL树是一种改进版的搜索二叉树.对于一般的搜索二叉树而言,如果数据恰好 ...

  7. AVL树----java

                                                                                        AVL树----java AVL ...

  8. 【Java】 大话数据结构(12) 查找算法(3) (平衡二叉树(AVL树))

    本文根据<大话数据结构>一书及网络资料,实现了Java版的平衡二叉树(AVL树). 平衡二叉树介绍 在上篇博客中所实现的二叉排序树(二叉搜索树),其查找性能取决于二叉排序树的形状,当二叉排 ...

  9. Java数据结构和算法(七)--AVL树

    在上篇博客中,学习了二分搜索树:Java数据结构和算法(六)--二叉树,但是二分搜索树本身存在一个问题: 如果现在插入的数据为1,2,3,4,5,6,这样有序的数据,或者是逆序 这种情况下的二分搜索树 ...

随机推荐

  1. 如何提高程序员的键盘使用效率?——ASE第一次作业

    引言 对于程序员来说,键盘输入是我们工作的基本方式,当你的手指在键盘上飞起来的时候,不但能够提高工作效率,还常常引来旁人羡慕的目光.下面将从不同方面介绍一些提高键盘使用效率的方法. 程序员最主要的文字 ...

  2. [转载]桥接与NAT

    NAT相当于是局域网中的局域网,把192.168.21.1当作外网ip,重新划分了一个网关(192.168.33.x) 网桥只是把网络桥接起来,还是原来的网关(192.168.21.x),虚拟机相当于 ...

  3. Python爬虫入门教程之BeautifulSoup

    模块安装 pip3 install beautifulsoup4 模块导入 from bs4 import BeautifulSoup 示例html内容 RPC是一种比较流行的RPC通信框架,由谷歌公 ...

  4. windows下 安装gitlab及其相关图形管理工具

    windows下 安装gitlab及其相关图形管理工具   在windows下安装git中文版客户端并连接gitlab   下载git Windows客户端 git客户端下载地址:https://gi ...

  5. 利用Python进行数据分析_Pandas_基本功能

    申明:本系列文章是自己在学习<利用Python进行数据分析>这本书的过程中,为了方便后期自己巩固知识而整理. 第一 重新索引 Series的reindex方法 In [15]: obj = ...

  6. Python使用datetime来判断近七天

    目录 strptime 使用strptime来格式化字符串 datetime.datetime.strptime("2019-10-02", "%Y-%m-%d" ...

  7. Nginx学习笔记(四):基本数据结构

    目录 Nginx的一些特点 Nginx自定义整数类型 异常机制错误处理 内存池 字符串 时间与日期 运行日志   Nginx的一些特点 高性能 采用事件驱动模型,可以无阻塞的处理海量并发连接 高稳定性 ...

  8. msyql 去重

    delete from userinfo where busi_id in (select busi_id from (select busi_id from userinfo group by bu ...

  9. JS强制关闭浏览器页签并且不提示关闭信息

    工作中很多奇葩的需求都会出现,现在就有一个问题,描述如下: 现在的登录跳转权限页面要去掉,集成在第三方系统信息上,当退出登录的时候需要关掉打开的Tab页面,因此考虑使用window.close()关闭 ...

  10. deferred.promise.then().then()异步链式操作(Chain operation)

    //deferred.promise.then().then() deferred.promise.then(function () { console.log('1 resolve'); retur ...