树的深度和高
1.对于任意节点 n i n_{i} ni, n i n_{i} ni的深度为从根到 n i n_{i} ni的唯一路径的长。 n i n_{i} ni的高是从 n i n_{i} ni到一片树叶的最长路径的长。
树的实现
class TreeNode{
Object element;
TreeNode firstChild;
TreeNode nextSibling;
}
树的实现(图示)
树的遍历
1.前序遍历:先访问根,然后访问子树的遍历方式。
前序遍历:F,B,A,D,C,E,G,I,H
2.中序遍历:先访问左(右)子树,然后访问根,最后访问右(左)子树的遍历方式。
中序遍历:A,B,C,D,E,F,G,H,I
3.后序遍历:先访问子树,然后访问根的遍历方式。
后序遍历:A,C,E,D,B,H,I,G,F
二叉树
二叉树是一棵树,其中每个节点都不能有多于两个的儿子。
二叉树的实现:
class BinaryNode{
Object element;
BinaryNode left;
BinaryNode right;
}
二叉查找树
二叉查找树 程序实现:
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>>
{
private static class BinaryNode<AnyType>
{
BinaryNode(AnyType theElement)
{
this(theElement,null,null);
}
BinaryNode(AnyType theElement,BinaryNode<AnyType> lt,BinaryNode<AnyType> rt)
{
element=theElement;
left=lt;
right=rt;
}
AnyType element;
BinaryNode<AnyType> left;
BinaryNode<AnyType> right;
}
private BinaryNode<AnyType> root;
public BinarySearchTree()
{
root=null;
}
//插入节点
public void insert(AnyType x)
{
root=insert(x, root);
}
//移除节点
public void remove(AnyType x)
{
root=remove(x, root);
}
//发现最小节点
public AnyType findMin()
{
if(isEmpty())
throw new UnderflowException();
return findMin(root).element;
}
public AnyType findMax()
{
if(isEmpty())
throw new UnderflowException();
return findMax(root).element;
}
public boolean contains(AnyType x)
{
return contains(x,root);
}
public void makeEmpty()
{
root=null;
}
public boolean isEmpty()
{
return root==null;
}
public void printTree()
{
if(isEmpty())
System.out.println("Empty tree");
else
printTree(root);
}
private BinaryNode<AnyType> insert(AnyType x,BinaryNode<AnyType> t)
{
if(t==null)
return new BinaryNode<>(x,null,null);
int compareResult=x.compareTo(t.element);
if(compareResult<0)
t.left=insert(x, t.left);
else if(compareResult>0)
t.right=insert(x, t.right);
else
;
return t;
}
private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t)
{
if (t == null)
return t;
int compareResult = x.compareTo(t.element);
if (compareResult < 0)
t.left = remove(x, t.left);
else if (compareResult > 0)
t.right = remove(x, t.right);
else if (t.left != null && t.right != null)
{
t.element = findMin(t.right).element;
t.right = remove(t.element, t.right);
} else
t = (t.left != null) ? t.left : t.right;
return t;
}
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t)
{
if(t==null)
return null;
else if(t.left==null)
return t;
return findMin(t.left);
}
private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t)
{
if(t!=null)
{
while(t.right!=null)
t=t.right;
}
return t;
}
private boolean contains(AnyType x,BinaryNode<AnyType> t)
{
if(t==null)
return false;
int compareResult=x.compareTo(t.element);
if(compareResult<0)
return contains(x,t.left);
else if(compareResult>0)
return contains(x, t.right);
else
return true;
}
private void printTree(BinaryNode<AnyType> t)
{
if(t!=null)
{
printTree(t.left);
System.out.println(t.element);
printTree(t.right);
}
}
private int height(BinaryNode<AnyType> t)
{
if(t==null)
return -1;
else
return 1+Math.max(height(t.left), height(t.right));
}
}
AVL树
AVL树是带有平衡条件的二叉查找树。(AVL树左右子树高度相差不超过1)。
平衡的破坏:
把必须重新平衡的节点叫做 α \alpha α,由于任意节点最多有两个儿子,因此出现高度不平衡就需要 α \alpha α点的两棵子树的高度差2。此种不平衡条件可能出现在以下四种情况:
1.对 α \alpha α的左儿子的左子树进行一次插入。
2.对 α \alpha α的左儿子的右子树进行一次插入。
3.对 α \alpha α的右儿子的左子树进行一次插入。
4.对 α \alpha α的右儿子的右子树进行一次插入。
AVL树 程序实现:
public class AvlTree<AnyType extends Comparable<? super AnyType>>
{
public AvlTree( )
{
root = null;
}
public void insert( AnyType x )
{
root = insert( x, root );
}
public void remove( AnyType x )
{
root = remove( x, root );
}
private AvlNode<AnyType> remove( AnyType x, AvlNode<AnyType> t )
{
if( t == null )
return t; // Item not found; do nothing
int compareResult = x.compareTo( t.element );
if( compareResult < 0 )
t.left = remove( x, t.left );
else if( compareResult > 0 )
t.right = remove( x, t.right );
else if( t.left != null && t.right != null ) // Two children
{
t.element = findMin( t.right ).element;
t.right = remove( t.element, t.right );
}
else
t = ( t.left != null ) ? t.left : t.right;
return balance( t );
}
public AnyType findMin( )
{
if( isEmpty( ) )
throw new UnderflowException( );
return findMin( root ).element;
}
public AnyType findMax( )
{
if( isEmpty( ) )
throw new UnderflowException( );
return findMax( root ).element;
}
public boolean contains( AnyType x )
{
return contains( x, root );
}
public void makeEmpty( )
{
root = null;
}
public boolean isEmpty( )
{
return root == null;
}
public void printTree( )
{
if( isEmpty( ) )
System.out.println( "Empty tree" );
else
printTree( root );
}
private static final int ALLOWED_IMBALANCE = 1;
private AvlNode<AnyType> balance( AvlNode<AnyType> t )
{
if( t == null )
return t;
if( height( t.left ) - height( t.right ) > ALLOWED_IMBALANCE )
if( height( t.left.left ) >= height( t.left.right ) )
t = rotateWithLeftChild( t );
else
t = doubleWithLeftChild( t );
else
if( height( t.right ) - height( t.left ) > ALLOWED_IMBALANCE )
if( height( t.right.right ) >= height( t.right.left ) )
t = rotateWithRightChild( t );
else
t = doubleWithRightChild( t );
t.height = Math.max( height( t.left ), height( t.right ) ) + 1;
return t;
}
public void checkBalance( )
{
checkBalance( root );
}
private int checkBalance( AvlNode<AnyType> t )
{
if( t == null )
return -1;
if( t != null )
{
int hl = checkBalance( t.left );
int hr = checkBalance( t.right );
if( Math.abs( height( t.left ) - height( t.right ) ) > 1 ||
height( t.left ) != hl || height( t.right ) != hr )
System.out.println( "OOPS!!" );
}
return height( t );
}
private AvlNode<AnyType> insert( AnyType x, AvlNode<AnyType> t )
{
if( t == null )
return new AvlNode<>( x, null, null );
int compareResult = x.compareTo( t.element );
if( compareResult < 0 )
t.left = insert( x, t.left );
else if( compareResult > 0 )
t.right = insert( x, t.right );
else
;
return balance( t );
}
private AvlNode<AnyType> findMin( AvlNode<AnyType> t )
{
if( t == null )
return t;
while( t.left != null )
t = t.left;
return t;
}
private AvlNode<AnyType> findMax( AvlNode<AnyType> t )
{
if( t == null )
return t;
while( t.right != null )
t = t.right;
return t;
}
private boolean contains( AnyType x, AvlNode<AnyType> t )
{
while( t != null )
{
int compareResult = x.compareTo( t.element );
if( compareResult < 0 )
t = t.left;
else if( compareResult > 0 )
t = t.right;
else
return true;
}
return false;
}
private void printTree( AvlNode<AnyType> t )
{
if( t != null )
{
printTree( t.left );
System.out.println( t.element );
printTree( t.right );
}
}
private int height( AvlNode<AnyType> t )
{
return t == null ? -1 : t.height;
}
单旋转
对应上述条件1
//左子树高,单旋转
private AvlNode<AnyType> rotateWithLeftChild( AvlNode<AnyType> k2 )
{
AvlNode<AnyType> k1 = k2.left;
k2.left = k1.right;
k1.right = k2;
k2.height = Math.max( height( k2.left ), height( k2.right ) ) + 1;
k1.height = Math.max( height( k1.left ), k2.height ) + 1;
return k1;
}
单旋转
对应上述条件2
//右子树高,单旋转
private AvlNode<AnyType> rotateWithRightChild( AvlNode<AnyType> k1 )
{
AvlNode<AnyType> k2 = k1.right;
k1.right = k2.left;
k2.left = k1;
k1.height = Math.max( height( k1.left ), height( k1.right ) ) + 1;
k2.height = Math.max( height( k2.right ), k1.height ) + 1;
return k2;
}
双旋转
对应上述条件3
//左子树高,双旋转
private AvlNode<AnyType> doubleWithLeftChild( AvlNode<AnyType> k3 )
{
k3.left = rotateWithRightChild( k3.left );
return rotateWithLeftChild( k3 );
}
双旋转
对应上述条件4
//右子树高,双旋转
private AvlNode<AnyType> doubleWithRightChild( AvlNode<AnyType> k1 )
{
k1.right = rotateWithLeftChild( k1.right );
return rotateWithRightChild( k1 );
}
//对树的节点进行定义
private static class AvlNode<AnyType>
{
AvlNode( AnyType theElement )
{
this( theElement, null, null );
}
AvlNode( AnyType theElement, AvlNode<AnyType> lt, AvlNode<AnyType> rt )
{
element = theElement;
left = lt;
right = rt;
height = 0;
}
AnyType element;
AvlNode<AnyType> left;
AvlNode<AnyType> right;
int height;
}
//树的根
private AvlNode<AnyType> root;
}