package fr.unistra.pelican.util;
import java.util.Iterator;
/**
* Multi-ensemble trié, optimisé. Supporte tous les objets étendants Number
* Indispensable pour obenir des performances correctes avec la MM soft
* @author perret
*
*/
public class SortedBag implements Iterator<Number>, Iterable<Number> {
/**
* Implémentation sous forme de liste doublement chainée: Tête et queue
*/
private Element head=null;
private Element tail=null;
private int size=0;
private int ind=0;
public SortedBag(){}
/**
* Ajoute l'élement item
* @param item élément à ajouter
*/
public void add(Number item)
{
add(item,1);
}
/**
* Ajoute plusieurs fois le même élément
* @param item élément à ajouter
* @param k nombre de fois à ajouter
*/
public void add(Number item, int k)
{
size+=k;
if (head==null)
{
head=new Element(item,k,null,null);
tail=head;
}
else {
Element ge=findGE(item);
if(ge!=null && Math.abs(ge.val.doubleValue()-item.doubleValue())<0.00001)
{ge.add(k);}
else {
if (ge == null)
{
Element nouv=new Element(item,k,null,head);
head.p=nouv;
head=nouv;
}
else {
Element nouv=new Element(item,k,ge,ge.n);
ge.n=nouv;
if (nouv.n==null) tail=nouv;
else nouv.n.p=nouv;
}
}
}
}
/**
* Récupère l'élément d'indice n
* @param n
* @return l'élément cherché, null si il n'existe pas
*/
public Number getElementAt(int n)
{
Element op=head;
//System.out.println("Accessing item " + n);
while (op!=null)
{
//System.out.println("Accessing item " + n);
//System.out.println(op.k + " items in this one");
if (op.k>n)
{//System.out.println("Ok taking it ");
return op.val;}
else {
n-=op.k;
op=op.n;
}
}
return null;
}
/**
* Renvoie l'élément numéro n en ordre inverse
* @param n
* @return
*/
public Number getReverseElementAt(int n)
{
Element op=tail;
while (op!=null)
{
if (op.k>n)
return op.val;
else {
n-=op.k;
op=op.p;
}
}
return null;
}
/**
* Renvoie le premier élément strictement plus grand que item
* @param item
* @return
*/
private Element findGE(Number item)
{
Element op=head;
while(op!=null && (item.doubleValue()<op.val.doubleValue() || (op.n!=null && item.doubleValue()>=op.n.val.doubleValue())))
op=op.n;
return op;
}
/**
* Initialize l'itérateur sur l'ensemble
*
*/
private void initializeIterator()
{
ind=0;
}
public static void main (String [] args)
{
SortedBag b=new SortedBag();
b.add(10,3);
for (Number n:b)
System.out.println(""+n);
System.out.println("");
b.add(2,5);
for (Number n:b)
System.out.println(""+n);
System.out.println("");
b.add(1,1);
for (Number n:b)
System.out.println(""+n);
System.out.println("");
b.add(22,28);
for (Number n:b)
System.out.println(""+n);
System.out.println("");
System.out.println("ahah " + b.getElementAt(0));
System.out.println("ahah " + b.getElementAt(1));
System.out.println("ahah " + b.getElementAt(5));
System.out.println("ahah " + b.getElementAt(6));
System.out.println("ahah " + b.getReverseElementAt(0));
System.out.println("ahah " + b.getReverseElementAt(27));
System.out.println("ahah " + b.getReverseElementAt(28));
System.out.println("ahah " + b.getReverseElementAt(36));
}
/**
* Récupère le nombre d'élément dans l'ensemble
* @return
*/
public int size(){ return size;}
public boolean hasNext() {
return (ind<size);
}
public Number next() {
return getElementAt(ind++);
}
/**
* non implémenté
*/
public void remove() {
return;
}
public Iterator<Number> iterator() {
initializeIterator();
return this;
}
}
/**
* Un élément d'un multi ensemble: un nombre et un nombre d'occurence
* @author Ben
*
*/
class Element {
/**
* Valeur
*/
Number val;
/**
* Nombre d'occurences
*/
int k;
/**
* Element suivant
*/
Element n;
/**
* Element précédent
*/
Element p;
/**
* COnstructeur
* @param val valeur
* @param k nombre d'occurences
* @param p élément précédent
* @param n élement suivant
*/
public Element(Number val, int k,Element p, Element n)
{
this.val=val;
this.k=k;
this.n=n;
this.p=p;
}
/**
* Ajoute des occurences à l'élément
* @param k nombre POSITIF!!!
*/
void add(int k)
{
this.k+=k;
}
}