précédent | suivant | table des matières
Le tri par fusion pour les tableaux est défini par la fonction qui découpe le tableau initial en deux tableaux, et par la fonction de fusion.
Il y a plusieurs façon de découper le tableau initial T en deux tableaux T1 et T2 :
On définit une méthode qui répartit les éléments alternativement sur deux tableaux :
void repartir( int t[], int t1[], int t2[]){
for(int i = 0; i<n.length; ++i){
t1[i/2] = t[i];
++i; if(i==n) break;
t2[i/2] = t[i];
}
}
Puis une fonction de fusion de deux tableaux ordonnés :
void fusionner(int t1[], int t2[], int t[]){
int i1=0, i2=0, i=0;
for( ; i1 < t1.length && i2 <t2.length; ++i )
if(t1[i1]<t2[i2]){
t[i]=t1[i1]; ++i1;
}
else {
t[i]=t2[i2]; ++i2;
}
for( ; i1<t1.length; ++i, ++i1 ) t[i]=t1[i1];
for( ; i2<t2.length; ++i, ++i2 ) t[i]=t2[i2];
}
Le tri par fusion s’écrit récursivement :
void triFusionR( int t[]){
if(t.length<=1) return;
else{
int [] t1 = new int[(t.length+1)/2];
int [] t2 = new int[t.length/2];
repartir(t, t1, t2);
triFusionR(t1);
triFusionR(t2);
fusionner(t1, t2, t);
}
}
La programmation récursive est gourmande en place... Le besoin en place s’exprime par la récurrence :
dont la solution pour
est
On peut réduire le besoin en place en écrivant la fusion différemment :
int [] tAux;
void FusionSP(int t[], int d, int m, int f){
// fusion de a [d, m[ et de a[m, f[
int i, j, fAux=m-d, k;
for(i=d, j=0; i<m; ++i, ++j)tAux[j]=t[i];
i=m; j=0; k=d;
for ( ; i<f && j<fAux; ++k)
if( t[i]<taux[j]){ t[k]=t[i]; ++i;}
else { t[k]=tAux[j]; ++j;}
for( ;i<f; ++i, ++k) t[k]=t[i];
for( ;j<fAux; ++j, ++k) t[k]=tAux[j];
}
void triFusionSP( int [] t, int d, int f){
// tri par fusion de a entre d (inclus) et f (exclu)
if(d>=f-1) return;
else {
int m = (d+f)/2;
triFusionSP(t, d, m);
triFusionSP(t, m, f);
FusionSP(t, d, m, f);
}
}
void triFusionSP( int t[]){
tAux = new int [(t.length+1)/2];
triFusionSP( t, 0, t.length);
}
La fusion sur place fonctionne de la façon suivante :
L’espace supplémentaire nécessaire n’est plus que de taille n/2.