平衡二叉树

二叉排序树的查询性能和二叉树的结构有关,如果二叉排序树退化为单链表,那么查询时间就是O(n),而平衡二叉树使得左右子树高度差不超过1,因此查询效率高,为O(log2n)。

性质:左子树和右子树都是平衡二叉树,且左右子树高度差的绝对值不超过1。

平衡因子:右子树减去左子树的高度差。

当平衡因子大于1时,则失去平衡,需要调整失去该平衡的最小子树。在插入的过程中会碰到四种插入情况,需要不同的调整方式。

分别是:

  1. LL平衡旋转:在当前节点的左孩子的左子树上插入新结点,导致该节点的平衡因子变为-2,需要LL平衡旋转。
  2. RR平衡旋转:在当前节点的右孩子的右子树上插入新节点,导致该节点的平衡因子变为2,需要RR平衡旋转。
  3. LR平衡旋转:在当前节点的左孩子的右子树上插入新节点,导致该节点的平衡因子变为-2,需要LR平衡旋转。
  4. RL平衡旋转:在当前节点的右孩子的左子树上插入新节点,导致该节点的平衡因子变为2,需要RL平衡旋转。

在插入的过程中,每次插入一个数需要根据平衡因子判断是否失去了平衡,然后调整。需要平衡旋转的最小子树的层数在旋转前后都未曾改变,因此子树之上的节点不需要调整平衡因子。

下面的程序使用avl算法实现了平衡二叉树的插入和删除。

public class App 
{

	public static void main(String[] arg) {
		int[]array= {11,39,23,68,85,8,3,46,27,50};
		BBTree bTree=new BBTree(array);
		bTree.preOrder();
		System.out.println("");
		bTree.delete(39);
		bTree.delete(27);
		bTree.preOrder();
	}
	//平衡二叉树,实现算法AVL
	static class BBTree{
		class Node{
			int data;
			Node leftChild,rightChild;
			int balance;//平衡因子
		}
		Node root;
		
		public BBTree(int[] array) {
			// TODO Auto-generated constructor stub
			for(int a:array) {
				insert(a);
//				preOrder();
//				System.out.println("");
			}
		}
		
		
		void preOrder() {
			preOrder(root);
		}
		void preOrder(Node p) {
			if(p==null) {
				return;
			}
			System.out.print(p.data+" ");
			preOrder(p.leftChild);
			preOrder(p.rightChild);
		}
		
		void insert(int k) {
			if(root==null) {
				root=new Node();
				root.data=k;
				return ;
			}
			Node a=root;
			Node preA=null;//a的前一个取值
			Node cur=root;
			while(true) {
				if(k<cur.data) {
					if(cur.leftChild!=null) {
						if(Math.abs(cur.balance)==1) {
							preA=a;
							a=cur;
						}
						cur=cur.leftChild;
						
					}else {
						if(Math.abs(cur.balance)==1) {
							preA=a;
							a=cur;
						}
						
						cur.leftChild=new Node();
						cur.leftChild.data=k;
						//从a修改balance
						updateBalance(k, a);
						//若不平衡则调整
						if(Math.abs(a.balance)==2) {
							//adjust tree
							if(a==root) {//根节点特殊处理
								root=rotate(a);
							}else if(preA.leftChild==a) {
								preA.leftChild=rotate(a);
							}else {
								preA.rightChild=rotate(a);
							}
						}
						return;
					}
				}else if(k>cur.data) {
					if(cur.rightChild!=null) {
						if(Math.abs(cur.balance)==1) {
							preA=a;
							a=cur;
						}
						cur=cur.rightChild;
					}else {
						if(Math.abs(cur.balance)==1) {
							preA=a;
							a=cur;
						}
						
						cur.rightChild=new Node();
						cur.rightChild.data=k;
						updateBalance(k, a);
						if(Math.abs(a.balance)==2) {
							if(a==root) {
								root=rotate(a);
							}else if(preA.leftChild==a) {
								preA.leftChild=rotate(a);
							}else {
								preA.rightChild=rotate(a);
							}
						}
						return;
					}
				}
			}
		}
		
