数据结构——二叉查找树、AVL树
二叉查找树:由于二叉查找树建树的过程即为插入的过程,所以其中序遍历一定为升序排列!

插入:直接插入,插入后一定为根节点
查找:直接查找
删除:叶子节点直接删除,有一个孩子的节点删除后将孩子节点接入到父节点即可,有两个孩子的节点,将左儿子最右边节点(或右儿子最左边节点)替换到根节点即可。
AVL树(二叉平衡查找树)
定义:节点的平衡度(左子树的高度 - 右子树的高度)只能为-1、0、1的二叉查找树。

创建:需要一个变量记录每个节点的平衡度
查找:直接查找
插入:LL、LR、RL、RR过程
删除:分情况讨论
AVL树的Java实现:
package com.tonyluis; /**
* AVL树
*
* @author TonyLuis 2016.07.27
* @param <T>
*/
public class AVLTree<T extends Comparable<T>> {
private AVLNode<T> root; @SuppressWarnings("hiding")
class AVLNode<T> {
T val;
AVLNode<T> left;
AVLNode<T> right;
int height; AVLNode(T val, AVLNode<T> left, AVLNode<T> right) {
this.val = val;
this.left = left;
this.right = right;
this.height = 0;
}
} public void insert(T num) {
root = insert(num, root);
} public void remove(T num) {
remove(num, root);
} public boolean find(T num) {
AVLNode<T> t = this.root;
while (t != null && num.compareTo(t.val) != 0)
t = num.compareTo(t.val) > 0 ? t.right : t.left;
if (t == null)
return false;
else
return true;
} private int height(AVLNode<T> node) {
return node == null ? -1 : node.height;
} private AVLNode<T> insert(T num, AVLNode<T> root) {
// root==null 找到了插入的位置
if (root == null)
return new AVLNode<T>(num, null, null); int compareResult = num.compareTo(root.val);
if (compareResult < 0) {// 插入左子树
root.left = insert(num, root.left);
if (height(root.left) - height(root.right) == 2) {
if (num.compareTo(root.left.val) < 0)
root = LL(root);
else
root = LR(root);
}
} else if (compareResult > 0) {
root.right = insert(num, root.right);
if (height(root.right) - height(root.left) == 2) {
if (num.compareTo(root.right.val) < 0)
root = RL(root);
else
root = RR(root);
}
}
root.height = Math.max(height(root.left), height(root.right)) + 1;
return root;
} public boolean remove(T num, AVLNode<T> root) {
boolean isStop = false;
boolean isLeftSubTree;
if (root == null)
return true;
int compareResult = num.compareTo(root.val);
if (compareResult < 0) {
isStop = remove(num, root.left);
isLeftSubTree = true;
} else if (compareResult > 0) {
isStop = remove(num, root.right);
isLeftSubTree = false;
} else if (root.left == null || root.right == null) {
root = root.left == null ? root.right : root.left;
return false;
} else {// 找到且有两个子树,将其和右子树最左边节点交换,然后在右子树执行删除操作
AVLNode<T> tmp = root.right;
while (tmp.left != null)
tmp = tmp.left;
root.val = tmp.val;
isStop = remove(root.val, root.right);
isLeftSubTree = false;
}
if (isStop)
return true;
int bf;// 删除前的root的平衡因子
if (isLeftSubTree) {
bf = height(root.left) - height(root.right) + 1;
if (bf == 0)
return true;
else if (bf == 1)
return false;
else if (bf == -1) {
int bfr = height(root.right.left) - height(root.right.left);
switch (bfr) {
case 0:
RR(root);
return true;
case -1:
RR(root);
return false;
default:
RL(root);
return false;
}
}
} else {
bf = height(root.left) - height(root.right) - 1;
if (bf == 0)
return true;
else if (bf == -1)
return false;
else if (bf == 1) {
int bfr = height(root.right.left) - height(root.right.left);
switch (bfr) {
case 0:
LL(root);
return true;
case 1:
LL(root);
return false;
default:
LR(root);
return false;
}
}
}
return false;
} private AVLNode<T> LL(AVLNode<T> node) {
AVLNode<T> nodeLeft = node.left;
node.left = nodeLeft.right;
nodeLeft.right = node;
node.height = Math.max(height(node.left), height(node.right)) + 1;
nodeLeft.height = Math.max(height(nodeLeft.left), node.height) + 1;
return nodeLeft;
} private AVLNode<T> RR(AVLNode<T> node) {
AVLNode<T> nodeRight = node.right;
node.right = nodeRight.left;
nodeRight.left = node;
node.height = Math.max(height(node.left), height(node.right)) + 1;
nodeRight.height = Math.max(height(nodeRight.right), node.height) + 1;
return nodeRight;
} private AVLNode<T> LR(AVLNode<T> node) {
node.left = RR(node.left);
return LL(node);
} private AVLNode<T> RL(AVLNode<T> node) {
node.right = LL(node.right);
return RR(node);
} }
数据结构——二叉查找树、AVL树的更多相关文章
- 006-数据结构-树形结构-二叉树、二叉查找树、平衡二叉查找树-AVL树
一.概述 树其实就是不包含回路的连通无向图.树其实是范畴更广的图的特例. 树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合. 1.1.树的特性: 每个结点有零个或多个子 ...
- linux 内核数据结构之 avl树.
转载: http://blog.csdn.net/programmingring/article/details/37969745 https://zh.wikipedia.org/wiki/AVL% ...
- 数据结构之AVL树
AVL树是高度平衡的而二叉树.它的特点是:AVL树中任何节点的两个子树的高度最大差别为1. 旋转 如果在AVL树中进行插入或删除节点后,可能导致AVL树失去平衡.这种失去平衡的可以概括为4种姿态:LL ...
- 二叉树-二叉查找树-AVL树-遍历
一.二叉树 定义:每个节点都不能有多于两个的儿子的树. 二叉树节点声明: struct treeNode { elementType element; treeNode * left; treeNod ...
- D&F学数据结构系列——AVL树(平衡二叉树)
AVL树(带有平衡条件的二叉查找树) 定义:一棵AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树. 为什么要使用AVL树(即为什么要给二叉查找树增加平衡条件),已经在我之前的博文中说到过 ...
- [算法] 数据结构之AVL树
1 .基本概念 AVL树的复杂程度真是比二叉搜索树高了整整一个数量级——它的原理并不难弄懂,但要把它用代码实现出来还真的有点费脑筋.下面我们来看看: 1.1 AVL树是什么? AVL树本质上还是一棵 ...
- [javaSE] 数据结构(AVL树基本概念)
AVL树是高度平衡的二叉树,任何节点的两个子树的高度差别<=1 实现AVL树 定义一个AVL树,AVLTree,定义AVLTree的节点内部类AVLNode,节点包含以下特性: 1.key——关 ...
- 面试题:什么叫平衡二叉查找树--AVL树
查找.插入和删除在平均和最坏情况下都是O(log n) 增加和删除可能需要通过一次或多次树旋转来重新平衡这个树 节点的平衡因子是它的左子树的高度减去它的右子树的高度.带有平衡因子 1.0 或 -1 的 ...
- 大话数据结构—平衡二叉树(AVL树)
平衡二叉树(Self-Balancing Binary Search Tree/Height-Balanced Binary Search Tree),是一种二叉排序树,当中每个节点的左子树和右子树的 ...
- 二叉树学习笔记之经典平衡二叉树(AVL树)
二叉查找树(BSTree)中进行查找.插入和删除操作的时间复杂度都是O(h),其中h为树的高度.BST的高度直接影响到操作实现的性能,最坏情况下,二叉查找树会退化成一个单链表,比如插入的节点序列本身就 ...
随机推荐
- asp.net mvc中在使用async的时候HttpContext为null的问题
摘要 HttpContext上下文并不是无处不在的.详情可以看下Fish Li的文章,解释的比较清楚. HttpContext.Current并非无处不在 问题复现 public async Task ...
- 【转】使用Eclipse构建Maven项目 (step-by-step)
安装eclipse 及配置maven时,参考的资料!!! from:http://blog.csdn.net/qjyong/article/details/9098213 Maven这个个项目管理和构 ...
- LINUX 命令行编辑快捷键
转自:http://www.cnblogs.com/edwardlost/archive/2012/07/27/2611536.html 删除 ctrl + d 删除光标所在位置上的字符相当于VIM里 ...
- Myeclipse如何关联源码
Myeclipse版本:Myeclipse2014 关联源码前要下载对应的源码,如本例的dom4j-1.6.1.jar,则去下载对应的源码dom4j-1.6.1.zip 如果做的是web项目,就要将该 ...
- Gulp实现web服务器
Gulp实现web服务器 阅读目录 一:gulp实现web服务器配置: 二:添加实时刷新(livereload)支持 回到顶部 一:gulp实现web服务器配置: 对于前端开发而言,需要在本地搭建一个 ...
- UnicodeDecodeError: 'utf8' codec can't decode
数据库存了些中文字符, 比如'处理脚本'这样的汉字, 结果导致一个python程序报错. 下面记录处理过程和相关结论. ===========================dal.py 程序片段,p ...
- [译]git push
push就是把你本地仓储的commit传到远程仓储中去. 用法 git push <remote> <branch> push指定的分支到<remote>中去. ...
- 关于Tchar
因为C++支持两种字符串,即常规的ANSI编码(使用""包裹)和Unicode编码(使用L""包裹),这样对应的就有了两套字符串处理函数,比如:strlen和w ...
- C#中页面之间传值传参的六种方法
QueryString是一种非常简单的传值方式,他可以将传送的值显示在浏览器的地址栏中.如果是传递一个或多个安全性要求不高或是结构简单的数值时,可以使用这个方法.但是对于传递数组或对象的话,就不能用这 ...
- Ubuntu 14 如何打开 .chm格式文档?
好多手册是.chm格式,Ubuntu是需要安装第三方软件才能打开.chm格式文档,操作方式如下: 到“软件中心” -> 搜索“xchm”,并安装 -> 右键某个.chm文档,选择“属性” ...