package com.tomsnail.data.tree;
/**
* AVL二叉平衡树
* @author tomsnail
* @date 2015年3月30日 下午4:35:50
*/
public class AVLTree { /**
* 根节点
* @author tomsnail
* @date 2015年3月30日 下午4:36:54
*/
private AVLNode rootNode; private String bulidType = ""; /**
* 增加一个节点
* @author tomsnail
* @date 2015年3月30日 下午4:36:08
*/
public void add(int value){
AVLNode subNode = null;
if(rootNode==null){
subNode = new AVLNode(value);
rootNode = subNode;
}else{
subNode = addNode(rootNode,value);
}
reBuild(subNode); } private AVLNode addNode(AVLNode node,int value){
AVLNode subNode = null;
if(node.getValue()>value){
if(node.getLeftNode()==null){
subNode = new AVLNode(value);
node.setLeftNode(subNode);
}else{
subNode = addNode(node.getLeftNode(), value);
}
}
if(node.getValue()<value){
if(node.getRightNode()==null){
subNode = new AVLNode(value);
node.setRightNode(subNode);
}else{
subNode = addNode(node.getRightNode(),value);
}
}
return subNode;
}
/**
* 重平衡树
* @author tomsnail
* @date 2015年3月30日 下午5:42:00
*/
private void reBuild(AVLNode node){
if(node!=null){
AVLNode tempRootNode = findTempRootNode(node);
if(tempRootNode!=null){
if(bulidType.equals("ll")){
Lrotate(node,tempRootNode);
}else if(bulidType.equals("rr")){
Rrotate(node,tempRootNode);
}else if(bulidType.equals("lr")){
Rrotate(node,tempRootNode.getLeftNode());
Lrotate(node,tempRootNode);
}else if(bulidType.equals("rl")){
Lrotate(node,tempRootNode.getRightNode());
Rrotate(node,tempRootNode);
}
reBuild(tempRootNode);
}
}
}
/**
* 右旋
* @author tomsnail
* @date 2015年3月30日 下午9:23:28
*/
private void Rrotate(AVLNode node,AVLNode tempRootNode){
AVLNode rotateNode = tempRootNode.getRightNode();//旋转节点
AVLNode rootNode = tempRootNode.getRootNode();//主根节点
String type = "";
if(rootNode!=null){
if(rootNode.getLeftNode()==tempRootNode){
type="l";
}else{
type="r";
}
}
AVLNode adjustNode = rotateNode.getLeftNode();//调整节点
rotateNode.setLeftNode(tempRootNode);
tempRootNode.setRightNode(null);
if(adjustNode!=null){
tempRootNode.setRightNode(adjustNode);
}
if(rootNode==null){
rotateNode.setRootNode(null);
this.rootNode = rotateNode;
}
if(type.equals("r")){
rootNode.setRightNode(rotateNode);
}else if(type.equals("l")){
rootNode.setLeftNode(rotateNode);
}
}
/**
* 左旋
* @author tomsnail
* @date 2015年3月30日 下午9:23:28
*/
private void Lrotate(AVLNode node,AVLNode tempRootNode){
AVLNode rotateNode = tempRootNode.getLeftNode();//旋转节点
AVLNode rootNode = tempRootNode.getRootNode();//主根节点
String type = "";
if(rootNode!=null){//子树类型
if(rootNode.getLeftNode()==tempRootNode){
type="l";
}else{
type="r";
}
}
AVLNode adjustNode = rotateNode.getRightNode();//调整节点
rotateNode.setRightNode(tempRootNode);
tempRootNode.setLeftNode(null);
if(adjustNode!=null){
tempRootNode.setLeftNode(adjustNode);
}
if(rootNode==null){
rotateNode.setRootNode(null);
this.rootNode = rotateNode;
}
if(type.equals("r")){
rootNode.setRightNode(rotateNode);
}else if(type.equals("l")){
rootNode.setLeftNode(rotateNode);
}
} /**
* 查找最小不平衡的根节点
* @author tomsnail
* @date 2015年3月30日 下午5:40:55
*/
private AVLNode findTempRootNode(AVLNode node){
AVLNode noB = getNoBalance(node);
if(noB==null){
return null;
}
if(isTypeLL(noB)){
bulidType = "ll";
}else if(isTypeRR(noB)){
bulidType = "rr";
}else if(isTypeLR(noB)){
bulidType = "lr";
}else if(isTypeRL(noB)){
bulidType = "rl";
}
return noB;
}
//左左类型
private boolean isTypeLL(AVLNode noB){
try {
if(noB.getRightNode()==null&&noB.getLeftNode().getRightNode()==null&&!noB.getLeftNode().getLeftNode().hasSubNode()){
return true;
}
if(noB.getRightNode()!=null&&noB.getLeftNode().getRightNode()!=null&&noB.getLeftNode().getLeftNode().hasSubNode()){
return true;
}
} catch (Exception e) {
}
return false;
}
//右右类型
private boolean isTypeRR(AVLNode noB){
try {
if(noB.getLeftNode()==null&&noB.getRightNode().getLeftNode()==null&&!noB.getRightNode().getRightNode().hasSubNode()){
return true;
}
if(noB.getLeftNode()!=null&&noB.getRightNode().getLeftNode()!=null&&noB.getRightNode().getRightNode().hasSubNode()){
return true;
}
} catch (Exception e) {
}
return false;
}
//左右类型
private boolean isTypeLR(AVLNode noB){
try {
if(noB.getRightNode()==null&&noB.getLeftNode().getLeftNode()==null&&!noB.getLeftNode().getRightNode().hasSubNode()){
return true;
}
if(noB.getRightNode()!=null&&noB.getLeftNode().getLeftNode()!=null&&noB.getLeftNode().getRightNode().hasSubNode()){
return true;
}
} catch (Exception e) {
}
return false;
}
//右左类型
private boolean isTypeRL(AVLNode noB){
try {
if(noB.getLeftNode()==null&&noB.getRightNode().getRightNode()==null&&!noB.getRightNode().getLeftNode().hasSubNode()){
return true;
}
if(noB.getLeftNode()!=null&&noB.getRightNode().getRightNode()!=null&&noB.getRightNode().getLeftNode().hasSubNode()){
return true;
}
} catch (Exception e) {
}
return false;
} //获取不平衡的根节点
private AVLNode getNoBalance(AVLNode node){
if(node.getRootNode()==null){
return null;
}else{
if(!isBalance(node.getRootNode())){
return node.getRootNode();
}else{
return getNoBalance(node.getRootNode());
}
}
} /**
* 删除一个节点
* @author tomsnail
* @date 2015年3月30日 下午4:36:20
*/
public void delete(int value){
AVLNode wantDeleteNode = find(value);
if(wantDeleteNode==null){
return;
}else{
if(wantDeleteNode.getLeftNode()==null&&wantDeleteNode.getRightNode()==null){//删除节点没有左右子树
AVLNode rootNode = wantDeleteNode.getRootNode();
if(rootNode!=null){
if(rootNode.getLeftNode()==wantDeleteNode){
rootNode.setLeftNode(null);
}else{
rootNode.setRightNode(null);
}
reBuild(rootNode);
}
}else if(wantDeleteNode.getRightNode()==null){//删除节点只有左子树
AVLNode rootNode = wantDeleteNode.getRootNode();
if(rootNode!=null){
if(rootNode.getLeftNode()==wantDeleteNode){
rootNode.setLeftNode(wantDeleteNode.getLeftNode());
}else{
rootNode.setRightNode(wantDeleteNode.getLeftNode());
}
wantDeleteNode.setLeftNode(null);
reBuild(rootNode);
}
}else if(wantDeleteNode.getLeftNode()==null){//删除节点只有右子树
AVLNode rootNode = wantDeleteNode.getRootNode();
if(rootNode!=null){
if(rootNode.getRightNode()==wantDeleteNode){
rootNode.setLeftNode(wantDeleteNode.getRightNode());
}else{
rootNode.setRightNode(wantDeleteNode.getRightNode());
}
wantDeleteNode.setRightNode(null);
reBuild(rootNode);
}
}else {//删除节点有左右子树
AVLNode maxNode = getLeftMaxValueNode(wantDeleteNode.getLeftNode());//找到节点左子树最大值的节点
AVLNode rootMaxNode = maxNode.getRootNode();//获得该节点的父节点
if(maxNode.getLeftNode()!=null){//如果最大值节点有左子树,则将最大值节点的父节点的右子树设为它
rootMaxNode.setRightNode(maxNode.getLeftNode());
maxNode.setLeftNode(null);
}else{//否则置空
rootMaxNode.setRightNode(null);
}
wantDeleteNode.setValue(maxNode.getValue());//把要删除节点的值用最大值节点的值替换
maxNode=null;//引用置空
reBuild(rootMaxNode);
}
}
}
//得到左子树最大值节点
private AVLNode getLeftMaxValueNode(AVLNode node){
if(node!=null&&node.getRightNode()!=null){
return getLeftMaxValueNode(node.getRightNode());
}else{
return node;
}
} /**
* 查找一个节点
* @author tomsnail
* @date 2015年3月30日 下午4:36:35
*/
public AVLNode find(int value){
return findWith2(rootNode,value);
}
private AVLNode findWith2(AVLNode node,int value){
if(node==null){
return null;
}
System.out.println(node.getValue());
if(node.getValue()>value){
return findWith2(node.getLeftNode(),value);
}else if(node.getValue()<value){
return findWith2(node.getRightNode(),value);
}else{
return node;
}
} /**
* 中序遍历
* @author tomsnail
* @date 2015年3月31日 下午6:23:05
*/
public void midScan(AVLNode node){
if(node==null){
return;
}
midScan(node.getLeftNode());
System.out.println(node.getValue());
midScan(node.getRightNode());
} public AVLNode getRootNode() {
return rootNode;
} public static void main(String[] args) {
int[] is = new int[]{10,11,23,3,5,44,32,4,6,18,19,7,8,70,50,60,40,55,65,53,80};//10,11,23,3,5,44,32,4,6,18,19,7,8,70,50,60,40,55,65,53,80
AVLTree tree = new AVLTree();
for(int i=0;i<is.length;i++){
tree.add(is[i]);
}
System.out.println(tree.getRootNode().getValue());
System.out.println("----------------------------");
tree.midScan(tree.getRootNode());
tree.delete(4);
System.out.println(isBalance(tree.getRootNode()));
System.out.println();
//tree.find(40);
} public static int depth(AVLNode node){
if(node==null){
return 0;
}else{
int ld = depth(node.getLeftNode());
int rd = depth(node.getRightNode());
return 1 + (ld >rd ? ld : rd);
}
} public static boolean isBalance(AVLNode node){
if (node==null)
return true;
int dis = depth(node.getLeftNode()) - depth(node.getRightNode());
if (dis>1 || dis<-1 )
return false;
else
return isBalance(node.getLeftNode()) && isBalance(node.getRightNode());
}
}
class AVLNode{
private int value;
private AVLNode leftNode;
private AVLNode rightNode;
private AVLNode rootNode;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public AVLNode getLeftNode() {
return leftNode;
}
public void setLeftNode(AVLNode leftNode) {
this.leftNode = leftNode;
if(leftNode!=null){
leftNode.setRootNode(this);
}
}
public AVLNode getRightNode() {
return rightNode;
}
public void setRightNode(AVLNode rightNode) {
this.rightNode = rightNode;
if(rightNode!=null){
rightNode.setRootNode(this);
}
} public AVLNode getRootNode() {
return rootNode;
}
public void setRootNode(AVLNode rootNode) {
this.rootNode = rootNode;
} public boolean hasSubNode(){
if(this.leftNode!=null||this.rightNode!=null){
return true;
}else{
return false;
}
} public AVLNode(){
}
public AVLNode(int value){
this.value = value;
}
}

