手写AVL平衡二叉搜索树
手写AVL平衡二叉搜索树
二叉搜索树的局限性
先说一下什么是二叉搜索树,二叉树每个节点只有两个节点,二叉搜索树的每个左子节点的值小于其父节点的值,每个右子节点的值大于其左子节点的值。如下图:

二叉搜索树,顾名思义,它的搜索效率很高,可以达到O(logn)。但这是理想状况下的,即上图所示。实际上,由于插入顺序的原因,形成的二叉搜索树并不会像上图这样“工整”,最坏的情况的下,甚至可能会退化成链表了,如下图:

这显然不是我们想要看的结果,那么我们必须要引入一套机制来避免这种事情的发生,也就是让二叉搜索树带上平衡条件。
AVL平衡二叉搜索树
几个基本概念
叶子节点:既没有左子节点,也没有右左子节点的节点就是叶子节点。
树的高度:叶子节点的高度为1,空节点的高度是-1,父节点的高度是其两个子树较高一棵子树的高度加一。
平衡条件:每一个节点的左子树与右子树的高度差不超过1。
核心思想
因为AVL平衡二叉搜索树,父节点的两颗子树的高度差不能超过1。在AVL平衡二叉树种,采用旋转的机制来使不满足平衡条件的二叉树重新回到满足平衡条件的状态。在二叉搜索树中,需要被平衡的情况可以分为两大类总共四种情况,
- 单旋转
- 左旋转
- 右旋转
- 双旋转
- 先左旋,再右旋
- 先右旋,再左旋
如下图所示:

