next up previous contents
suivant: Bibliographie monter: Package util précédent: Fifo.java   Table des matières

Heap.java


package buffalo.util;

import java.util.Vector;
import java.lang.Comparable;

/**
   Classe générique regroupant des éléments 
   dans un tas selon une clé définie par l'utilisateur 
   de la classe. On place à la racine du tas l'élement de 
   plus petite cl&eacute; (<CODE>a.compareTo(b)</CODE> renvoie 
   <CODE>1</CODE> si <CODE>a > b</CODE>)
   Pour inverser le tas, il suffit de modifier 
   l'impl&eacute;mentation de la fonction de comparaison.
*/

public class Heap
{
    
    /**
       Tableau contenant tous les &eacute;l&eacute;ments du tas, 
       ce tableau est indic&eacute; &agrave; partir de 
       <CODE>0</CODE>.
    */
    
    Vector elements;

    /*------------------------------------------------------------*/
    
    public Heap()
    {
	elements = new Vector();
    }
    
    /*------------------------------------------------------------*/
    
    /**
       Renvoie l'indice du fils droit de 
       l'<CODE>index</CODE>-i&egrave;me 
       &eacute;l&eacute;ment 
       du tableau, renvoie <CODE>-1</CODE> si il n'y en a pas.
    */
    
    private int rightSon(int index)
    {
	if ((2*index + 1) >= getSize()) 
	    {
		return -1;
	    }
	return (2*index + 1);
    }
    
    /*------------------------------------------------------------*/    
    
    /**
       Renvoie le nombre d'&eacute;l&eacute;ments contenus dans le tas.
    */
    
    public int getSize()
    {
	return elements.size();
    }

    /*------------------------------------------------------------*/
    
    /**
       Renvoie l'indice du fils gauche de 
       l'<CODE>index</CODE>-i&egrave;me 
       &eacute;l&eacute;ment de tableau, renvoie 
       <CODE>-1</CODE> si il n'y en a pas.
    */
    
    private int leftSon(int index)
    {
	if ((2*index + 2)>=getSize() ) 
	    {
            return -1;
	    }
	return (2*index + 2);
    }
    
    /*------------------------------------------------------------*/
    
    /**
       Renvoie l'indice du plus fils gauche de 
       l'<CODE>index</CODE>-i&egrave;me 
       &eacute;l&eacute;ment de tableau, 
       renvoie <CODE>-1</CODE> si il n'y en a pas.
    */
    
    private int smallestSon(int index)
    {
	int valueOfRightSon = rightSon(index);
	int valueOfLeftSon = leftSon(index);
	if (valueOfRightSon == -1 ) 
	    {
		return -1;
	    }
	if (valueOfLeftSon == -1 ) 
	    {
		return valueOfRightSon;
	    }
	if (((Comparable)elements.get(valueOfLeftSon)).compareTo
	    (elements.get(valueOfRightSon)) == -1)
	    {
		return valueOfLeftSon;
	    }
	else
	    {
		return valueOfRightSon;	
	    }
    }
    
    /*------------------------------------------------------------*/
    
    /**
       Renvoie l'indice du p&egrave;re de 
       l'<CODE>index</CODE>-i&egrave;me &eacute;l&eacute;ment 
       de tableau, renvoie <CODE>-1</CODE> 
       si il n'y en a pas.
    */
    
    private int father(int index)
    {
	if ( index <= 0 ) 
	    {
		return -1;
	    }
	return ((index-1) / 2);
    }
    
    /*------------------------------------------------------------*/
    
    /**
       Permute les deux éléments d'indices <CODE>index1</CODE>
       et <CODE>index2</CODE>.
    */
    
    private void swap(int index1, int index2)
    {
         Object temp;
         temp = elements.get(index1);
         elements.set(index1, elements.get(index2));
         elements.set(index2, temp);
    }
    
    /*------------------------------------------------------------*/
    
    /**
       Place un nouvel <CODE>item</CODE> dans l'arbre sans 
       &eacute;quilibrer ce dernier.
    */
    
