java实现二叉平衡树

本文深入探讨了二叉平衡树的定义,不平衡二叉树转为平衡二叉树的策略,以及通过旋转调整树平衡的具体算法。介绍了树高度的概念,不平衡子树的查找和调整方法,特别是针对不同不平衡情况的旋转处理,包括单旋转和双旋转,以及如何在算法设计中避免常见错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 二叉平衡树定义
    二叉树中所有子树的左右子树的高度差不超过1

  2. 树的高度
    从所有叶节点开始数高度到根节点,其中的最大值即为树的高度

  3. 非平衡二叉树转成平衡二叉树(思路)

  1. 找出所有不平衡的子树,将不平衡子树的根节点记录下来.
  2. 调节位于最下方的子树,使之平衡
  3. 重复1,2步,直到这棵树平衡
    每次调整只调整节点数最少的子树,节点少的子树大部分情况都为4中的基本情况
  1. 二叉树的调节(旋转)
    不平衡的情况(符合二叉树的规则大的节点在右边,小的在左)
    图一
    在这里插入图片描述
    图二
    在这里插入图片描述

图一中
1,2两种情况,分别以中间的节点为旋转中心顺时针(1),逆时针(2)将根节点旋转到中间节点的下方.(两种情况对应)
3,4两种情况,将最下方的节点作为根节点,分别将根节点,中间节点作为最下方节点的左右子节点.(两种情况对应)
处理图:(四种情况中列出两种,其余两种对应)
在这里插入图片描述

图二中
1(ll),2(rr)两种情况,分别以根节点的左子节点(1),右子节点(2)为旋转中心,将跟节点选装至他子节点的下方,子节点的右(左)子节点,称为根节点的左(右)子节点.(两种情况对应)

3(lr),4(rl)两种情况,以最下方的叶子节点的父节点为旋转中心,将跟节点的左(右)子节点旋转至其父节点的下方,这样3,4两种情况就转化成了1,2两种情况,再用处理1,2两种情况的方法处理.(两种情况对应)
处理图:(四种情况中列出两种,其余两种对应)在这里插入图片描述

其余情况:最小的不平衡子树的高度超过4
在这里插入图片描述

只需将根节点旋转至节点少的这一侧即可

  1. 算法设计及实现

了解了大致情况,要转换成二叉树,节点的变换,
(1)左右节点变化(是否从有到无或者从无到有),过程中很可能忘记setRight(null)操作,这样这棵树就完全乱了.我的User类中在设置左右节点时,就将左右节点的父节点设置成当前节点

public void setLeft(User faust) {
		
		this.left = faust;
		if(faust != null)
			faust.head = this;
		
	}

	public void setRight(User pippin) {
		
		this.right = pippin;
		if(pippin != null)
			pippin.head = this;
	}

(2)根节点是否改变,根节点没有父节点要setHead(null); root = user;这两步操作

计算树的高度

public int getDepth(User treeRoot){
		
		if(treeRoot == null)
			return 0;
		
		return Math.max(getDepth(treeRoot.getLeft()), getDepth(treeRoot.getRight()))+1;
		
	}

判断是否为平衡二叉树

ArrayList<User> avlUsers = new ArrayList<User>();
int l;//每次记录的是最后一次判断的子树的根
public boolean isAvl(User treeRoot){
		if(treeRoot == null)
			return true;
		if(Math.abs(getDepth(treeRoot.getLeft())-getDepth(treeRoot.getRight()))>1){
			avlUsers.add(treeRoot);//记录不平衡子树的根节点
			if(getDepth(treeRoot.getLeft())>getDepth(treeRoot.getRight()))
				l = 1;//左边子树高导致的不平衡
			else {
				l = 0;//右边子高导致的不平衡
			}
			return false;
		}
		else 
			return isAvl(treeRoot.getLeft())&&isAvl(treeRoot.getRight());//左右子树都平衡,这棵树才平衡
	}

调节算法

public void toAVL(User user){
		
		User insertUser = user.getHead();
		User insertUserHead = insertUser.getHead();
		
		
		if(insertUserHead.getRight() == null || insertUserHead.getLeft()==null){//单转
			treeRoate(user, insertUser, insertUserHead);
			
		}else {
			User p = insertUserHead.getHead();
			int g = getDepth(avlUsers.get(avlUsers.size()-1));
			if (g<5) {
				if(insertUserHead == p.getLeft() && insertUser == insertUserHead.getRight()){//图二中的3,lr
					
					//先单转
					treeRoate(user, insertUser, insertUserHead);
					
					treeRoateLL(p.getLeft().getLeft(), p.getLeft());
				}
				
				else if(insertUserHead == p.getRight() && insertUser == insertUserHead.getLeft()){//图二中的4,rl
					//先单转
					treeRoate(user, insertUser, insertUserHead);
					
					treeRoateLL(p.getRight().getRight(), p.getRight());
				}
			}else//图二中的1,2情况,其余情况
				treeRoateLL(insertUser, insertUserHead);
		}
	}

