定义平衡树节点:

class TreeNode {

        /**
* 树节点的值
*/
private int val; /**
* 树的高度
*/
private int height; /**
* 左子节点
*/
private TreeNode left; /**
* 右子节点
*/
private TreeNode right; public TreeNode(int val) {
this.val = val;
} }

辅助的方法:

1.用于计算节点的高度:

/**
* 获取节点的高度
*
* @param node
* @return
*/
private int height(TreeNode node) {
return node == null ? -1 : max(height(node.left), height(node.right)) + 1;
} /**
* 获取二者中较大的
*
* @param a
* @param b
* @return
*/
private int max(int a, int b) {
return a >= b ? a : b;
}

2.获取节点的平衡因子(即左子树与右子树的高度差):

    /**
* 获取节点的平衡因子
*
* @param node
* @return
*/
private int getBalanceFactor(TreeNode node) {
return node == null ? -1 : height(node.left) - height(node.right);
}

AVL树插入数据的四种结构:

第一种:

只需要实现单次右旋:

    /**
* 右旋
* 返回旋转后新的节点
* @param tree 待旋转的节点
*/
private TreeNode rightRotate(TreeNode tree) {
//拷贝源节点的左节点
TreeNode node = tree.left;
tree.left = node.right;
node.right = tree;
//重新计算节点的高度
node.height = height(node);
// tree.height = height(tree);
tree = null; //help gc
return node;
}

第二种:

先左旋节点的左子节点,再右旋节点:

//先左旋左节点,再右旋节点
node.left = leftRotate(node.left);
return rightRotate(node);

第三种:

只需要实现单次左旋:

   /**
* 左旋
*
* @param tree 待旋转的节点
*/
private TreeNode leftRotate(TreeNode tree) {
TreeNode node = tree.right;
tree.right = node.left;
node.left = tree;
//重新计算节点的高度
node.height = height(node);
// tree.height = height(tree);
tree = null; //help gc
return node;
}

第四种:

先右旋右子节点,再左旋:

//先右旋右节点,再左旋节点
node.right = rightRotate(node.right);
return leftRotate(node);

出入数据的完整实现:

public class AvlTree {

    static class TreeNode {

        /**
* 树节点的值
*/
private int val; /**
* 树的高度
*/
private int height; /**
* 左子节点
*/
private TreeNode left; /**
* 右子节点
*/
private TreeNode right; public TreeNode(int val) {
this.val = val;
} } /**
* 插入节点key到以node为根的树中
*
* @param node
* @param key
* @return
*/
public TreeNode add(TreeNode node, int key) {
//1.插入节点:
if (node == null)
return new TreeNode(key);
if (key < node.val) {
//查找左树
node.left = add(node.left, key);
} else if (key > node.val) {
//查找右树
node.right = add(node.right, key);
} else {
//do noting
return node;
}
//2.插入后更新节点的高度
node.height = max(height(node.left), height(node.right));
//3.获取平衡因子,如有失衡者,则平衡树节点
int factor = getBalanceFactor(node);
if (factor > 1) {
//左高
if (key < node.left.val) {
//只右旋转一次
return rightRotate(node);
} else {
//先左旋左节点,再右旋节点
node.left = leftRotate(node.left);
return rightRotate(node);
}
} else if (factor < -1) {
//右高
if (key > node.right.val) {
//只右旋转一次
return leftRotate(node);
} else {
//先右旋右节点,再左旋节点
node.right = rightRotate(node.right);
return leftRotate(node);
}
}
return node;
} /**
* 获取节点的平衡因子
*
* @param node
* @return
*/
private int getBalanceFactor(TreeNode node) {
return node == null ? -1 : height(node.left) - height(node.right);
} public static void main(String[] args) {
AvlTree tree = new AvlTree();
TreeNode node = null;
int[] a = {3, 2, 1, 4, 5, 6, 7, 10, 9, 8};
for (int b : a) {
node = tree.add(node, b);
}
//遍历node
inOrder(node);
preOrder(node);
//layerOrder(node);
} /**
* 获取节点的高度
*
* @param node
* @return
*/
private int height(TreeNode node) {
return node == null ? -1 : max(height(node.left), height(node.right)) + 1;
} /**
* 获取二者中较大的
*
* @param a
* @param b
* @return
*/
private int max(int a, int b) {
return a >= b ? a : b;
} /**
* 右旋
*
* @param tree 待旋转的节点
*/
private TreeNode rightRotate(TreeNode tree) {
//拷贝源节点的左节点
TreeNode node = tree.left;
tree.left = node.right;
node.right = tree;
//重新计算节点的高度
node.height = height(node);
// tree.height = height(tree);
tree = null; //help gc
return node;
} /**
* 左旋
*
* @param tree 待旋转的节点
*/
private TreeNode leftRotate(TreeNode tree) {
TreeNode node = tree.right;
tree.right = node.left;
node.left = tree;
//重新计算节点的高度
node.height = height(node);
// tree.height = height(tree);
tree = null; //help gc
return node;
} /**
* 中序遍历测试
*
* @param node
*/
private static void inOrder(TreeNode node) {
if (node != null) {
inOrder(node.left);
System.err.println(node.val);
inOrder(node.right);
}
} /**
* 前序遍历测试
*
* @param node
*/
private static void preOrder(TreeNode node) {
if (node != null) {
System.err.println(node.val + " - height:" + node.height);
preOrder(node.left);
preOrder(node.right);
}
}
  
private static void layerOrder(TreeNode root) {
Queue<TreeNode> queue = new ArrayDeque<>();
if (root != null) queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
System.out.println(node.val);
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}
}

