1,Node.java

 package com.cnblogs.mufasa.BalanceBinaryTree;

 public class Node {
Node parent;
Node leftChild;
Node rightChild;
int val;
public Node(Node parent, Node leftChild, Node rightChild,int val) {
super();
this.parent = parent;
this.leftChild = leftChild;
this.rightChild = rightChild;
this.val = val;
} public Node(int val){
this(null,null,null,val);
} public Node(Node node,int val){
this(node,null,null,val);
}
}

图1 Node.java结构图

2,BalanceBinaryTree.java

 package com.cnblogs.mufasa.BalanceBinaryTree;

 import java.util.LinkedList;
import java.util.Queue; public class BalanceBinaryTree {
private final static int LEFT=0;
private final static int RIGHT=1;
private Node root;
private int size;
public BalanceBinaryTree(){
super();
} //LL型非平衡树,右旋转
public Node rightRotation(Node node){
System.out.println(node.val+"右旋");
if(node != null){
Node leftChild = node.leftChild;// 用变量存储node节点的左子节点
node.leftChild = leftChild.rightChild;// 将leftChild节点的右子节点赋值给node节点的左节点
if(leftChild.rightChild != null){// 如果leftChild的右节点存在,则需将该右节点的父节点指给node节点
leftChild.rightChild.parent = node;
}
leftChild.parent = node.parent;
if(node.parent == null){// 即表明node节点为根节点
this.root = leftChild;
}else if(node.parent.rightChild == node){// 即node节点在它原父节点的右子树中
node.parent.rightChild = leftChild;
}else if(node.parent.leftChild == node){
node.parent.leftChild = leftChild;
}
leftChild.rightChild = node;
node.parent = leftChild;
return leftChild;
}
return null;
} //RR型非平衡树,左旋
public Node leftRotation(Node node){
System.out.println(node.val+"左旋");
if(node != null){
Node rightChild = node.rightChild;
node.rightChild = rightChild.leftChild;
if(rightChild.leftChild != null){
rightChild.leftChild.parent = node;
}
rightChild.parent = node.parent;
if(node.parent == null){
this.root = rightChild;
}else if(node.parent.rightChild == node){
node.parent.rightChild = rightChild;
}else if(node.parent.leftChild == node){
node.parent.leftChild = rightChild;
}
rightChild.leftChild = node;
node.parent = rightChild; }
return null;
} //添加新元素
public boolean put(int val){
return putVal(root,val);
}
private boolean putVal(Node node,int val){
if(node == null){// 初始化根节点
node = new Node(val);
root = node;
size++;
return true;
}
Node temp = node;
Node p;
int t;
/**
* 通过do while循环迭代获取最佳节点,
*/
do{
p = temp;
t = temp.val-val;
if(t > 0){
temp = temp.leftChild;
}else if(t < 0){
temp = temp.rightChild;
}else{
temp.val = val;//插入数值有相同数据,不符合要求
return false;
}
}while(temp != null); Node newNode = new Node(p, val);
if(t > 0){
p.leftChild = newNode;
}else if(t < 0){
p.rightChild = newNode;
}
rebuild(p);// 使二叉树平衡的方法,优化平衡
size++;
return true;
} //平衡二叉树优化节点
private void rebuild(Node p){
while(p != null){
if(calcNodeBalanceValue(p) == 2){// 说明左子树高,需要右旋或者 先左旋后右旋
fixAfterInsertion(p,LEFT);// 调整操作
}else if(calcNodeBalanceValue(p) == -2){// 说明右子树高
fixAfterInsertion(p,RIGHT);
}
p = p.parent;
}
} //计算二叉树平衡因子①
private int calcNodeBalanceValue(Node node){
if(node != null){
return getHeightByNode(node);
}
return 0;
} //计算二叉树平衡因子②
public int getHeightByNode(Node node){
if(node == null){//多余
return 0;
}
return getChildDepth(node.leftChild)-getChildDepth(node.rightChild);
} // 计算node节点的高度,递归调用
public int getChildDepth(Node node){
if(node == null){
return 0;
}
return 1+Math.max(getChildDepth(node.leftChild),getChildDepth(node.rightChild));
} /**
* 调整树结构,先后顺序需要换一下,先判断LR型和RL型进行二次旋转
* @param p
* @param type
*/
private void fixAfterInsertion(Node p, int type) {
if(type == 0){//需要右旋或者 先左旋后右旋
final Node leftChild = p.leftChild;
if(leftChild.rightChild != null){// 先左旋后右旋
leftRotation(leftChild);
rightRotation(p);
}else if(leftChild.leftChild != null){//右旋
rightRotation(p);
} }else{
final Node rightChild = p.rightChild;
if(rightChild.leftChild != null){// 先右旋,后左旋
rightRotation(p);
leftRotation(rightChild);
}else if(rightChild.rightChild != null){// 左旋
leftRotation(p);
}
}
} //删除元素
public boolean delete(int val){
Node node = getNode(val);//搜索这个节点的数值
if(node == null){
return false;
}
boolean flag = false;
Node p = null;
Node parent = node.parent;
Node leftChild = node.leftChild;
Node rightChild = node.rightChild;
//以下所有父节点为空的情况,则表明删除的节点是根节点
if(leftChild == null && rightChild == null){//没有子节点
if(parent != null){
if(parent.leftChild == node){
parent.leftChild = null;
}else if(parent.rightChild == node){
parent.rightChild = null;
}
}else{//不存在父节点,则表明删除节点为根节点
root = null;
}
p = parent;
node = null;
flag = true;
}else if(leftChild == null && rightChild != null){// 只有右节点
if(parent != null && parent.val > val){// 存在父节点,且node位置为父节点的左边
parent.leftChild = rightChild;
}else if(parent != null && parent.val < val){// 存在父节点,且node位置为父节点的右边
parent.rightChild = rightChild;
}else{
root = rightChild;
}
p = parent;
node = null;
flag = true;
}else if(leftChild != null && rightChild == null){// 只有左节点
if(parent != null && parent.val > val){// 存在父节点,且node位置为父节点的左边
parent.leftChild = leftChild;
}else if(parent != null && parent.val < val){// 存在父节点,且node位置为父节点的右边
parent.rightChild = leftChild;
}else{
root = leftChild;
}
p = parent;
flag = true;
}else if(leftChild != null && rightChild != null){// 两个子节点都存在
Node successor = getSuccessor(node);// 这种情况,一定存在后继节点
int temp = successor.val;
boolean delete = delete(temp);
if(delete){
node.val = temp;
}
p = successor;
successor = null;
flag = true;
}
if(flag){
rebuild(p);
}
return flag;
} /**
* 搜索节点
* @param val
* @return
*/
public Node getNode(int val){
Node temp = root;
int t;
do{//直接使用循环遍历的方法
t = temp.val-val;
if(t > 0){
temp = temp.leftChild;
}else if(t < 0){
temp = temp.rightChild;
}else{
return temp;
}
}while(temp != null);
return null;
} //获取后继节点
private Node getSuccessor(Node node){
if(node.rightChild != null){
Node rightChild = node.rightChild;
while(rightChild.leftChild != null){
rightChild = rightChild.leftChild;
}
return rightChild;
}
Node parent = node.parent;
while(parent != null && (node == parent.rightChild)){
node = parent;
parent = parent.parent;
}
return parent;
} /**
* 平衡二叉树节点遍历
* @param type 0前序,1中序,2后续,3层序
*/
public void print(int type){
if(type==0){//前序
printPre(root);
}else if(type==1){
printMid(root);
}else if(type==2){
printEnd(root);
}else if(type==3){
printLevel(root);
}
} //前序遍历
private void printPre(Node root){
if(root != null){
System.out.println(root.val);// 位置在中间,则中序,若在前面,则为先序,否则为后续
printPre(root.leftChild);
printPre(root.rightChild);
}
} //中序遍历
private void printMid(Node root){
if(root != null){
printMid(root.leftChild);
System.out.println(root.val);// 位置在中间,则中序,若在前面,则为先序,否则为后续
printMid(root.rightChild);
}
} //后序遍历
private void printEnd(Node root){
if(root != null){
printEnd(root.leftChild);
printEnd(root.rightChild);
System.out.println(root.val);// 位置在中间,则中序,若在前面,则为先序,否则为后续
}
} //层次遍历
private void printLevel(Node root){
if(root == null){
return;
}
Queue<Node> queue = new LinkedList<>();
Node temp = null;
queue.add(root);
while(!queue.isEmpty()){
temp = queue.poll();
System.out.print("节点值:"+temp.val+",平衡值:"+calcNodeBalanceValue(temp)+"\n");
if(temp.leftChild != null){
queue.add(temp.leftChild);
}
if(temp.rightChild != null){
queue.add(temp.rightChild);
}
}
}
}

