AVL树----java

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

1.单旋转LL旋转

理解记忆:1.在不平衡的节点的左孩子的左孩子插入导致的不平衡,所以叫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;
}

2.单旋转RR

理解记忆:1.不平衡节点的右孩子的有孩子插入导致的不平衡,所以叫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;
}

3.双旋转LR

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

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

private AVLTreeNode<T> leftRightRotation(AVLTreeNode<T> k3) {
k3.left = rightRightRotation(k3.left); return leftLeftRotation(k3);
}

4.双旋转RL



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

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

private AVLTreeNode<T> rightLeftRotation(AVLTreeNode<T> k1) {
k1.right = leftLeftRotation(k1.right); return rightRightRotation(k1);
}

5.AVL的样例

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

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

AVL树----java的更多相关文章

  1. AVL树(Java实现)

    AVL树基本介绍 AVL树是一种自平衡的二叉查找树,在AVL树中任何节点的两个子树的高度差不能超过1.就是相当于在二叉搜索树的基础上,在插入和删除时进行了平衡处理. 不平衡的四种情况 LL:结构介绍 ...

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

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

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

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

  4. AVL树之 Java的实现

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

  5. AVL树的Java实现

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

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

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

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

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

  8. AVL树(C++&Java)

    目录 AVL Tree精讲专题 前言 一.AVL Tree for CPP(Coding) 1.AVL树原型 2.旋转的四种方式 二.完整版AVL Tree的CPP和JAVA实现 AVL Tree C ...

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

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

随机推荐

  1. 五张图概括 什么是 ASP 、 ASP.NET (Web Pages,Web Forms ,MVC )

    当你看懂下面这五张图,我相信你对于学习.NET Web开发路线将不陌生!                                               来源: http://www.w3 ...

  2. 转: AlphaImageLoader简介

    Microsoft.AlphaImageLoader是IE滤镜的一种,其主要作用就是对图片进行透明处理.虽然FireFox和IE7以上的IE浏览器已经支持透明的PNG图片,但是就IE5-IE6而言还是 ...

  3. Delphi_MemoryModule — load DLL from memory. Also includes hooking utilities.

    https://github.com/Fr0sT-Brutal/Delphi_MemoryModule

  4. AWVS介绍(转)

    使用AWVS对域名进行全局分析,深入探索: 首先,介绍一下AWVS这个工具. Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的网络漏洞扫描工具,它通过网 ...

  5. WebLech是一个功能强大的Web站点下载与镜像工具

    WebLech是一个功能强大的Web站点下载与镜像工具.它支持按功能需求来下载web站点并能够尽可能模仿标准Web浏览器的行为.WebLech有一个功能控制台并采用多线程操作. http://sour ...

  6. 深入解析MFC -- 句柄与对象的关系

    CWnd::FromHandlePermanent ——根据窗口句柄得到CWnd*指针 This function, unlike FromHandle, does not create tempor ...

  7. 提高mysql查询效率的六种方法

    1,表设计一定要优化,冗余数据最少,少用连接查询.如果在实际应用中,使用了极其复杂的连接,子查询,则数据表的设计得要重新考虑了. 2,尽量用char而不是varchar,因为固定长度得string用起 ...

  8. 获取sdcard和内存的存储空间

    package com.example.sdcardspace; import java.io.File; import android.os.Bundle; import android.os.En ...

  9. PHP - 四级单词lrc文件解析为txt

    原始文件: 转换后文件: php代码: 首先根据需要更改文件路径. 转换后存放的文件要事先创建,为txt文件. 核心代码:正则表达式替换: <?php header('Content-type: ...

  10. 高级特性(7)- 高级AWT

    7.1 绘图操作流程7.2 形状7.3 区域7.4 笔划7.5 着色7.6 坐标变换7.7 剪切7.8 透明与组合7.9 绘图提示7.10 图像的读取器和写入器 7.10.1 获得图像文件类型的读取器 ...