Avl平衡树的java代码实现
Avl平衡树的结点数据结构
public class AvlTreeNode {
private int val;
private int height;
private AvlTreeNode leftTree;
private AvlTreeNode rightTree;
public AvlTreeNode() {
}
public AvlTreeNode(int val) {
this.val = val;
}
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public AvlTreeNode getLeftTree() {
return leftTree;
}
public void setLeftTree(AvlTreeNode leftTree) {
this.leftTree = leftTree;
}
public AvlTreeNode getRightTree() {
return rightTree;
}
public void setRightTree(AvlTreeNode rightTree) {
this.rightTree = rightTree;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
@Override
public String toString() {
return "AvlTreeNode{" +
"val=" + val +
", height=" + height +
'}';
}
}
Avl树的代码结构
class AvlTree {
/**
* 树的根结点
*/
private AvlTreeNode rootTreeNode;
public AvlTreeNode search(int val) {
return search(val, rootTreeNode);
}
/**
* 前序遍历树
*/
private void preOrder(AvlTreeNode avlTreeNode){
if(null != avlTreeNode){
System.out.println(avlTreeNode);
}
if(avlTreeNode.getLeftTree() != null ){
preOrder(avlTreeNode.getLeftTree());
}
if(avlTreeNode.getRightTree() != null){
preOrder(avlTreeNode.getRightTree());
}
}
public void preOrder(){
preOrder(rootTreeNode);
}
private AvlTreeNode search(int val, AvlTreeNode avlTreeNode) {
if (null == avlTreeNode) {
return null;
}
if (avlTreeNode.getVal() == val) {
return avlTreeNode;
} else if (avlTreeNode.getVal() > val) {
return search(val, avlTreeNode.getLeftTree());
} else {
return search(val, avlTreeNode.getRightTree());
}
}
public void insert(int val) {
if (null == rootTreeNode) {
rootTreeNode = new AvlTreeNode(val);
rootTreeNode.setHeight(0);
return;
}
rootTreeNode = insert(val, rootTreeNode);
}
private AvlTreeNode insert(int val, AvlTreeNode avlTreeNode) {
if (null == avlTreeNode) {
avlTreeNode = new AvlTreeNode(val);
avlTreeNode.setHeight(0);
return avlTreeNode;
} else if (val == avlTreeNode.getVal()) {
throw new RuntimeException("val is exist, not add again!");
} else if (val > avlTreeNode.getVal()) {
avlTreeNode.setRightTree(insert(val, avlTreeNode.getRightTree()));
avlTreeNode.setHeight(Math.max(height(avlTreeNode.getLeftTree()), height(avlTreeNode.getRightTree())) + 1);
if(height(avlTreeNode.getRightTree()) - height(avlTreeNode.getLeftTree()) == 2){
if(val > avlTreeNode.getRightTree().getVal()){
//RR旋转
avlTreeNode = rightRightRotation(avlTreeNode);
}else{
avlTreeNode = rightLeftRotation(avlTreeNode);
}
}
} else {
//插入到左边
avlTreeNode.setLeftTree(insert(val, avlTreeNode.getLeftTree()));
avlTreeNode.setHeight(Math.max(height(avlTreeNode.getLeftTree()), height(avlTreeNode.getRightTree())) + 1);
if (height(avlTreeNode.getLeftTree()) - height(avlTreeNode.getRightTree()) == 2) {
if (val < avlTreeNode.getLeftTree().getVal()) {
//LL旋转
avlTreeNode = leftLeftRotation(avlTreeNode);
} else {
//LR型旋转
avlTreeNode = leftRightRotation(avlTreeNode);
}
}
}
return avlTreeNode;
}
/**
* 计算结点的高度
* @param avlTreeNode
* @return
*/
private int height(AvlTreeNode avlTreeNode) {
if (null == avlTreeNode) {
return 0;
}
return avlTreeNode.getHeight();
}
/**
* LL 旋转 【主要针对左树的左子树插入导致平衡被破坏】右旋
*
* 4[avlTreeNode] 2[key1]
* 2 5 1 4
* 1 3 0 3 5
* 0
* avlTreeNode为平衡被破坏的点,将其进行LL旋转重新获得平衡
*
* @param avlTreeNode
* @return
*/
private AvlTreeNode leftLeftRotation(AvlTreeNode avlTreeNode) {
AvlTreeNode key1;
key1 = avlTreeNode.getLeftTree();
avlTreeNode.setLeftTree(key1.getRightTree());
key1.setRightTree(avlTreeNode);
//计算重新移动过后的高度
avlTreeNode.setHeight(Math.max(height(avlTreeNode.getLeftTree()),height(avlTreeNode.getRightTree())) + 1);
key1.setHeight(Math.max(height(key1.getLeftTree()),avlTreeNode.getHeight()) + 1);
return key1;
}
/**
* RR 旋转 【主要针对右树的右子树插入 导致平衡被破坏】 左旋
*
* 1 【avlTreeNode】 3 【key1】
* 0 3 1 5
* 2 5 0 2 6
* 6
*
* avlTreeNode 为平衡被破坏的点,将其进行RR旋转重新获取平衡
*
* @param avlTreeNode
* @return
*/
private AvlTreeNode rightRightRotation(AvlTreeNode avlTreeNode){
AvlTreeNode key1;
key1 = avlTreeNode.getRightTree();
avlTreeNode.setRightTree(key1.getLeftTree());
key1.setLeftTree(avlTreeNode);
avlTreeNode.setHeight(Math.max(height(avlTreeNode.getLeftTree()),height(avlTreeNode.getRightTree())) + 1);
key1.setHeight(Math.max(height(avlTreeNode.getRightTree()),avlTreeNode.getHeight()) + 1);
return key1;
}
/**
* LR旋转【主要针对在左树的 右子树进行插入 导致平衡被破坏】
* A 先对A的左树进行RR旋转==>> A 再对A进行LL旋转 ====>> E
* [1] B C [1] E C B A
* D E B D H C
* H D H
*
* @param avlTreeNode
* @return
*/
private AvlTreeNode leftRightRotation(AvlTreeNode avlTreeNode){
avlTreeNode.setLeftTree(rightRightRotation(avlTreeNode.getLeftTree()));
return leftLeftRotation(avlTreeNode);
}
/**
* RL旋转
* 与LR对称 主要针对 右树的左子树插入导致平衡被破坏
* A 现对平衡被破坏的点A的右子树进行一次LL旋转 ====>> A 再对A进行一次RR旋转完成平衡 D
* B C B D A C
* D E F C B F E
* F E
*
*
* @param avlTreeNode
* @return
*/
private AvlTreeNode rightLeftRotation(AvlTreeNode avlTreeNode){
avlTreeNode.setRightTree(leftLeftRotation(avlTreeNode.getRightTree()));
return rightRightRotation(avlTreeNode);
}
/**
* 删除指定结点
* @param val
*/
public void deleteAvlTreeNode(int val){
if(null == rootTreeNode){
return;
}
rootTreeNode = deleteAvlTreeNode(val,rootTreeNode);
}
public AvlTreeNode deleteAvlTreeNode(int val,AvlTreeNode avlTreeNode){
if(null == avlTreeNode) {
return null;
}
if(val == avlTreeNode.getVal()){
//找到为当前结点 进行删除
if(avlTreeNode.getLeftTree() != null && null != avlTreeNode.getRightTree()){
//左子树比右子树高
if(height(avlTreeNode.getLeftTree()) > height(avlTreeNode.getRightTree())){
//找到该子树左子树中最大的结点
AvlTreeNode maxAvlTreeNode = maximum(avlTreeNode.getLeftTree());
avlTreeNode.setVal(maxAvlTreeNode.getVal());
avlTreeNode.setLeftTree(deleteAvlTreeNode(maxAvlTreeNode.getVal(),avlTreeNode.getLeftTree()));
}else{
//右子树比左子树高或者相等
AvlTreeNode minTreeNode = minimum(avlTreeNode.getRightTree());
avlTreeNode.setVal(minTreeNode.getVal());
avlTreeNode.setRightTree(deleteAvlTreeNode(minTreeNode.getVal(),avlTreeNode.getRightTree()));
}
}else{
avlTreeNode = avlTreeNode.getLeftTree() == null ? avlTreeNode.getRightTree() : avlTreeNode.getLeftTree();
}
}else if(val < avlTreeNode.getVal()){
avlTreeNode.setLeftTree(deleteAvlTreeNode(val,avlTreeNode.getLeftTree()));
//删除之后判断是否树失去平衡 删除的节点在树的左边
if(height(avlTreeNode.getRightTree()) - height(avlTreeNode.getLeftTree()) == 2){
//删除导致不平衡则进行旋转 因为被影响的右子树的高度高于左子树
//则需要判断 右子树的左子树高 还是右子树高
AvlTreeNode rTreeNode = avlTreeNode.getRightTree();
if(height(rTreeNode.getLeftTree()) > height(rTreeNode.getRightTree())){
//符合RL情况
//解释: 如果平衡被影响的结点的 右结点的的右左子树高于 右右子树 则等同于 结点插入到右结点的左子树的情况符合(RL)
avlTreeNode = rightLeftRotation(avlTreeNode);
}else{
//符合RR情况
//解释: 如果平衡被影响的结点的 右结点的右左子树等于小于右右子树 则符合RR型插入结构
// A
// B C
// G D E
// F H
//
//如果G结点被删除 则A结点平衡型被影响 则通过查看A的右结点C的左右子树情况 判断影响平衡的结点满足的类型
// 右结点的左子树高度等于右结点的右子树 时:
// A C
// B C A E
// D E ==》 进型一个RR型左旋 B D H
// F H F
//右结点的 左子树高度小于右结点的右子树时
// A A C
// B C B C A E
// G D E ===》 删除结点G D E ===》 进行一次RR型左旋转 B D H
// H H
// 打到平衡 所以 符合LL型与LR型同此推理 通过递归达到局部平衡从而达到一个整体的平衡
avlTreeNode = rightRightRotation(avlTreeNode);
}
}
}else{
avlTreeNode.setRightTree(deleteAvlTreeNode(val,avlTreeNode.getRightTree()));
//删除之后判断是否树失去平衡 删除的节点在树的右边
if(height(avlTreeNode.getLeftTree()) - height(avlTreeNode.getRightTree()) == 2){
//删除导致不平衡则进行旋转
AvlTreeNode lTreeNode = avlTreeNode.getLeftTree();
if(height(lTreeNode.getRightTree()) > height(lTreeNode.getLeftTree())){
//被删除结点的 左边结点子树的高度 右子树如果高于左子树 则满足LR型
avlTreeNode = leftRightRotation(avlTreeNode);
}else{
//否则相等或者小于则舒服 LL型
avlTreeNode = leftLeftRotation(avlTreeNode);
}
}
}
if(null != avlTreeNode){
//如果没有左右子树则为叶子结点
if(null == avlTreeNode.getLeftTree() && null == avlTreeNode.getRightTree()){
avlTreeNode.setHeight(0);
}else{
avlTreeNode.setHeight(Math.max(height(avlTreeNode.getLeftTree()),height(avlTreeNode.getRightTree())) + 1);
}
}
return avlTreeNode;
}
/**
* 寻找指定结点子结点的 最大结点
* @param avlTreeNode
* @return
*/
private AvlTreeNode maximum(AvlTreeNode avlTreeNode){
if(null == avlTreeNode){
return null;
}
AvlTreeNode maxTreeNode = avlTreeNode;
while(maxTreeNode != null){
if(maxTreeNode.getRightTree() != null){
maxTreeNode = maxTreeNode.getRightTree();
}else{
return maxTreeNode;
}
}
return maxTreeNode;
}
/**
* 寻找指定结点的最小子结点
* @param avlTreeNode
* @return
*/
private AvlTreeNode minimum(AvlTreeNode avlTreeNode){
if(null == avlTreeNode){
return null;
}
AvlTreeNode minTreeNode = avlTreeNode;
while(null != minTreeNode){
if(null != minTreeNode.getLeftTree()){
minTreeNode = minTreeNode.getLeftTree();
}else{
return minTreeNode;
}
}
return minTreeNode;
}
}
测试代码
class Main{
public static void main(String[] args) {
AvlTree avlTree = new AvlTree();
// 6
// 3 10
// 2 4 7
//1
avlTree.insert(6);
avlTree.insert(3);
avlTree.insert(10);
avlTree.insert(7);
avlTree.insert(2);
avlTree.insert(4);
avlTree.insert(1);
avlTree.preOrder();
System.out.println("================");
avlTree.deleteAvlTreeNode(7);
System.out.println("================");
avlTree.preOrder();
System.out.println(avlTree.search(3));
}
}