图一中情况处理

public void treeRoate(User user,User insertUser,User insertUserHead){
		if(user==insertUser.getRight()&&insertUser == insertUserHead.getRight()){//rr
			
			if(insertUserHead == root){
				insertUser.setHead(null);
				root = insertUser;
				insertUser.setLeft(insertUserHead);
				insertUserHead.setRight(null);
			}else {
				User p = insertUserHead.getHead();
				if(p.getLeft() == insertUserHead)
					p.setLeft(insertUser);
				else
					p.setRight(insertUser);
				insertUser.setLeft(insertUserHead);
				insertUserHead.setRight(null);
			}
		}
		else if(user==insertUser.getLeft()&&insertUser == insertUserHead.getLeft()){//ll
			if(insertUserHead == root){
				insertUser.setHead(null);
				root = insertUser;
				insertUser.setRight(insertUserHead);
				insertUserHead.setLeft(null);
			}else {
				User p = insertUserHead.getHead();
				if(p.getLeft() == insertUserHead)
					p.setLeft(insertUser);
				else
					p.setRight(insertUser);
				insertUser.setRight(insertUserHead);
				insertUserHead.setLeft(null);
			}
		}
		else if(user==insertUser.getLeft()&&insertUser == insertUserHead.getRight()){//lr
			if(insertUserHead == root){
				user.setRight(insertUserHead);
				user.setLeft(insertUser);
				user.setHead(null);
				insertUserHead.setLeft(null);
				insertUser.setRight(null);
				root = user;
			}else {
				User p = insertUserHead.getHead();
				if(p.getLeft() == insertUserHead)
					p.setLeft(user);
				else
					p.setRight(user);
				
				user.setRight(insertUserHead);
				user.setLeft(insertUser);
				insertUserHead.setLeft(null);
				insertUser.setRight(null);
				
			}
		}
		else if(user==insertUser.getRight()&&insertUser == insertUserHead.getLeft()){//rl
			if(insertUserHead == root){
				user.setLeft(insertUserHead);
				user.setRight(insertUser);
				user.setHead(null);
				insertUserHead.setRight(null);
				insertUser.setLeft(null);
				root = user;
			}else {
				User p = insertUserHead.getHead();
				if(p.getLeft() == insertUserHead)
					p.setLeft(user);
				else
					p.setRight(user);
				
				user.setLeft(insertUserHead);
				user.setRight(insertUser);
				insertUserHead.setRight(null);
				insertUser.setLeft(null);
				
			}
		}
	}

其余情况和图二中的1,2情况处理

	public void treeRoateLL(User insertUser,User insertUserHead){
		
		User p = avlUsers.get(avlUsers.size()-1);
		User util;
		
		if(l == 0){//rr
			insertUserHead = p.getRight();
			//insertUser = insertUserHead.getRight();
			
			util = insertUserHead.getLeft();
			if(p == root){
				root = insertUserHead;
				insertUserHead.setLeft(p);
				insertUserHead.setHead(null);
				
				p.setRight(util);
			}else {
				
				User pHead = p.getHead();
				
				insertUserHead.setLeft(p);
				p.setRight(util);
				
				if(pHead.getLeft() == insertUserHead)
					pHead.setLeft(insertUserHead);
				else
					pHead.setRight(insertUserHead);
			}
		}
		else {//ll
			insertUserHead = p.getLeft();
			//insertUser = insertUserHead.getLeft();
			
			util = insertUserHead.getRight();
			if(p == root){
				root = insertUserHead;
				insertUserHead.setRight(p);
				insertUserHead.setHead(null);
				
				p.setLeft(util);
			}else {
				
				User pHead = p.getHead();
				
				insertUserHead.setRight(p);
				p.setLeft(util);
				
				if(pHead.getLeft() == insertUserHead)
					pHead.setLeft(insertUserHead);
				else
					pHead.setRight(insertUserHead);
			}
		}
		
	}

总函数

public boolean addAVL(User friend) throws IllegalArgumentException {
		
		if(friend == null){
			throw new IllegalArgumentException();
		}
		
		else {
			this.beFriend(friend);
			
			//清空list结合
			avlUsers.clear();
			
			/*if(isAvl(root) == false)
				toAVL(friend);*/
			User p = root;
			
			//用while循环遍历,将树中所有不平衡子树的根节点存在list集合中
			while(isAvl(p) == false){
				isAvl(p);
				if(l==1)
					p = avlUsers.get(avlUsers.size()-1).getLeft();
				else {
					p = avlUsers.get(avlUsers.size()-1).getRight();
				}
			}
			//如果list集合中有元素,说明树不平衡
			if(avlUsers.size()>0)
				toAVL(friend);
			return true;
		}
		
		return false;
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值