赞
踩
class BinaryNode {
BinaryNode( Comparable theElement ) {
this( theElement, null, null );//调用本类中的其他构造方法
}
BinaryNode( Comparable theElement, BinaryNode lt,BinaryNode rt ) {
element = theElement
left = lt;
right = rt;
}
Comparable element;
BinaryNode left;
BinaryNode right;
}
//二叉搜素树的实现 public class BinarySearchTree { public BinarySearchTree(){ root = null; } public void makeEmpty(){ root = null; } public boolean isEmpty(){ return root == null;} public Comparable find( Comparable x ) {return elementAt( find( x, root));} public Comparable findMin() {return elementAt( findMin( root ) );} public Comparable findMax() {return elementAt( findMax( root ) ); public void insert( Comparable x ) {root = insert( x, root );} public void remove( Comparable x ) {root = remove( x, root ); } public void printTree()//都是外部接口 private BinaryNode root; private Comparable elementAt( BinaryNode t ){ return t == null ? Null : t.element; } private BinaryNode find( Comparable x, BinaryNode t ) private BinaryNode findMin( BinaryNode t ) private BinaryNode findMax( BinaryNode t ) private BinaryNode insert( Comparable x, BinaryNode t ) private BinaryNode remove( Comparable x, BinaryNode t ) private BinaryNode removeMin( BinaryNode t ) private void printTree( BinaryNode t ) } //查找某个元素的算法 private BinaryNode find( Comparable x, BinaryNode t ) { if( t == null ) return null; if( x.compareTo( t.element ) < 0 ) return find( x, t.left ); else if( x.compareTo( t.element ) > 0 ) return find( x, t.right ); else return t;//Match } //查找值最小的结点 //使用递归查找结点 private BinaryNode findMin( BinaryNode t ) { if( t == null ) return null; else if( t.left == null ) return t; return findMin( t.left ); } //迭代找最小结点 private BinaryNode findMin(BinaryNode t){ if(t != null){ while(t.left != null){ t = t.left; } } return t; } //递归找到最大结点 private BinaryNode findMax( BinaryNode t){ if(t == null){ return null; }else if(t.right == null){ return t; } return findMax(t.right); } //迭代找到最大结点 private BinaryNode findMax( BinaryNode t ) { if( t != null ) while( t.right != null ) t = t.right; return t; } //将数值插入固定位置的算法 private BinaryNode insert( Comparable x, BinaryNode t ) { //先查找一次,如果找到了就不用进行查找 if( t == null ) t = new BinaryNode( x, null, null ); else if( x.compareTo( t.element ) < 0 ) t.left = insert( x, t.left ); else if( x.compareTo( t.element ) > 0 ) t.right = insert( x, t.right ); else ;//duplicate; do nothing return t; } //compareTo()方法如果小于返回负数,大于返回正数
private BinaryNode remove( Comparable x, BinaryNode t ) {
if( t == null )
return t;
if( x.compareTo( t.element ) < 0 )
t.left = remove( x, t.left );
else if( x.compareTo( t.element ) > 0 )
t.right = remove( x, t.right );
else if( t.left != null && t.right != null ) {
t.element = findMin( t.right ).element;//把右树最小的复制给t
t.right = remove( t.element , t.right );//递归的删除
}else{
t = ( t.left != null ) ? t.left : t.right;//一颗子树的情况
}
}
class AVLNode { AVLNode(Comparable theElement) { this( theElement, null, null); } AVLNode(Compalable theElement, AVLNode lt, AVLNode rt) { element = theElement; left = lt; right = rt; height = 0; } Comparable element; AVLNode left; AVLNode right; int height; } private static int height( AVLNode t ) { return t =s= null ? –1 : t. height; }
查询过程和正常的二叉搜索树是相同的,其算法复杂度和正常二叉搜索树的搜索算法的复杂度是相同的。
算法思想:插入一个新结点后,需要从插入位置沿通向根的路径回溯,检查各结点左右子树的高度差,如果发现某点高度不平衡则停止回溯。
单旋转:外侧—从不平衡结点沿刚才回溯的路径取直接下两层如果三个结点处于一直线A,C,E
双旋转:内侧—从不平衡结点沿刚才回溯的路径取直接下两层如果三个结点处于一折线A,C,D
以上以右外侧,右内侧为例,左外侧,左内侧是对称的。与前面对称的情况:左外侧,左内侧 左外侧
插入:
private AVLNode insert( Comparable x, AVLNode t ) { if (t == null) t = new AVLNode( x, null, null ); else if ( x.compareTo(t.element) < 0 ){ t.left = insert(x, t.left);//不仅x插入左子树,而其左子树已经调平衡了,也就会子树已经旋转过了 if(height(t.left) – height(t.right) == 2 ) if(x.compareTo(t.left.element)<0) //根据大小进行调整 t = rotateWithLeftChild (t);//左子树的左子树,只要做一次左向单旋 else t = doubleWithLeftChild(t);//左子树的右子树,需要做一次左向双选 //下面是对称的插入在右子树上 }else if(x.compareTo(t.element)>0) { t.right = insert(x, t.right ); if( height(t.right)–height(t.left)== 2) if(x.compareTo(t.right.element)>0) t = rotateWithRightChild(t); else t = doubleWithRightChild(t) }else; t.height = max(height(t.left), height(t.right)) + 1; return t; }
右下旋
private static AVLNode rotateWithLeftChild( AVLNode k2 ) {
AVLNode k1 = k2.left;//k1持有k2的左子树
k2.left = k1.right;//k1的右子树挂到k2的左子树上
k1.right = k2;//把k2自己挂到k1的右子树上
k2.height = max(height(k2.left), height(k2.right)) + 1 ;
k1.height = max(height(k1.left), k2.height) + 1;
return k1;
}
左下旋
private static AVLNode rotateWithRightChild(AVLNode k2){
AVLNode k1 = k2.right;//k1持有k2的右子树
k2.right = k1.left;//k2的右子树挂到k1的左子树上
k1.left = k2;//把k2自己挂到k1的左子树上
k2.height = max(height(k2.left),height(k2.right)) + 1;
k1.height = max(k2.height,k1.right) + 1;
return k1;
}
右内侧
private static AVLNode doubleWithLeftChild( AVLNode k3 ) {
k3.left = rotateWithRightChild(k3.left);
return rotateWithLeftChild( k3 );
}
左内侧
private static AVLNode doubleWithRightChild(AVLNode k3){
k3.right = rotateWithLeftChild(k3.right);
return rotateWithRightChild( k3 );
}
删除元素不会影响树的叉数,物理层次影响叉数。
类型一:同一层还有节点,直接删除没有影响
类型二:本层删除后没有节点,所以需要把底下能合适的最大(最小)的进行提升
基本上同B树,所不同的是一直查到叶结点上的这个关键码为止
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。