    private void addLeaf(Comparable item)
    {
	elements.add(item);
    }
    
    /*------------------------------------------------------------*/
    
    /**
       Remplace le premier &eacute;l&eacute;ment par le dernier sans 
       &eacute;quilibrer le tas.
    */
    
    private void removeLeaf()
    {
	if (getSize()!=0)
	    {
		swap(0,getSize()-1);
	    }
	elements.remove(getSize()-1);
    }
    
    /*------------------------------------------------------------*/
    
   /**
      Retourne <CODE>0</CODE> si le tas est 
      &eacute;quilibr&eacute;
      <CODE>1</CODE> si <CODE>tab[index]>tab[father]</CODE>
      <CODE>2</CODE> si <CODE>tab[index]>tab[filsXxxx]</CODE>
   */
    
    private int isBalanced(int index)
    {
	int valueOfRightSon = rightSon(index);
	int valueOfLeftSon = leftSon(index);
	int valueOfFather = father(index);
	if ((valueOfFather!=-1)&&
	    (((Comparable)elements.get(valueOfFather)).compareTo
	     (elements.get(index))) == 1)
	    {
		return 1;
	    }
	if ((valueOfLeftSon!=-1)&&
	    (((Comparable)elements.get(index)).compareTo
	     (elements.get(valueOfLeftSon))) ==  1)
	    {
		return 2;
	    }
	if ((valueOfRightSon!=-1)&&
	    (((Comparable)elements.get(index)).compareTo
	     (elements.get(valueOfRightSon))) == 1)
	    {
		return 2;
	    }
	return 0; 
    }
    
    /*------------------------------------------------------------*/
    
    /**
       Equilibre le tas &agrave; partir de <CODE>index</CODE> et se 
       rappelle pour propager l'&eacute;quilibre.
    */
      
    private void balance(int index)
    {
	int valueOfFather;
	int indexOfSmallestSon;
	switch(isBalanced(index))
	    {
            case 1 : valueOfFather = father(index);
		swap(index, valueOfFather);
		balance(valueOfFather);
		break;
            case 2 : indexOfSmallestSon = smallestSon(index);
		swap(index, indexOfSmallestSon);
		balance(indexOfSmallestSon);
		break;
	    }
    }
    
    /*------------------------------------------------------------*/
    
    /**
       Ajoute un objet <CODE>item</CODE>
       impl&eacute;mentant <CODE>Comparable</CODE> 
       dans le tas.
    */
    
    public void add(Comparable item)
    {
	addLeaf(item);
	balance(getSize()-1);
    }
    
    /*------------------------------------------------------------*/
    
    /**
       Fonction de suppression du premier
       &eacute;l&eacute;ment du tas.
    */
    
    public void removeRoot()
    {
	Comparable formerRoot = getRoot();
	removeLeaf();
	balance(0);
	if((getRoot()!=null)&&(getRoot().compareTo(formerRoot) == 0))
	    {
		removeRoot();
	    }
    }
    
    /*------------------------------------------------------------*/
    
    /**
       Cette renvoie le premier &eacute;l&eacute;ment du tas.
    */
    
    public Comparable getRoot()
    {
	if (getSize() == 0) 
	    {
		return null;
	    }
	return (Comparable)elements.get(0);
    }  
    

    /*--------------------------------------------------------------*/

    /**
       Renvoie le tas au format cha&icirc;ne de caract&egrave;res.
     */
    
    public String toString()
    {
	return elements.toString();
    }

    /*--------------------------------------------------------------*/

    public static void main(String[] args)
    {
	int k = 71;
	Heap tas = new Heap();
	for (int i = 0; i < k; i++)
	    {
		tas.add(new Integer((i*i*i)%k));		
	    }
	for (; tas.getRoot() != null;)
	    {
		System.out.print(tas.getRoot() + " --> ");
		tas.removeRoot();
	    }
    }

}



Alexandre 2009-05-14