平衡二叉树(AVL)Java实现

平衡二叉树:

平衡二叉树(AVL)是带平衡条件的二叉树,即每个节点的左子树和右子树高度最多差一的二叉查找树。

节点:

因为AVL必须保证左右两颗子数的平衡,所以定义一个高度变量表示该树的高度。再加上左右子树构成AVL的节点。

	private class AvlNode{
		public int element;
		public AvlNode left;
		public AvlNode right;
		int height;
		private AvlNode(int a,AvlNode b,AvlNode c) {
			element = a;
			left=b;
			right=c;
			height=0;
		}
		public AvlNode(int a) {
			this(a, null, null);
		}
	}

插入:

在插入之后,只有那些从插入点到根结点的路径上的节点的平衡可能被改变,因为只有这些节点的子树可能发生变化,后续也只需要对这些节点进行平衡操作。
因为二叉树最多两个节点,所有插入后影响平衡的情况只有四种:
插入左节点的左子树中 LL 右旋
插入左节点的右子树中 LR 左旋再右旋
插入右子树的右子树中 RR 左旋
插入右子树的左子树中 RL 先右旋再左旋

以上内容转自维基百科AVL树
同二叉查找树的插入,但是每次插入后都要对该节点到根结点的所有节点进行平衡操作。

	private AvlNode insert(int a,AvlNode t) {
		if(t==null) {
			return new AvlNode(a);
		}
		if(a<t.element) {
			t.left = insert(a, t.left);
		}else if(a>t.element) {
			t.right = insert(a, t.right);
		}else {
			//一样不用插入
		}
		return balance(t);
	}

平衡函数:

	private AvlNode balance(AvlNode t) {
		if(t==null) {
			return t;
		}
		if(t.left.height>t.right.height) {
			if(height(t.left.left)>=height(t.left.right)) {
				t=rotateWithLeftChild(t);//右旋
			}else {
				t=doubleWithLeftChild(t);//先左旋再右旋
			}
		}else if(t.right.element>t.left.element) {
			if(height(t.right.right)>=height(t.right.left)) {
				t=rotateWithRightChild(t);//左旋
			}else {
				t=doubleWithRightChild(t);//先右旋再左旋
			}
		}
		t.height = Math.max(t.left.height,t.right.height)+1;
		return t;
	}

左旋函数:

	private AvlNode rotateWithRightChild(AvlNode t) {
		AvlNode avlNode = t.right;
		t.right=avlNode.left;
		avlNode.left = t;
		t.height = Math.max(t.left.height, t.right.height);
		avlNode.height = Math.max(t.height, avlNode.right.height);
		return avlNode;
	}

右旋:

	private AvlNode rotateWithLeftChild(AvlNode t) {
		AvlNode avlNode  = t.left;
		t.left = avlNode.right;
		avlNode.right = t;
		t.height = Math.max(t.left.height, t.right.height)+1;
		avlNode.height = Math.max(avlNode.height, t.height)+1;
		return avlNode;
	}

先左旋再右旋:

	private AvlNode doubleWithLeftChild(AvlNode t) {
		t.left=rotateWithRightChild(t.left);
		rotateWithLeftChild(t);
		return t;
	}

先右旋再左旋:

	private AvlNode doubleWithRightChild(AvlNode t) {
		t.right=rotateWithLeftChild(t.right);
		rotateWithRightChild(t);
		return t;
	}

删除:

删除操作与插入类似,删除之后再做平衡就好。但是删除有一种特殊情况就是删除之后左子树或右子树的两个节点高度相等的情况,例如上图中左左情况经过右旋得到的下面的图,如果再将5节点删除就出现这种情况。
但是这种情况也只需要经过单旋就能得到,所有在上面平衡函数判断语句中加入=号。

	private AvlNode remove(int a,AvlNode t) {
		if(t==null) {
			return t;
		}
		if(a<t.element) {
			t.left = remove(a, t.left);
		}else if(a>t.element) {
			t.right = remove(a, t.right);
		}else {
			if(t.left!=null&&t.right!=null) {
				t.element = findMin(t.right).element;
				t.right = remove(findMin(t.right).element, t.right);
			}else {
				t= (t.left!=null)?t.left:t.right;
			}
		}
		return balance(t);
		
	}

AVL

public class BlanceTree {
	
	
	private AvlNode insert(int a,AvlNode t) {
		if(t==null) {
			return new AvlNode(a);
		}
		if(a<t.element) {
			t.left = insert(a, t.left);
		}else if(a>t.element) {
			t.right = insert(a, t.right);
		}else {
			
		}
		return balance(t);
	}
	
	private int height(AvlNode t) {
		return t==null?-1:t.height;
	}
	
	private AvlNode balance(AvlNode t) {
		if(t==null) {
			return t;
		}
		if(t.left.height>t.right.height) {
			if(height(t.left.left)>=height(t.left.right)) {
				t=rotateWithLeftChild(t);
			}else {
				t=doubleWithLeftChild(t);
			}
		}else if(t.right.element>t.left.element) {
			if(height(t.right.right)>=height(t.right.left)) {
				t=rotateWithRightChild(t);
			}else {
				t=doubleWithRightChild(t);
			}
		}
		t.height = Math.max(t.left.height,t.right.height)+1;
		return t;
	}
	
	private AvlNode doubleWithRightChild(AvlNode t) {
		t.right=rotateWithLeftChild(t.right);
		rotateWithRightChild(t);
		return t;
	}

	private AvlNode rotateWithRightChild(AvlNode t) {
		AvlNode avlNode = t.right;
		t.right=avlNode.left;
		avlNode.left = t;
		t.height = Math.max(t.left.height, t.right.height);
		avlNode.height = Math.max(t.height, avlNode.right.height);
		return avlNode;
	}

	private AvlNode doubleWithLeftChild(AvlNode t) {
		t.left=rotateWithRightChild(t.left);
		rotateWithLeftChild(t);
		return t;
	}

	private AvlNode rotateWithLeftChild(AvlNode t) {
		AvlNode avlNode  = t.left;
		t.left = avlNode.right;
		avlNode.right = t;
		t.height = Math.max(t.left.height, t.right.height)+1;
		avlNode.height = Math.max(avlNode.height, t.height)+1;
		return avlNode;
	}

	private AvlNode remove(int a,AvlNode t) {
		if(t==null) {
			return t;
		}
		if(a<t.element) {
			t.left = remove(a, t.left);
		}else if(a>t.element) {
			t.right = remove(a, t.right);
		}else {
			if(t.left!=null&&t.right!=null) {
				t.element = findMin(t.right).element;
				t.right = remove(findMin(t.right).element, t.right);
			}else {
				t= (t.left!=null)?t.left:t.right;
			}
		}
		t.height = Math.max(t.left.height, t.right.height)-1;
		return balance(t);
		
	}
	
	private AvlNode findMin(AvlNode t) {
		if(t==null) {
			return null;
		}
		if(t.left==null) {
			return t;
		}else {
			return findMin(t.left);
		}
	}

	private class AvlNode{
		public int element;
		public AvlNode left;
		public AvlNode right;
		int height;
		private AvlNode(int a,AvlNode b,AvlNode c) {
			element = a;
			left=b;
			right=c;
			height=0;
		}
		public AvlNode(int a) {
			this(a, null, null);
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值