图2,BalanceBinaryTree.java结构图

3,JavaDemo.java

 package com.cnblogs.mufasa.BalanceBinaryTree;

 public class JavaDemo {
public static void main(String[] args) {
BalanceBinaryTree bbt=new BalanceBinaryTree();
// bbt.put(10);
// bbt.put(9);
// bbt.put(11);
// bbt.put(7);
// bbt.put(12);
// bbt.put(8);
// bbt.put(38);
// bbt.put(24);
// bbt.put(17);
// bbt.put(4);
// bbt.put(3); bbt.put(11);
bbt.put(7);
bbt.put(15);
bbt.put(4);
bbt.put(9);
bbt.put(10);
bbt.print(3);
}
}

4,特别鸣谢

https://www.cnblogs.com/qm-article/p/9349681.html

数据结构-平衡二叉树Java实现的更多相关文章

  1. 数据结构与算法——常用高级数据结构及其Java实现

    前文 数据结构与算法--常用数据结构及其Java实现 总结了基本的数据结构,类似的,本文准备总结一下一些常见的高级的数据结构及其常见算法和对应的Java实现以及应用场景,务求理论与实践一步到位. 跳跃 ...

  2. 什么是泛型?,Set集合,TreeSet集合自然排序和比较器排序,数据结构-二叉树,数据结构-平衡二叉树

    ==知识点== 1.泛型 2.Set集合 3.TreeSet 4.数据结构-二叉树 5.数据结构-平衡二叉树 ==用到的单词== 1.element[ˈelɪmənt] 要素 元素(软) 2.key[ ...

  3. 数据结构-堆 Java实现

    数据结构-堆 Java实现. 实现堆自动增长 /** * 数据结构-堆. 自动增长 * */ public class Heap<T extends Comparable> { priva ...

  4. 20172332 2017-2018-2 《程序设计与数据结构》Java哈夫曼编码实验--哈夫曼树的建立,编码与解码

    20172332 2017-2018-2 <程序设计与数据结构>Java哈夫曼编码实验--哈夫曼树的建立,编码与解码 哈夫曼树 1.路径和路径长度 在一棵树中,从一个结点往下可以达到的孩子 ...

  5. 数据结构(java语言描述)

    概念性描述与<数据结构实例教程>大同小异,具体参考:http://www.cnblogs.com/bookwed/p/6763300.html. 概述 基本概念及术语 数据 信息的载体,是 ...

  6. 数据结构:JAVA实现二叉查找树

    数据结构:JAVA实现二叉查找树 写在前面 二叉查找树(搜索树)是一种能将链表插入的灵活性与有序数组查找的高效性结合在一起的一种数据结构. 观察二叉查找树,我们发现任何一个节点大于左子节点且小于其右子 ...

  7. 【数据结构】Java版

    有趣有内涵的文章第一时间送达! 喝酒I创作I分享 生活中总有些东西值得分享 @醉翁猫咪 想你吴亦凡;赵丽颖 - 想你 你是程序猿对吗?会写代码的那种? 我是打字猿?会打代码的那种? 现在告诉大家一个很 ...

  8. 数据结构-平衡二叉树 旋转过程平衡因子分析 c和java代码实现对比

    平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且 ...

  9. Java数据结构——平衡二叉树的平衡因子(转自牛客网)

    若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性.首先要找出插入新结点后失去平衡的最小子树根结点的指针.然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树.当失去平衡的最小子树被 ...

随机推荐

  1. 咏南中间件D7客户端演示

    咏南中间件D7客户端演示 咏南中间件MORMOT(http.sys)支持D6.D7等老版本开发客户端.客户端使用TClientDataSet内存表控件,数据序列使用TynSerial类.

  2. Python-文件读写及修改

    文件的读写有三种形式:读.写和追加. 一.读模式 r 和读写模式 r+ 1.读模式 r 读模式r特点:(1)只能读,不能写:(2)文件不存在时会报错. (1)例:读取当前目录下的books.txt文件 ...

  3. SQL-W3School-函数:SQL GROUP BY 语句

    ylbtech-SQL-W3School-函数:SQL GROUP BY 语句 1.返回顶部 1. 合计函数 (比如 SUM) 常常需要添加 GROUP BY 语句. GROUP BY 语句 GROU ...

  4. 常用学习&面试资源网站

    https://github.com/MZCretin/RollToolsApi  开源通用API https://github.com/SenhLinsh/Android-Hot-Libraries ...

  5. R-CNN论文学习

    Rich feature hierarchies for accurate object detection and semantic segmentation Tech report (v5) pr ...

  6. RocketMQ共包含9个模块

    rocketmq-common:通用的枚举.基类方法.或者数据结构,包名有admin.consumer.filter.hook.message rocketmq-remoting:使用netty的客户 ...

  7. 关于类似QQ的展开和折叠效果的实现

    介绍: 1.两级折叠与展开: 实现原理如下: 1>通过表视图的组的头视图和单元格实现; 2>通过改变cell的高度实现; 3>通过cell实现; 实现 UITableView 的ce ...

  8. mysql创建数据库、表、写数据

    mysql> create database ceshi; Query OK, 1 row affected (0.01 sec) 给数据库授权,否则程序时无法连接ceshi数据库的,每次创建一 ...

  9. golang web框架 beego 学习 (七)json转数组

    Modules type User struct { Id int64 `json:"id"` Name string `json:"name"` Email ...

  10. java调用jacob组件实现word转pdf,HTML等出现的问题

    1.部署项目的服务器上必须安装WPS或Word office: 2.将jacob.jar文件放入%JAVA_HOME%\jre中: 3.将.dll文件放入%JAVA_HOME%\jre\bin中: 4 ...