		void updateBalance(int k,Node p) {
			//更新平衡因子,如果p为null,默认使用root
			if(p==null) {
				p=root;
			}
			while(p.data!=k) {
				if(k<p.data) {
					p.balance--;
					p=p.leftChild;
				}else if(k>p.data){
					p.balance++;
					p=p.rightChild;
				}
			}
		}
		/***
		 * 自动根据平衡因子分辨LL、LR、RR、RL四种情况,然后调整
		 * @param a 该节点平衡因子必须大于1,即不平衡
		 * @return 返回新根节点
		 */
		Node rotate(Node a) {
			if(Math.abs(a.balance)<=1) {
				return null;
			}
			if(a.leftChild!=null && a.leftChild.balance==-1) {
				//LL
				Node b=a.leftChild;
				Node temp=b.rightChild;
				b.rightChild=a;
				a.leftChild=temp;
				//修改平衡因子
				a.balance=getBalance(a);
				b.balance=getBalance(b);
				return b;
			}else if(a.leftChild!=null && a.leftChild.balance==1) {
				//LR
				Node b=a.leftChild;
				Node c=b.rightChild;
				Node temp1=c.leftChild,temp2=c.rightChild;
				c.leftChild=b;
				c.rightChild=a;
				b.rightChild=temp1;
				a.leftChild=temp2;
				
				a.balance=getBalance(a);
				b.balance=getBalance(b);
				c.balance=getBalance(c);
				return c;
			}else if(a.rightChild!=null&&a.rightChild.balance==-1) {
				//RL
				Node b=a.rightChild;
				Node c=b.leftChild;
				Node temp1=c.leftChild,temp2=c.rightChild;
				c.leftChild=a;
				c.rightChild=b;
				a.rightChild=temp1;
				b.leftChild=temp2;
				
				a.balance=getBalance(a);
				b.balance=getBalance(b);
				c.balance=getBalance(c);
				return c;
			}else if(a.rightChild!=null&&a.rightChild.balance==1) {
				//RR
				Node b=a.rightChild;
				Node temp=b.leftChild;
				b.leftChild=a;
				a.rightChild=temp;
				
				a.balance=getBalance(a);
				b.balance=getBalance(b);
				return b;
			}
			return null;
		}
		/***
		 * 得到关于该节点的高度
		 * @param p
		 * @return
		 */
		int getHeight(Node p) {
			if(p==null) {
				return 0;
			}
			int height1=getHeight(p.leftChild);
			int height2=getHeight(p.rightChild);
			return Math.max(height1, height2)+1;
		}
		/***
		 * 得到该节点的平衡因子
		 * @param p
		 * @return
		 */
		int getBalance(Node p) {
			int left=getHeight(p.leftChild);
			int right=getHeight(p.rightChild);
			return right-left;
		}
		void delete(int k) {
			root=delete(k, root);
		}
		boolean shorter=true;
		Node delete(int k,Node p) {
			if(p==null) {//没有该元素
				shorter=false;
				return null;
			}
			if(k<p.data) {
				p.leftChild=delete(k, p.leftChild);
				//判断shorter
				if(shorter) {
					if(p.balance==1) {
						Node q=p.rightChild;
						if(q.balance==1) {
							shorter=true;
							p=rotate(p);
						}else if(q.balance==0) {//不属于四种平衡旋转之一。。。
							shorter=false;
							Node temp=q.leftChild;
							q.leftChild=p;
							p.rightChild=temp;
							q.balance=getBalance(q);
							p.balance=getBalance(p);
							
							p=q;//要返回p,而p是根节点。
						}else if(q.balance==-1) {
							shorter=true;
							p=rotate(p);
						}
					}else if(p.balance==0) {
						p.balance=getBalance(p);
						shorter=false;
					}else if(p.balance==-1) {
						p.balance=getBalance(p);
						shorter=true;
					}
				}
				return p;
			}else if(k>p.data){
				p.rightChild=delete(k, p.rightChild);
				//判断shorter
				if(shorter) {
					if(p.balance==1) {
						shorter=true;
						p.balance=getBalance(p);
					}else if(p.balance==0) {
						shorter=false;
						p.balance=getBalance(p);
					}else if(p.balance==-1) {
						Node q=p.leftChild;
						if(q.balance==0) {
							Node temp=q.rightChild;
							q.rightChild=p;
							p.leftChild=temp;
							shorter=false;
							p.balance=getBalance(p);
							q.balance=getBalance(q);
							
							p=q;
				
						}else if (q.balance==-1) {
							shorter=true;
							p=rotate(p);
						}else if(q.balance==1) {
							shorter=true;
							p=rotate(p);
						}
					}
				}
				return p;
			}else {
				shorter=true;
				if(p.leftChild!=null&&p.rightChild!=null) {
					Node temp=min(p.rightChild);
					temp.rightChild=deleteMin(p.rightChild);
					temp.leftChild=p.leftChild;
					return temp;
				}else if(p.leftChild==null) {
					return p.rightChild;
				}else {
					return p.leftChild;
				}
				
			}
		}
		Node min(Node p) {
			while(p.leftChild!=null) {
				p=p.leftChild;
			}
			return p;
		}
		Node deleteMin(Node p) {
			if(p.leftChild==null) {
				return p.rightChild;
			}
			p.leftChild=deleteMin(p.leftChild);
			return p;
		}
		
	}
	
	

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值