通过图片的形式我们很容易就可以写出使二叉树回到满足平衡条件的代码
// 右旋转
public TreeNode rightRotate(TreeNode root) {
TreeNode temp1 = root.left;
TreeNode temp2 = temp1.right;
temp1.right = root;
root.left = temp2;
return temp1;
}
// 左旋转
public TreeNode leftRotate(TreeNode root) {
TreeNode temp1 = root.right;
TreeNode temp2 = temp1.left;
temp1.left = root;
root.right = temp2;
return temp1;
}
// 先右后左
public TreeNode rightLeftRotate(TreeNode root) {
root.right = rightRotate(root.right);
return leftRotate(root);
}
// 先左后右
public TreeNode leftRightRotate(TreeNode root) {
root.left = leftRotate(root.left);
return rightRotate(root);
}
我们必须再每一次插入节点后判断树是否需要平衡,也就是是否会出现两颗子树的高度差超过1的情况,首先编写一个可以计算出传入节点 高度的函数。
public int height(TreeNode root) {
if (root == null) {
return -1;
}
if (root.left == null && root.right == null) {
return 0;
}
return Math.max(height(root.right), height(root.left));
}
有了这个函数,我们就不仅可以判断是否出现需要平衡的情况,还可以判断需要平衡的情况是四种情况种的哪一种。
public TreeNode balance(TreeNode root) {
int l = height(root.left);
int r = height(root.right);
if (l - r >= 2) {
// rightRotate
if (height(root.left.left) - height(root.left.right) >= 1) {
// rightRotate
root = rightRotate(root);
} else if (height(root.left.right) - height(root.left.left) >= 1) {
// leftRightRotate
root = leftRightRotate(root);
}
} else if (r - l >= 2) {
// leftRotate
if (height(root.right.right) - height(root.right.left) >= 1) {
// leftRotate
root = leftRotate(root);
} else if (height(root.right.left) - height(root.right.right) >= 1){
root = rightLeftRotate(root);
}
}
return root;
}
以上就是AVL平衡二叉搜索树的精髓,并且已经用代码实现了。
完整代码
这是我完善后的功能相对完整的AVL二叉搜索平衡树。
class TreeNode {
int value;
TreeNode left;
TreeNode right;
int height;
public TreeNode(int value) {
this.value = value;
}
}
public class AVLBinarySearchTree {
public static void main(String[] args) {
AVLBinarySearchTree a = new AVLBinarySearchTree();
for (int i = 0; i < 10; i++) {
a.insert(i);
}
}
private TreeNode root;
private static final int ALLOWED_IMBALANCE = 1;
// 删除元素
public void remove(int value) {
root = remove(value, root);
}
// 检查是否包含某一元素,包含则返回该节点,不包含则返回null
public TreeNode contain(int value) {
TreeNode temp = root;
if (temp == null) {
return temp;
}
while (temp.value != value) {
if (value > temp.value) {
temp = temp.right;
} else if (value < temp.value) {
temp = temp.left;
}
}
return temp;
}
// 删除指定子树上的指定元素
private TreeNode remove(int value, TreeNode abn) {
if (abn == null) {
return abn;
}
if (value > abn.value) {
abn.right = remove(value, abn.right);
} else if (value < abn.value) {
abn.left = remove(value, abn.left);
} else {
if (abn.right == null && abn.left == null) {
abn = null;
return abn;
} else if (abn.right != null) {
abn.value = findMin(abn.right).value;
abn.right = remove(abn.value, abn.right);
} else {
abn.value = findMax(abn.left).value;
abn.left = remove(abn.value, abn.left);
}
}
return balance(abn);
}
// 找到指定子树最大值
private TreeNode findMax(TreeNode abn) {
if (abn == null) {
return null;
}
TreeNode temp = abn;
while (temp.right != null) {
temp = temp.right;
}
return temp;
}
// 找到指定子树最小值
private TreeNode findMin(TreeNode abn) {
if (abn == null) {
return null;
}
TreeNode temp = abn;
while (temp.left != null) {
temp = temp.left;
}
return temp;
}
// 插入节点
public void insert(int value) {
root = insert(value, root);
}
// 计算节点高度
private int height(TreeNode abn) {
if (abn == null) {
return -1;
}
return abn.height;
}
// 树的高度
public int height() {
return height(root);
}
// 插入节点
private TreeNode insert(int value, TreeNode abn) {
if (abn == null) {
return new TreeNode(value);
}
if (value > abn.value) {
abn.right = insert(value, abn.right);
} else if (value < abn.value) {
abn.left = insert(value, abn.left);
}
return balance(abn);
}
// 平衡不平衡的树
private TreeNode balance(TreeNode abn) {
if (height(abn.left) - height(abn.right) > ALLOWED_IMBALANCE) {
if (height(abn.left.left) >= height(abn.left.right)) {
abn = leftSingleRotate(abn);
} else if (height(abn.left.left) < height(abn.left.right)) {
abn = leftDoubleRotate(abn);
}
} else if (height(abn.right) - height(abn.left) > ALLOWED_IMBALANCE) {
if (height(abn.right.right) >= height(abn.right.left)) {
abn = rightSingleRotate(abn);
} else {
abn = rightDoubleRotate(abn);
}
}
abn.height = Math.max(height(abn.left), height(abn.right)) + 1;
return abn;
}
// 右单旋转
private TreeNode rightSingleRotate(TreeNode abn) {
TreeNode temp = abn;
abn = abn.right;
temp.right = abn.left;
abn.left = temp;
temp.height = Math.max(height(temp.right), height(temp.left)) + 1;
abn.height = Math.max(height(abn.right), temp.height) + 1;
return abn;
}
// 左单旋转
private TreeNode leftSingleRotate(TreeNode abn) {
TreeNode temp = abn;
abn = abn.left;
temp.left = abn.right;
abn.right = temp;
temp.height = Math.max(height(temp.right), height(temp.left)) + 1;
abn.height = Math.max(height(abn.right), temp.height) + 1;
return abn;
}
// 右双旋转
private TreeNode rightDoubleRotate(TreeNode abn) {
abn.right = leftSingleRotate(abn.right);
return rightSingleRotate(abn);
}
// 左双旋转
private TreeNode leftDoubleRotate(TreeNode abn) {
abn.left = rightSingleRotate(abn.left);
return leftSingleRotate(abn);
}
}
手写AVL平衡二叉搜索树的更多相关文章
- 二叉搜索树、AVL平衡二叉搜索树、红黑树、多路查找树
1.二叉搜索树 1.1定义 是一棵二叉树,每个节点一定大于等于其左子树中每一个节点,小于等于其右子树每一个节点 1.2插入节点 从根节点开始向下找到合适的位置插入成为叶子结点即可:在向下遍历时,如果要 ...
- AVL平衡二叉搜索树原理及各项操作编程实现
C语言版 #include<stdio.h> #include "fatal.h" struct AvlNode; typedef struct AvlNode *Po ...
- 【算法学习】AVL平衡二叉搜索树原理及各项操作编程实现(C语言)
#include<stdio.h> #include "fatal.h" struct AvlNode; typedef struct AvlNode *Positio ...
- 看动画学算法之:平衡二叉搜索树AVL Tree
目录 简介 AVL的特性 AVL的构建 AVL的搜索 AVL的插入 AVL的删除 简介 平衡二叉搜索树是一种特殊的二叉搜索树.为什么会有平衡二叉搜索树呢? 考虑一下二叉搜索树的特殊情况,如果一个二叉搜 ...
- convert sorted list to binary search tree(将有序链表转成平衡二叉搜索树)
Given a singly linked list where elements are sorted in ascending order, convert it to a height bala ...
- 算法:非平衡二叉搜索树(UnBalanced Binary Search Tree)
背景 很多场景下都需要将元素存储到已排序的集合中.用数组来存储,搜索效率非常高: O(log n),但是插入效率比较低:O(n).用链表来存储,插入效率和搜索效率都比较低:O(n).如何能提供插入和搜 ...
- LeetCode 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树
第108题 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定有序数组: [-10 ...
- 算法进阶面试题04——平衡二叉搜索树、AVL/红黑/SB树、删除和调整平衡的方法、输出大楼轮廓、累加和等于num的最长数组、滴滴Xor
接着第三课的内容和讲了第四课的部分内容 1.介绍二叉搜索树 在二叉树上,何为一个节点的后继节点? 何为搜索二叉树? 如何实现搜索二叉树的查找?插入?删除? 二叉树的概念上衍生出的. 任何一个节点,左比 ...
- 【数据结构与算法Python版学习笔记】树——平衡二叉搜索树(AVL树)
定义 能够在key插入时一直保持平衡的二叉查找树: AVL树 利用AVL树实现ADT Map, 基本上与BST的实现相同,不同之处仅在于二叉树的生成与维护过程 平衡因子 AVL树的实现中, 需要对每个 ...
随机推荐
- javascript获取焦点对象ID
document.activeElement 方法:if(document.activeElement.id="textbox1") { }
- 学习笔记-CCS-MSP430F5529[快速入门篇一]
由于最近竞赛需要使用TI公司的MSP430系列芯片,本人在最近两天匆忙的学习了一下MSP430F5529(下文统一称作5529)的使用.写下本文是为了将这两天学习内容做一个复习,并且将学习过程中遇到的 ...
- Linux下MySQL基础及操作语法
什么是MySQL? MySQL是一种开源关系数据库管理系统(RDBMS),它使用最常用的数据库管理语言-结构化查询语言(SQL)进行数据库管理.MySQL是开源的,因此任何人都可以根据通用公共许可证下 ...
- 阿里内部资料:Android开发核心知识笔记共2100页,58万字,完整版开放下载
作为一个3-5年的Android工程师,我们经常会遇到这些瓶颈: 1.技术视野窄长期在小型软件公司,外包公司工作,技术视野被限制的太厉害 2.薪资提升难初中级Android岗位薪资上升空间有限,基本上 ...
- tomcat启动时启动窗口出现乱码一招搞定
先来看看问题(图示),在tomcat的启动窗口打印的启动信息中包含了大量的中文乱码,虽然这些对tomcat本身的使用没有任何影响,但却非常碍眼,影响视觉效果! tomcat启动时启动窗口出现乱码的解决 ...
- xubuntu共享打印机
by 无若 1.查看系统中的打印机lpstat -ssystem default destination: HP-Color-LaserJet-CP1215device for HP-Color-La ...
- 跟我一起写 Makefile(六)
书写命令 ---- 每条规则中的命令和操作系统Shell的命令行是一致的.make会一按顺序一条一条的执行命令,每条命令的开头必须以[Tab]键开头,除非,命令是紧跟在依赖规则后面的分号后的.在命令行 ...
- windows的自动登录和隐藏用户
Launch Regedit. #r -> regedit 1. Navigate to: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\Cu ...
- SpringBoot开发二十-私信列表
私信列表功能开发. 发送私信功能开发 首先创建一个实体类:Message package com.nowcoder.community.entity; import java.util.Date; p ...
- 武器级工具包 Immunity Canvas 7.26 泄露事件 | 附下载地址
关于Immunity Canvas Immunity CANVAS是Immunity公司的一款商业级漏洞利用和渗透测试工具,包含了480多个以上的漏洞利用,该工具并不开源,其中文版介绍如下: &quo ...