主要实现思路为左旋转和右旋转
代码
package com.atguigu.avlTreeDemo;
import java.util.Objects;
/**
* avl树:平衡二叉树
*/
public class AvlTreeDemo {
public static void main(String[] args) {
//左旋转测试开始
/* int[] arr = {4,3,6,5,7,8};
AvlTree avlTree = new AvlTree();
for (int num:arr) {
avlTree.add(new Node(num));
}
System.out.println("树的前序遍历结果为");
avlTree.infixOrder();
System.out.println("根节点为" + avlTree.root);
System.out.println("树的高度为" + avlTree.hight());
System.out.println("树的左子树高度为" + avlTree.leftHight());
System.out.println("树的右子树高度为" + avlTree.rightHight());*/
//左旋转测试结束
/*//右旋转测试开始
int[] rightRotate = {10,12,8,9,7,6};
AvlTree rightTree = new AvlTree();
for (int num:rightRotate) {
rightTree.add(new Node(num));
}
System.out.println("右旋转测试数的中序遍历结果为");
rightTree.infixOrder();
System.out.println("树的根节点为" + rightTree.root + "\n树的高度为" + rightTree.hight() +
"\n树的左子树的高度为" +rightTree.leftHight() + "\n树的右子树的高度为" + rightTree.rightHight());
//右旋转测试结束*/
//双旋转测试开始
int[] rightRotate = {10,11,7,6,8,9};
AvlTree rightTree = new AvlTree();
for (int num:rightRotate) {
rightTree.add(new Node(num));
}
System.out.println("右旋转测试数的中序遍历结果为");
rightTree.infixOrder();
System.out.println("树的根节点为" + rightTree.root + "\n树的高度为" + rightTree.hight() +
"\n树的左子树的高度为" +rightTree.leftHight() + "\n树的右子树的高度为" + rightTree.rightHight());
//双旋转测试结束
}
}
/**
* 平衡二叉树的主体
*/
class AvlTree{
public Node root;
public AvlTree() {
}
public AvlTree(Node root) {
this.root = root;
}
/**
* 此方法为左旋转的方法
* 步骤:
* 1、创建一个新的节点:值为根节点的值
* 2、新节点的右子节点为根节点的右节点的左节点
* 3、新节点的左子节点为根节点的左节点
* 4、将根节点的右节点的值赋值给根节点
* 5、根节点的右节点为右节点的右节点
* 6、根节点的左节点为新节点
*/
public void leftRotate(){
if (root == null){
return;
}
root.leftRotate();
}
//添加节点
public void add(Node node){
if (root == null) {
root = node;
} else {
root.add(node);
}
}
//树的高度
public int hight(){
return root == null?0:root.hight();
}
//树的左子树的高度
public int leftHight(){
return root == null?0:root.leftHight();
}
//树的左子树的高度
public int rightHight(){
return root == null?0:root.righttHight();
}
//删除节点
public void del(int values){
//查看待删除的节点是否存在
if (searchNode(values) == null){
System.out.println("待删除的节点不存在");
}else {
Node delNode = searchNode(values);//寻找到待删除的节点
Node parent = searchParent(values);
boolean flag1 = (delNode.left != null);
boolean flag2 = (delNode.right != null);
boolean flagpar = !(parent == null);
Node temp;
if (!flag1 && !flag2){//如果待删除的节点是叶子结点,没有子节点
if (parent == null){//待删除的是根节点
root =null;
}else {//有父节点
if (parent.left != null && parent.left.equals(delNode)){
parent.left = null;
}else if (parent.right != null && parent.right.values == values){
parent.right = null;
}
}
}else if ( (flag1 && !flag2 )//如果删除的节点有一个子节点
||(!flag1 && flag2)){//只有一个子节点
if (flag1 && !flagpar){//没有父节点且左边有一个子节点,即根节点
root = delNode.left;
/*delNode.left = null;
delNode = temp;*/
}else if (flag1 && flagpar){//有父节点且左边有一个子节点
if (parent.left != null && parent.left.values == values){//目标节点是父节点的左子节点
parent.left = delNode.left;
}else if (parent.right != null && parent.right.values == values){//目标节点是父节点的左子节点
parent.right = delNode.left;
}
}else if (flag2 && !flagpar){//没有父节点且右边有一个子节点,即根节点
root = delNode.right;
/*delNode.right = null;
delNode = temp;*/
}else if (flag2 && flagpar){//有父节点且右边有一个子节点
if (parent.left != null && parent.left.values == values){//目标节点是父节点的左子节点
parent.left = delNode.right;
}else if (parent.right != null && parent.right.values == values){//目标节点是父节点的左子节点
parent.right = delNode.right;
}
}
}else if (flag1 && flag2){//如果待删除的节点有两个子节点
/* temp = delNode.right.fingMin();//法一:从右边寻找最小的
del(delNode.right.fingMin().values);
delNode.values = temp.values;*/
//法二:从左边找最大的
temp = delNode.left.fingMax();
del(delNode.left.fingMax().values);
delNode.values = temp.values;
}
}
}
//查找等待删除的节点是否存在
public Node searchNode(int values){
if (root.values == values){
return root;
}else{
return root.search(values);
}
}
//查找待删除的节点的父节点
public Node searchParent(int values){
if (root.values == values){
return null;
}else {
return root.searchParents(values);
}
}
//中序遍历
public void infixOrder(){
if (root == null){
System.out.println("空树");
}else{
root.infixOrder();
}
}
}
/**
* 节点
*/
class Node{
public int values;//节点对应的值
Node left;//左子节点
Node right;//右子节点
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node node = (Node) o;
return values == node.values;
}
/**
* 左旋转的方法
* 步骤:
* 1、创建一个新节点(值为当前节点)
* 2、 新节点左节点为原来的左节点
* 3、新节点的右节点为原来右节点的左节点
* 4、原来左节点连接新节点
* 5、原来节点值为原右节点值
* 6、原来右节点为右节点的右节点
*/
public void leftRotate(){
Node newNode = new Node(values);
newNode.left = left;
newNode.right = right.left;
left = newNode;
this.values = right.values;
right = right.right;
}
/**
* 右旋转的方法
* 1、创建新节点(值为当前节点)
* 2、新节点右节点为当前节点的右节点
* 3、新节点左节点为当前左节点的右节点
* 4、当前节点值改为左节点的值
* 5、当前右节点为新节点
* 6、当前左节点为左节点的左节点
*/
public void rightRotate(){
Node newNode = new Node(values);
newNode.right = right;
newNode.left =left.right;
this.values = left.values;
right = newNode;
left = left.left;
}
//得到以该节点为根节点的子树的高度
public int hight(){
return Math.max((left == null? 1: left.hight() + 1),
(right == null? 1:right.hight() +1));
}
//得到该节点的左子树的子树高度
public int leftHight(){
return (left == null)? 0: left.hight();
}
//得到该节点的右子树的子树高度
public int righttHight(){
return (right == null)? 0: right.hight();
}
//寻找一个节点下面的最小的节点
public Node fingMin(){
if (this.left == null ){
return this;
}else {
return this.left.fingMin();
}
}
//寻找一个节点下面的最大的节点
public Node fingMax(){
if (this.right == null ){
return this;
}else {
return this.right.fingMax();
}
}
@Override
public int hashCode() {
return Objects.hash(values);
}
//查找待删除的节点是否存在
public Node search(int values){
if (this.values == values){
return this;
}else if (this.left != null && this.values > values){
return this.left.search(values);
}else if (this.right != null && this.values <= values){
return this.right.search(values);
}else {
return null;
}
}
//查找待删除节点的父节点
public Node searchParents(int values){
if (this.values == values){
return null;
}
if ((this.left != null && this.left.values == values) ||
this.right != null && this.right.values == values ){
return this;
}else if (this.left != null && this.values > values){
return this.left.searchParents(values);
}else if (this.right != null && this.values <= values){
return this.right.searchParents(values);
}else {
return null;
}
}
public Node(Node left) {
this.left = left;
}
public Node(int values) {
this.values = values;
}
//中序遍历
public void infixOrder(){
if (this.left != null){
this.left.infixOrder();
}
System.out.println(this);
if (this.right != null){
this.right.infixOrder();
}
}
//添加节点的方法
public void add(Node node){
if (node == null){
return;
}else{
if (node.values < this.values){
if (this.left == null){
this.left = node;
}else{
this.left.add(node);
}
}else{
if ((this.right == null)) {
this.right = node;
} else {
this.right.add(node);
}
}
if (righttHight() - leftHight() > 1){//当添加完一个节点后,右子树的高度比左子树高出超过1以及以上,进行左旋转
if (right != null && right.leftHight() > right.righttHight()){
right.leftRotate();
}
leftRotate();
}else if (leftHight() - righttHight() > 1){//当添加完一个节点后,左子树的高度比左子树高出超过1以及以上,进行右旋转
if (left != null && left.righttHight() > left.leftHight()){
left.leftRotate();
}
rightRotate();
}
}
}
@Override
public String toString() {
return "Node{" +
"values=" + values +
'}';
}
}