1.定义节点对象
package com.wang.tree;
/**
* 二叉树节点类
* @description
* @author wang
* @date 2018年11月20日
*/
public class TreeNode {
private int data;
private TreeNode leftNode;
private TreeNode rightNode;
private TreeNode parentNode;
public TreeNode() {
super();
// TODO 自动生成的构造函数存根
}
public TreeNode(int data) {
super();
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public TreeNode getLeftNode() {
return leftNode;
}
public void setLeftNode(TreeNode leftNode) {
this.leftNode = leftNode;
}
public TreeNode getRightNode() {
return rightNode;
}
public void setRightNode(TreeNode rightNode) {
this.rightNode = rightNode;
}
public TreeNode getParentNode() {
return parentNode;
}
public void setParentNode(TreeNode parentNode) {
this.parentNode = parentNode;
}
}
2.工具类加入 插入、左旋、右旋等方法
package com.wang.tree;
/**
* 二叉平衡树(AVL树)
* @description
* @author wang
* @date 2018年11月20日
*/
public class AVLTreeUtil {
/**
* 判断二叉树是否是平衡二叉树
* 缺点:重复的计算子树的高度
* @param node (root根节点,迭代遍历)
* @return
*/
public static boolean isBalance=true;
public static boolean isBalanced(TreeNode node){
//如果是空树,则是平衡二叉树
if(null == node){
return true;
}
//如果不为空
//左子树或者右子树为空,则高度差肯定小于2则为平衡二叉树
if(null == node.getLeftNode() || null == node.getRightNode()){
return true;
}
//如果左子树或者右子树都不为空,则比较高度差
// 计算得到左子树的深度
int leftDepth = treeDepth(node.getLeftNode());
// 计算得到右子树的深度
int rightDepth = treeDepth(node.getRightNode());
// 如果高度差大于1,不满足平衡二叉的条件
if (Math.abs(leftDepth - rightDepth) > 1) {
return false;
}
// 判断左子树和右子树是否满足平衡二叉树的条件
return isBalanced(node.getLeftNode()) && isBalanced(node.getRightNode());
}
public static int treeDepth(TreeNode node){
if(null == node){
return 0;
}
//计算左子树的深度
int left = treeDepth(node.getLeftNode());
//计算右子树的深度
int right = treeDepth(node.getRightNode());
// 树root的深度=路径最长的子树深度 + 1
return left >= right ? (left + 1) : (right + 1);
}
/**
* 可以用后序遍历,从下到上遍历如果子树中任一不满足条件返回 false<p>
* 否则返回 true 这样每个节点的高度只会算一次
* @param node
* @return
*/
public static boolean isBalanced1(TreeNode node){
treeDepth1(node);
return isBalance;
}
public static int treeDepth1(TreeNode root){
if(root==null)
return 0;
int left=treeDepth1(root.getLeftNode());
//左子树高度
int right=treeDepth1(root.getRightNode());
//右子树高度
if(Math.abs(left-right)>1)
{
isBalance=false;
//只要有一个子树的左右子树的高度绝对值大于 1 isBalance=false
}
return Math.max(left, right)+1;
}
/**
* 向AVL树中插入数据
* @param root
* @param Data
*/
public static void add(TreeNode root, int data){
if(data < root.getData()){
if(root.getLeftNode() != null){
add(root.getLeftNode(),data);
}else{
TreeNode newLeftNode = new TreeNode(data);
root.setLeftNode(newLeftNode);
newLeftNode.setParentNode(root);
}
}else{
if(root.getRightNode() != null){
add(root.getRightNode(),data);
}else{
TreeNode newRightNode = new TreeNode(data);
root.setRightNode(newRightNode);
newRightNode.setParentNode(root);
}
}
//插入完成
//如果不再平衡,需要旋转
int balance = calculateBalance(root);
//左子树高,应该右旋(包括左左,左右)
if(balance >= 2){
//右孙高,先左旋(左右,旋转两次,先左旋再右旋)
if(calculateBalance(root.getLeftNode()) == -1){
left_rotate(root.getLeftNode());
}
//(左左,旋转一次,直接右旋)
right_rotate(root);
}
//右子树高,应该左旋(包括右右,右左)
if(balance <= -2){
//左孙高,先右旋(右左,旋转两次,先右旋再左旋)
if(calculateBalance(root.getRightNode()) == 1){
right_rotate(root.getRightNode());
}
//(右右,旋转一次,直接左旋)
left_rotate(root);
}
}
/**
* 插入新节点
* @param root
* @param data
*/
public static void insert(TreeNode root, int data){
if(data < root.getData()){
if(root.getLeftNode() != null){
insert(root.getLeftNode(),data);
}else{
TreeNode newLeftNode = new TreeNode(data);
root.setLeftNode(newLeftNode);
newLeftNode.setParentNode(root);
}
}else{
if(root.getRightNode() != null){
insert(root.getRightNode(),data);
}else{
TreeNode newRightNode = new TreeNode(data);
root.setRightNode(newRightNode);
newRightNode.setParentNode(root);
}
}
}
/**
* 计算平衡因子(左右子树高度(深度)之差)
* @param root
* @return
*/
public static int calculateBalance(TreeNode root){
if(root == null){
return 0;
}
//计算左子树的深度
int left = treeDepth(root.getLeftNode());
//计算右子树的深度
int right = treeDepth(root.getRightNode());
return (left-right);
}
/**
* 左旋
* @param root
*/
public static void left_rotate(TreeNode p){
//父节点
TreeNode pParent = p.getParentNode();
//右子节点
TreeNode pRight = p.getRightNode();
//右子节点的左节点(孙节点)
TreeNode pRightLeft = pRight.getLeftNode();
//右子节点变父
pRight.setParentNode(pParent);
if(pParent != null){
if(p == pParent.getLeftNode()){
pParent.setLeftNode(pRight);
}else if(p == pParent.getRightNode()){
pParent.setRightNode(pRight);
}
}
pRight.setLeftNode(p);
p.setParentNode(pRight);
//右左孙变右子
p.setRightNode(pRightLeft);
if(pRightLeft != null){
pRightLeft.setParentNode(p);
}
}
/**
* 右旋
* @param root
*/
public static void right_rotate(TreeNode p){
//父节点
TreeNode pParent = p.getParentNode();
//左子节点
TreeNode pLeft = p.getLeftNode();
//左子节点的右节点(孙节点)
TreeNode pLeftRight = pLeft.getRightNode();
//左子变父
pLeft.setParentNode(pParent);
//判断p原来是pParent的左子还是右子,并改为赋予pLeft
if(pParent != null){
if(p == pParent.getLeftNode()){
pParent.setLeftNode(pLeft);
}else if(p == pParent.getRightNode()){
pParent.setRightNode(pLeft);
}
}
pLeft.setRightNode(p);
p.setParentNode(pLeft);
//左右孙变左子
p.setLeftNode(pLeftRight);
if(pLeftRight != null){
pLeftRight.setParentNode(p);
}
}
/**
* 前序遍历 中--左--右(DLR)
* @param root
*/
public static void preorderTraversal(TreeNode root){
if(root != null){
System.out.println(root.getData() +"->");
preorderTraversal(root.getLeftNode());
preorderTraversal(root.getRightNode());
}
}
/**
* 中序遍历 左--中--右(LDR)
* @param root
*/
public static void inorderTraversal(TreeNode root){
if(root != null){
inorderTraversal(root.getLeftNode());
System.out.println(root.getData() +"->");
inorderTraversal(root.getRightNode());
}
}
/**
* 后序遍历 左--右--中(LRD)
* @param root
*/
public static void postorderTraversal(TreeNode root){
if(root != null){
postorderTraversal(root.getLeftNode());
postorderTraversal(root.getRightNode());
System.out.println(root.getData() +"->");
}
}
}
3.测试代码
package com.wang.tree;
/**
* 测试二叉平衡树插入
* @description
* @author wang
* @date 2018年11月22日
*/
public class AVLTreeTest2 {
public static void main(String[] args) {
TreeNode root = new TreeNode(5);
TreeNode node2 = new TreeNode(3);
TreeNode node3 = new TreeNode(6);
TreeNode node4 = new TreeNode(1);
TreeNode node5 = new TreeNode(4);
root.setLeftNode(node2);
root.setRightNode(node3);
node2.setParentNode(root);
node2.setLeftNode(node4);
node2.setRightNode(node5);
node4.setParentNode(node2);
node5.setParentNode(node2);
System.out.println("=====开始中序遍历=====");
AVLTreeUtil.inorderTraversal(root);
AVLTreeUtil.add(root, 2);
System.out.println("=====开始中序遍历=====");
AVLTreeUtil.inorderTraversal(node2);
}
}
输出结果:
=====开始中序遍历=====
1->
3->
4->
5->
6->
=====开始中序遍历=====
1->
2->
3->
4->
5->
6->