树——平衡二叉树插入和查找的JAVA实现(2):增加删除方法的更多相关文章

  1. 树——平衡二叉树插入和查找的JAVA实现

    package com.tomsnail.data.tree; /** * AVL二叉平衡树 * @author tomsnail * @date 2015年3月30日 下午4:35:50 */ pu ...

  2. 数据结构系列之2-3-4树的插入、查找、删除和遍历完整版源代码实现与分析(dart语言实现)

    本文属于原创,转载请注明来源. 在上一篇博文中,详细介绍了2-3树的操作(具体地址:https://www.cnblogs.com/outerspace/p/10861488.html),那么对于更多 ...

  3. 数据结构系列之2-3树的插入、查找、删除和遍历完整版代码实现(dart语言实现)

    弄懂了二叉树以后,再来看2-3树.网上.书上看了一堆文章和讲解,大部分是概念,很少有代码实现,尤其是删除操作的代码实现.当然,因为2-3树的特性,插入和删除都是比较复杂的,因此经过思考,独创了删除时分 ...

  4. DS-二叉排序树的插入、查找和删除

    2019-12-02(菜鸡开始学习了...) Data Structure 之 二叉排序树 二叉排序树是给定一个节点后,接下来插入的数如果比它大就会放到它的右孩子那边,比它小就会放到它的左孩子那边. ...

  5. 萌新笔记——C++里创建 Trie字典树(中文词典)(二)(插入、查找、导入、导出)

    萌新做词典第二篇,做得不好,还请指正,谢谢大佬! 做好了插入与遍历功能之后,我发现最基本的查找功能没有实现,同时还希望能够把内存的数据存入文件保存下来,并可以从文件中导入词典.此外,数据的路径是存在配 ...

  6. C++里创建 Trie字典树(中文词典)(二)(插入、查找、导入、导出)

    萌新做词典第二篇,做得不好,还请指正,谢谢大佬! 做好了插入与遍历功能之后,我发现最基本的查找功能没有实现,同时还希望能够把内存的数据存入文件保存下来,并可以从文件中导入词典.此外,数据的路径是存在配 ...

  7. Java手写简单Linkedlist一(包括增加,插入,查找,toString,remove功能)

    @Java300 学习总结 一.自定义节点 LinkList底层为双向链表.特点为查询效率低,但增删效率高,线程不安全. 链表数据储存在节点,且每个节点有指向上个和下个节点的指针. 创建ggLinke ...

  8. 树·AVL树/平衡二叉树

    1.AVL树 带有平衡条件的二叉查找树,所以它必须满足条件: 1 是一棵二叉查找树 2 满足平衡条件 1.1 平衡条件: 1)严格的平衡条件:每个节点都必须有相同高度的左子树和右子树(过于严格而不被使 ...

  9. 【转】B树、B-树、B+树、B*树、红黑树、 二叉排序树、trie树Double Array 字典查找树简介

    B  树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: ...

随机推荐

  1. jQuery Validate(一)

    jQuery Validate 插件为表单提供了强大的验证功能,让客户端表单验证变得更简单. 但是在学习的过程中,我也遇到了疑惑,网上的很多例子貌似都是依赖jquery.metadata.js这个库, ...

  2. ubuntu系统安装好后一些基本软件的安装

    preface: 由于某些原因重装了系统,原来在ubuntu下安装的一些软件又要又一次安装.稍微麻烦,整理下须要安装的步骤. #==================================== ...

  3. 01 http协议概念及工作流程

    一:HTTP协议 重要性: 无论是以后用webserverice ,还是用rest做大型架构,都离不开对HTTP协议的认识. 甚至可以简化的说: webservice = http协议+XML Res ...

  4. Encoding::CompatibilityError: incompatible character encodings: GBK and UTF-8

    直接grunt serve读的css是.tmp/css/main.css 而这个文件不通过build生成出来是这样: /* Encoding::CompatibilityError: incompat ...

  5. C#泛型<T>说明

    泛型:即通过参数化类型来实现在同一份代码上操作多种数据类型.泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用. C#泛型的作用概述 C#泛型赋予了代码更强的类型安全,更 ...

  6. iOS项目 -- 模仿花椒直播做的第一层次界面

    公最近直播比较火爆,我也跟跟风,自己做一个直播app, 现在打算用金山云直播的,但是去注册的时候,联系那边的工作人员,他们讲使用金山云直播要有公司和他们线下签约才能授权开放直播平台. 怎么办呢?于是我 ...

  7. 九度OJ 1167:数组排序 (排序)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5395 解决:1715 题目描述: 输入一个数组的值,求出各个值从小到大排序后的次序. 输入: 输入有多组数据. 每组输入的第一个数为数组的 ...

  8. 记录Elasticsearch的一次坑

    Elasticsearch建立mapping关系时,默认会给string类型加上分词. 所以例如openid这种,如果你用默认的分词,就可能会出现查不到数据的情况. 解决方案: 1.将数据备份 2.r ...

  9. 洛谷 2261 [CQOI2007]余数求和

    题目戳这里 一句话题意 求 \(\sum_{i=1}^{n} (k ~~\texttt{mod} ~~i)\) Solution 30分做法: 说实话并不知道怎么办. 60分做法: 很明显直接一遍o( ...

  10. 20145239杜文超 《Java程序设计》第2周学习总结

    20145239 <Java程序设计>第2周学习总结 教材学习内容总结 第三章主要介绍了Java语言的基础语法. 要求我们认识类型与变量,学习运算符的基本使用以及了解类型转换.运用基本流程 ...