Java实现平衡二叉树(AVL树)
2017-12-21 17:01
736 查看
一、定义
AVL树:左右子树高度之差的绝对值不超过1的二叉排序树平衡因子:左子树的高度减去右子树的高度的差
失去平衡的最小子树:以距离插入结点最近,且平衡因子绝对值大于1的结点作为根的子树
二、插入、调整操作
2.1 定义结点private TreeNode<T> root;//根节点 private Comparator<? super T> cmp; //内部类 public static class TreeNode<T>{ T data; TreeNode<T> left; TreeNode<T> right; int height; TreeNode(T data, TreeNode<T> lt, TreeNode<T> rt){ data= data; left = lt; right = rt; height = 0; } }
2.2 插入节点
有必要解释下递归插入:
①递归结束的条件是
t==null,②最后的一个
insert方法的返回值是
new TreeNode<T>(x,null, null)知道这两个点就很好理解了
public void insert(T data){ root = insert(data, root); } /** * 插入节点,如果根节点不存在,则把待插入节点设为根节点 * @param x 待插入节点 * @param t 根节点 * @return */ private TreeNode<T> insert(T x, TreeNode<T> t){ if(t == null) return new TreeNode<T>(x, null, null); int compareResult = myCompare(x, t.data); if(compareResult < 0){//插入左子树 t.left = insert(x, t.left); if(height(t.left)-height(t.right) == 2){ if(myCompare(x, t.left.data) < 0) t = rotateWithLeftChild(t);//左左情况 else t = doubleWithLeftChild(t);//左右情况 } }else if(compareResult > 0){//插入右子树 t.right = insert(x, t.right); if(height(t.right)-height(t.left) == 2){ if(myCompare(x, t.right.data) < 0) t = doubleWithRightChild(t);//右左情况 else t = rotateWithRightChild(t);//右右情况 } } //更新height值 t.height = Math.max(height(t.left), height(t.right))+1; return t; }
2.3 LL 调整
/** * 可将LL情况变平衡,也可将RL情况变成RR * @param k2 * @return */ private TreeNode<T> rotateWithLeftChild(TreeNode<T> k2){ TreeNode<T> k1 = k2.left; k2.left = k1.right; // 将RL情况变成RR k1.right = k2; k2.height = Math.max(height(k2.left), height(k2.right)) + 1; k1.height = Math.max(height(k1.left), k2.height) + 1; return k1; }
2.4 LR 调整
/** * 左右情况(LR)、双旋转 * 1、先右右再左左 * @param k3 * @return */ private TreeNode<T> doubleWithLeftChild(TreeNode<T> k3){ try{ k3.left = rotateWithRightChild(k3.left); }catch(NullPointerException e){ throw e; } return rotateWithLeftChild(k3); }
2.5 RR 调整
/** * 可将RR情况变平衡,也可将LR情况变成LL * @param k2 * @return */ private TreeNode<T> rotateWithRightChild(TreeNode<T> k2){ TreeNode<T> k1 = k2.right; k2.right = k1.left;//将LR情况变成LL k1.left = k2; k2.height = Math.max(height(k2.left), height(k2.right)) + 1; k1.height = Math.max(height(k1.right), k2.height) + 1; return k1; }
2.6 RL 调整
/** * 右左情况(RL),双旋转 * 1、先左左再右右 * @param k3 * @return */ private TreeNode<T> doubleWithRightChild(TreeNode<T> k3){ try{ k3.right = rotateWithLeftChild(k3.right); }catch(NullPointerException e){ throw e; } return rotateWithRightChild(k3); }
2.7 删除节点
递归的结束条件:
t == null
/** * 删除节点 * @param x * @param t 根节点 * @return */ private TreeNode<T> remove(T x, TreeNode<T> t){ if(t == null) return null; int compareResult = myCompare(x, t.data); if(compareResult < 0){ t.left = remove(x, t.left); //左节点被删除,需要考虑不平衡的情况有:RR、RL if(height(t.right)-height(t.left) == 2){ TreeNode<T> r = t.right; if(height(r.left) < height(r.right)) t = rotateWithRightChild(t);//右右情况 else t = doubleWithRightChild(t);//右左情况 } }else if(compareResult > 0){ t.right = remove(x, t.right); //右节点被删除,需要考虑不平衡的情况有:LL、LR if(height(t.left)-height(t.right) == 2){ TreeNode<T> r = t.left; if(height(r.left) > height(r.right)) t = rotateWithLeftChild(t);//左左情况 else t = doubleWithLeftChild(t);//左右情况 } }else if(t.left != null && t.right != null){ //最小右节点替换不会造成不平衡 t.data = findMin(t.right).data; t.right = remove(t.data, t.right); }else{ t = (t.left != null)?t.left:t.right; } t.height = Math.max(height(t.left), height(t.right))+1; return t; }
2.7 完整代码
package com.demo10;
import java.util.Comparator;
public class AVLTreeDemo<T extends Comparable<? super T>> {
private TreeNode<T> root;
private Comparator<? super T> cmp;
/**
* 节点数据结构
* @author admin
* @param <T>
*/
public static class TreeNode<T>{
T data;
TreeNode<T> left;
TreeNode<T> right;
int height;
TreeNode(T data, TreeNode<T> lt, TreeNode<T> rt){
this.data= data;
this.left = lt;
this.right = rt;
this.height = 0;
}
}
/**
* 节点大小比较
* @param lhs
* @param rhs
* @return
*/
private int myCompare(T lhs, T rhs){
if(cmp != null)
return cmp.compare(lhs, rhs);
else
return ((Comparable)lhs).compareTo(rhs);
}
public void insert(T data){ root = insert(data, root); } /** * 插入节点,如果根节点不存在,则把待插入节点设为根节点 * @param x 待插入节点 * @param t 根节点 * @return */ private TreeNode<T> insert(T x, TreeNode<T> t){ if(t == null) return new TreeNode<T>(x, null, null); int compareResult = myCompare(x, t.data); if(compareResult < 0){//插入左子树 t.left = insert(x, t.left); if(height(t.left)-height(t.right) == 2){ if(myCompare(x, t.left.data) < 0) t = rotateWithLeftChild(t);//左左情况 else t = doubleWithLeftChild(t);//左右情况 } }else if(compareResult > 0){//插入右子树 t.right = insert(x, t.right); if(height(t.right)-height(t.left) == 2){ if(myCompare(x, t.right.data) < 0) t = doubleWithRightChild(t);//右左情况 else t = rotateWithRightChild(t);//右右情况 } } //更新height值 t.height = Math.max(height(t.left), height(t.right))+1; return t; }
/**
* 获取节点t高度
* @param t
* @return
*/
private int height(TreeNode<T> t){
return t == null ? -1 : t.height;
}
/** * 可将LL情况变平衡,也可将RL情况变成RR * @param k2 * @return */ private TreeNode<T> rotateWithLeftChild(TreeNode<T> k2){ TreeNode<T> k1 = k2.left; k2.left = k1.right; // 将RL情况变成RR k1.right = k2; k2.height = Math.max(height(k2.left), height(k2.right)) + 1; k1.height = Math.max(height(k1.left), k2.height) + 1; return k1; }
/** * 可将RR情况变平衡,也可将LR情况变成LL * @param k2 * @return */ private TreeNode<T> rotateWithRightChild(TreeNode<T> k2){ TreeNode<T> k1 = k2.right; k2.right = k1.left;//将LR情况变成LL k1.left = k2; k2.height = Math.max(height(k2.left), height(k2.right)) + 1; k1.height = Math.max(height(k1.right), k2.height) + 1; return k1; }
/** * 左右情况(LR)、双旋转 * 1、先右右再左左 * @param k3 * @return */ private TreeNode<T> doubleWithLeftChild(TreeNode<T> k3){ try{ k3.left = rotateWithRightChild(k3.left); }catch(NullPointerException e){ throw e; } return rotateWithLeftChild(k3); }
/** * 右左情况(RL),双旋转 * 1、先左左再右右 * @param k3 * @return */ private TreeNode<T> doubleWithRightChild(TreeNode<T> k3){ try{ k3.right = rotateWithLeftChild(k3.right); }catch(NullPointerException e){ throw e; } return rotateWithRightChild(k3); }
public void remove(T data){
root = remove(data, root);
}
/**
* 删除节点
* @param x
* @param t 根节点
* @return
*/
private TreeNode<T> remove(T x, TreeNode<T> t){
if(t == null)
return null;
int compareResult = myCompare(x, t.data);
if(compareResult < 0){
t.left = remove(x, t.left);
//左节点被删除,需要考虑不平衡的情况有:RR、RL
if(height(t.right)-height(t.left) == 2){
TreeNode<T> r = t.right;
if(height(r.left) < height(r.right))
t = rotateWithRightChild(t);//右右情况
else
t = doubleWithRightChild(t);//右左情况
}
}else if(compareResult > 0){
t.right = remove(x, t.right);
//右节点被删除,需要考虑不平衡的情况有:LL、LR
if(height(t.left)-height(t.right) == 2){
TreeNode<T> r = t.left;
if(height(r.left) > height(r.right))
t = rotateWithLeftChild(t);//左左情况
else
t = doubleWithLeftChild(t);//左右情况
}
}else if(t.left != null && t.right != null){
t.data = findMin(t.right).data;
t.right = remove(t.data, t.right);
}else{
t = (t.left != null)?t.left:t.right;
}
if(t!=null){
t.height = Math.max(height(t.left), height(t.right))+1;
}
return t;
}
private TreeNode<T> findMin(TreeNode<T> t){
if(t == null)
return null;
if(t.left == null)
return t;
return findMin(t.left);
}
private TreeNode<T> findMax(TreeNode<T> t){
if(t == null)
return null;
if(t.right == null)
return t;
return findMax(t.right);
}
/**
* 前序遍历
* @param tree
*/
private void preOrder(TreeNode<T> tree) {
if(tree != null) {
System.out.println(tree.data+" ");
preOrder(tree.left);
preOrder(tree.right);
}
}
public void preOrder() {
preOrder(root);
}
/**
* 中序遍历
* @param tree
*/
private void inOrder(TreeNode<T> tree) {
if(tree != null){
inOrder(tree.left);
System.out.println(tree.data+" ");
inOrder(tree.right);
}
}
public void inOrder() {
inOrder(root);
}
/**
* 后序遍历
* @param tree
*/
private void postOrder(TreeNode<T> tree) {
if(tree != null) {
postOrder(tree.left);
postOrder(tree.right);
System.out.println(tree.data+" ");
}
}
public void postOrder() {
postOrder(root);
}
}
相关文章推荐
- 平衡二叉树(AVL树)算法 Java实现
- java数据结构与算法之平衡二叉树(AVL树)的设计与实现
- java数据结构与算法之平衡二叉树(AVL树)的设计与实现
- java实现AVL树(一种自平衡二叉树)数据结构
- 数据结构--AVL树的insert()的Java实现
- 平衡二叉树的java实现
- java实现平衡二叉树的建立
- AVL树(三)之 Java的实现
- 平衡二叉树——AVL树的实现
- 平衡二叉树(AVL树)的简单实现
- AVL树-自平衡二叉查找树(Java实现)
- AVL树的java实现
- 树——平衡二叉树插入和查找的JAVA实现
- AVL树 Java实现
- Java实现平衡二叉树(AVLTree)的构建
- AVL树的Java实现(递归方法)
- java实现平衡二叉树(详细分析)
- 平衡二叉树(AVL)--查找、删除、插入(Java实现)
- AVL树Java实现,包括删除
- 平衡二叉树Java实现