定义平衡树节点:

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. SQLite多线程使用总结

    SQLite支持3种线程模式: 单线程:这种模式下,没有进行互斥,多线程使用不安全.禁用所有的mutex锁,并发使用时会出错.当SQLite编译时加了SQLITE_THREADSAFE=0参数,或者在 ...

  2. Python: PS 滤镜-- 极坐标变换到平面坐标

    本文用 Python 实现 PS 中的一种滤镜 极坐标变换到平面坐标,具体的算法原理和效果可以参考之前的博客: http://blog.csdn.net/matrix_space/article/de ...

  3. tyvj2044 旅游景点

    背景 “扫地”杯III NOIP2012模拟赛 day2 第二题 描述 liouzhou_101住在柳侯公园附近,闲暇时刻都会去公园散散步.很那啥的就是,柳侯公园的道路太凌乱了,假若不认识路就会走着走 ...

  4. AutoIt:应用WMI接口,打印远程机器安装的所有应用程序

    Dim $computer ="computer name" Dim $Remoteuser ="Login account" Dim $Remotepass ...

  5. 全民nib

    1.为任何组件创建nib文件 那么如何通过XIB来创建自己的个性化的class呢. 1.Add----New Filss---Cocoa Touch Classes---Object-C  Class ...

  6. 1.oracle中decode的一些巧妙用法

    1.符号函数sign在decode中的用法--比较大小 select decode(sign(变量1-变量2),-1,变量1,变量2) from dual; --取较小值sign()函数根据某个值是0 ...

  7. POI生成Excel工具类

    import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInp ...

  8. monkeyRunner

    MonkeyRunner工具是使用Jython(使用Java编程语言实现的Python)写出来的,它提供了多个API,通过monkeyrunner API 可以写一个Python的程序来模拟操作控制A ...

  9. c/c++面试12-18------关与sizeof那些事儿

    12 使用sizeof计算普通变量所占空间大小 (1)不同数据类型所占字节数不同(32位 64位系统不同) int----->4 double----->8 char-------> ...

  10. UVa 10214 Trees in a Wood. (数论-欧拉函数)

    题意:给定一个abs(x) <= a, abs(y) <= b,除了原点之外的整点各有一棵树,可以相互阻挡,求从原点可以看到多少棵树. 析:由于a < b,所以我们可以一列一列的统计 ...