二叉查找树和AVL树学习笔记

树的深度和高

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;
}

树的实现(图示)

《二叉查找树和AVL树学习笔记》
《二叉查找树和AVL树学习笔记》

树的遍历

1.前序遍历:先访问根,然后访问子树的遍历方式。

《二叉查找树和AVL树学习笔记》

前序遍历:F,B,A,D,C,E,G,I,H
2.中序遍历:先访问左(右)子树,然后访问根,最后访问右(左)子树的遍历方式。

《二叉查找树和AVL树学习笔记》
中序遍历:A,B,C,D,E,F,G,H,I

3.后序遍历:先访问子树,然后访问根的遍历方式。

《二叉查找树和AVL树学习笔记》
后序遍历: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

《二叉查找树和AVL树学习笔记》

   //左子树高,单旋转
    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

《二叉查找树和AVL树学习笔记》

   //右子树高,单旋转
    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

《二叉查找树和AVL树学习笔记》

    //左子树高,双旋转
    private AvlNode<AnyType> doubleWithLeftChild( AvlNode<AnyType> k3 )
    {
        k3.left = rotateWithRightChild( k3.left );
        return rotateWithLeftChild( k3 );
    }

双旋转
对应上述条件4

《二叉查找树和AVL树学习笔记》

    //右子树高,双旋转
    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;

}

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/qq_37296487/article/details/84110087
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