二叉查找树之AVL树的更多相关文章

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

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

  2. 深入浅出数据结构C语言版(12)——平衡二叉查找树之AVL树

    在上一篇博文中我们提到了,如果对普通二叉查找树进行随机的插入.删除,很可能导致树的严重不平衡 所以这一次,我们就来介绍一种最老的.可以实现左右子树"平衡效果"的树(或者说算法),即 ...

  3. 二叉查找树,AVL树,伸展树【CH4601普通平衡树】

    最近数据结构刚好看到了伸展树,在想这个东西有什么应用,于是顺便学习一下. 二叉查找树(BST),对于树上的任意一个节点,节点的左子树上的关键字都小于这个节点的关键字,节点的右子树上的关键字都大于这个节 ...

  4. 算法学习 - 平衡二叉查找树实现(AVL树)

    平衡二叉查找树 平衡二叉查找树是非常早出现的平衡树,由于全部子树的高度差不超过1,所以操作平均为O(logN). 平衡二叉查找树和BS树非常像,插入和删除操作也基本一样.可是每一个节点多了一个高度的信 ...

  5. 常见基本数据结构——树,二叉树,二叉查找树,AVL树

    常见数据结构——树 处理大量的数据时,链表的线性时间太慢了,不宜使用.在树的数据结构中,其大部分的运行时间平均为O(logN).并且通过对树结构的修改,我们能够保证它的最坏情形下上述的时间界. 树的定 ...

  6. AVL树(平衡二叉查找树)

    首先要说AVL树,我们就必须先说二叉查找树,先介绍二叉查找树的一些特性,然后我们再来说平衡树的一些特性,结合这些特性,然后来介绍AVL树. 一.二叉查找树 1.二叉树查找树的相关特征定义 二叉树查找树 ...

  7. 006-数据结构-树形结构-二叉树、二叉查找树、平衡二叉查找树-AVL树

    一.概述 树其实就是不包含回路的连通无向图.树其实是范畴更广的图的特例. 树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合. 1.1.树的特性: 每个结点有零个或多个子 ...

  8. 数据结构与算法分析-AVL树

    1.AVL树是带有平衡条件的二叉查找树. 2.AVL树的每个节点高度最多相差1. 3.AVL树实现的难点在于插入或删除操作.由于插入和删除都有可能破坏AVL树高度最多相差1的特性,所以当特性被破坏时需 ...

  9. 二叉树,AVL树和红黑树

    为了接下来能更好的学习TreeMap和TreeSet,讲解一下二叉树,AVL树和红黑树. 1. 二叉查找树 2. AVL树 2.1. 树旋转 2.1.1. 左旋和右旋 2.1.2. 左左,右右,左右, ...

随机推荐

  1. CI核心文件分析之基准测试类 (Benchmark.php)

    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * * ...

  2. [TJOI2016 & HEOI2016] 字符串

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=4556 [算法] 不难发现 , 对于每个询问        ans = max{ mi ...

  3. [HAOI 2012] 外星人

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2749 [算法] 首先 , 每次对一个数x进行操作 , 只会使该数减少一个2的因子 那 ...

  4. bzoj2957楼房重建——线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2957 线段树维护原点到楼顶的斜率,可以知道答案就是从原点开始斜率递增的个数: 记录一个mx数 ...

  5. oracle获取一段时间内所有的小时、天、月

    获取一段时间内所有的小时 ) sdate FROM dual CONNECT ; 获取一段时间内所有的天 sdate FROM dual CONNECT ; from user_objects whe ...

  6. ubuntu16.04 + cuda9.0(deb版)+Cudnn7.1

    https://blog.csdn.net/Umi_you/article/details/80268983

  7. weex 打包apk

    安装 weexpack weexpack create my-project    //创建项目 cd my-project cnpm install //安装依赖 npm start //运行项目 ...

  8. SQL集锦之IndexOf、LastIndexOf 【转】

    DECLARE @Name NVARCHAR (50)SET @Name = '12345.67890ABCDE.FGHIJKLMNOPQRSTUVWXYZTest' DECLARE @Positio ...

  9. ECMAScript 6 &ECMAScript 5(在线手册)

    https://www.w3.org/html/ig/zh/wiki/ES5#.E8.A1.A8.E8.BE.BE.E5.BC.8F      ECMAScript 5(在线手册) http://es ...

  10. 1 python----pycharm本地部署spark

    下图相关工具连接 链接:https://pan.baidu.com/s/115XWf_Fc1yMiJytKJQXnFQ   密码:3jvr 好了,加油哟!