Skip to content
GitLab
Projets
Groupes
Sujets
Extraits de code
/
Aide
Aide
Support
Forum de la communauté
Raccourcis clavier
?
Proposer une rétroaction
Contribuer à GitLab
Connexion
Activer/désactiver la navigation
Menu
Mathys MACIA
AlgoAvance
Comparer les révisions
ad9389a93ba7d21f09aa2248f915208dbbfa35a6...48bfbd490d74c5ac0c0c1d49be338a0e8516df00
Commits (2)
ajout des tests
· d3d64f4d
Mathys MACIA
a écrit
déc. 02, 2025
d3d64f4d
Merge branch 'test' into 'master'
· 48bfbd49
Mathys MACIA
a écrit
déc. 02, 2025
ajout des tests See merge request
!1
48bfbd49
Masquer les modifications d'espaces
En ligne
Côte à côte
ABR_insert.csv
Voir le fichier @
48bfbd49
n,1000,2000,5000,10000,20000,50000
n,1000,2000,5000,10000,20000,50000
ASCENDANT,
1231700,00,4418640,00,30034160,00,116455020,0
0,474
819140,00,3056061360,0
0
ASCENDANT,
2741266,60,4242239,60,25764592,60,103848038,6
0,4
2
74
39882,20,2674167635,6
0
ALEATOIRE,
149580,00,167500,0
0,
3
56
340,00,830320,00,1814660,00,560992
0,
0
0
ALEATOIRE,
296387,40,450203,4
0,
6
56
077,20,1670061,80,3761467,60,1195784
0,
2
0
ABR_search.csv
Voir le fichier @
48bfbd49
n,1000,2000,5000,10000,20000,50000
n,1000,2000,5000,10000,20000,50000
ASCENDANT,
2658220,00,9699160,00,60452520,00,233926280,00,907753720,00,5800536280
,00
ASCENDANT,
4158852,60,12248819,80,76968346,20,319434800,40,1309307052,20,8234666725
,00
ALEATOIRE,
128340,00,122680,00,310240,00,577920,00,1311820,00,3409080
,00
ALEATOIRE,
266154,80,235807,80,574324,40,1102771,40,2151257,40,5866763
,00
ARN_insert.csv
Voir le fichier @
48bfbd49
n,1000,2000,5000,10000,20000,50000
n,1000,2000,5000,10000,20000,50000
ASCENDANT,
221140,00,242880,00,405760,00,720540,00,761520,00,1803680,0
0
ASCENDANT,
429293,00,541214,60,1492209,80,1450807,80,1846437,80,4429069,4
0
ALEATOIRE,
153900,00,219500,00,457300,00,938200,00,2106160,00,6222500
,00
ALEATOIRE,
402464,80,359252,00,1019308,20,1808727,00,3546869,20,11937927
,00
ARN_search.csv
Voir le fichier @
48bfbd49
n,1000,2000,5000,10000,20000,50000
n,1000,2000,5000,10000,20000,50000
ASCENDANT,
136940,00,128920,00,320120,0
0,
7
33
100,00,1475920,00,4872060,0
0
ASCENDANT,
353458,80,290777,00,621226,2
0,
1
33
6956,20,2635875,60,9406446,4
0
ALEATOIRE,
51780,00,101540,00,308340,00,616120,00,1244160,00,3500360,0
0
ALEATOIRE,
63701,80,132267,60,378176,00,815282,80,1745943,60,5169691,2
0
pom.xml
Voir le fichier @
48bfbd49
...
@@ -61,13 +61,43 @@
...
@@ -61,13 +61,43 @@
<artifactId>
maven-site-plugin
</artifactId>
<artifactId>
maven-site-plugin
</artifactId>
<version>
3.21.0
</version>
<version>
3.21.0
</version>
</plugin>
</plugin>
</plugins>
<plugin>
<groupId>
org.jacoco
</groupId>
<artifactId>
jacoco-maven-plugin
</artifactId>
<version>
0.8.12
</version>
<executions>
<execution>
<id>
default-prepare-agent
</id>
<goals>
<goal>
prepare-agent
</goal>
</goals>
</execution>
<execution>
<id>
default-report
</id>
<goals>
<goal>
report
</goal>
</goals>
</execution>
<execution>
<id>
default-check
</id>
<goals>
<goal>
check
</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<pluginManagement>
<plugins>
<plugins>
<plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-checkstyle-plugin
</artifactId>
<artifactId>
maven-checkstyle-plugin
</artifactId>
<version>
3.6.0
</version>
<version>
3.6.0
</version>
<configuration>
<configLocation>
google_checks.xml
</configLocation>
</configuration>
<dependencies>
<dependencies>
<dependency>
<dependency>
<groupId>
com.puppycrawl.tools
</groupId>
<groupId>
com.puppycrawl.tools
</groupId>
...
@@ -102,6 +132,19 @@
...
@@ -102,6 +132,19 @@
<artifactId>
maven-javadoc-plugin
</artifactId>
<artifactId>
maven-javadoc-plugin
</artifactId>
<version>
3.12.0
</version>
<version>
3.12.0
</version>
</plugin>
</plugin>
</plugins>
<plugin>
</reporting>
<groupId>
org.jacoco
</groupId>
<artifactId>
jacoco-maven-plugin
</artifactId>
<version>
0.8.12
</version>
<reportSets>
<reportSet>
<reports>
<!-- select non-aggregate reports -->
<report>
report
</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
</project>
</project>
src/main/java/collection/ArbreBinaireRecherche.java
Voir le fichier @
48bfbd49
...
@@ -12,261 +12,282 @@ import java.util.Stack;
...
@@ -12,261 +12,282 @@ import java.util.Stack;
*/
*/
public
class
ArbreBinaireRecherche
<
E
extends
Comparable
<
E
>>
implements
Collection
<
E
>
{
public
class
ArbreBinaireRecherche
<
E
extends
Comparable
<
E
>>
implements
Collection
<
E
>
{
/** Classe interne représentant un nœud de l'arbre */
/** Classe interne représentant un nœud de l'arbre */
private
class
Noeud
{
private
class
Noeud
{
E
cle
;
E
cle
;
Noeud
gauche
,
droit
;
Noeud
gauche
;
Noeud
droit
;
Noeud
(
E
k
)
{
this
.
cle
=
k
;
Noeud
(
E
k
)
{
}
this
.
cle
=
k
;
}
}
}
private
Noeud
racine
;
private
Noeud
racine
;
private
int
size
=
0
;
private
int
taille
=
0
;
@Override
@Override
public
boolean
add
(
E
e
)
{
public
boolean
add
(
E
e
)
{
Objects
.
requireNonNull
(
e
);
Objects
.
requireNonNull
(
e
);
// Si l’arbre est vide : racine = nouvel élément
// Si l’arbre est vide : racine = nouvel élément
if
(
racine
==
null
)
{
if
(
racine
==
null
)
{
racine
=
new
Noeud
(
e
);
racine
=
new
Noeud
(
e
);
size
++;
taille
++;
return
true
;
return
true
;
}
}
Noeud
cur
=
racine
,
parent
=
null
;
Noeud
actuel
=
racine
;
int
cmp
=
0
;
Noeud
parent
=
null
;
int
cmp
=
0
;
// Recherche de la position correcte pour insérer
while
(
cur
!=
null
)
{
// Recherche de la position correcte pour insérer
parent
=
cur
;
while
(
actuel
!=
null
)
{
cmp
=
e
.
compareTo
(
cur
.
cle
);
parent
=
actuel
;
cmp
=
e
.
compareTo
(
actuel
.
cle
);
if
(
cmp
<
0
)
cur
=
cur
.
gauche
;
// aller à gauche
if
(
cmp
<
0
)
{
else
if
(
cmp
>
0
)
actuel
=
actuel
.
gauche
;
// aller à gauche
cur
=
cur
.
droit
;
// aller à droite
}
else
if
(
cmp
>
0
)
{
else
actuel
=
actuel
.
droit
;
// aller à droite
return
false
;
// élément déjà présent
}
else
{
}
return
false
;
// élément déjà présent
}
// Insertion du nœud
}
if
(
cmp
<
0
)
parent
.
gauche
=
new
Noeud
(
e
);
// Insertion du nœud
else
if
(
cmp
<
0
)
{
parent
.
droit
=
new
Noeud
(
e
);
parent
.
gauche
=
new
Noeud
(
e
);
}
else
{
size
++;
parent
.
droit
=
new
Noeud
(
e
);
return
true
;
}
}
/**
taille
++;
* Recherche d'un nœud contenant la clé donnée
return
true
;
*/
}
private
Noeud
findNode
(
E
e
)
{
Noeud
cur
=
racine
;
/**
* Recherche d'un nœud contenant la clé donnée
while
(
cur
!=
null
)
{
*/
int
cmp
=
e
.
compareTo
(
cur
.
cle
);
private
Noeud
findNode
(
E
e
)
{
Noeud
actuel
=
racine
;
if
(
cmp
==
0
)
return
cur
;
while
(
actuel
!=
null
)
{
if
(
cmp
<
0
)
int
cmp
=
e
.
compareTo
(
actuel
.
cle
);
cur
=
cur
.
gauche
;
else
if
(
cmp
==
0
)
{
cur
=
cur
.
droit
;
return
actuel
;
}
}
return
null
;
if
(
cmp
<
0
)
{
actuel
=
actuel
.
gauche
;
}
else
{
actuel
=
actuel
.
droit
;
}
}
}
return
null
;
}
@Override
@Override
public
boolean
contains
(
Object
o
)
{
public
boolean
contains
(
Object
o
)
{
if
(
o
==
null
)
if
(
o
==
null
)
{
return
false
;
return
false
;
try
{
@SuppressWarnings
(
"unchecked"
)
E
e
=
(
E
)
o
;
return
findNode
(
e
)
!=
null
;
}
catch
(
ClassCastException
ex
)
{
return
false
;
}
}
}
@Override
try
{
public
boolean
remove
(
Object
o
)
{
@SuppressWarnings
(
"unchecked"
)
if
(
o
==
null
)
E
e
=
(
E
)
o
;
return
false
;
return
findNode
(
e
)
!=
null
;
}
catch
(
ClassCastException
ex
)
{
try
{
return
false
;
@SuppressWarnings
(
"unchecked"
)
E
e
=
(
E
)
o
;
}
catch
(
ClassCastException
ex
)
{
return
false
;
}
// Suppression simple (remplacement par successeur)
// (Pour les benchmarks, remove n'est pas essentiel)
E
key
=
(
E
)
o
;
Noeud
parent
=
null
,
cur
=
racine
;
// Recherche du nœud à supprimer
while
(
cur
!=
null
&&
!
cur
.
cle
.
equals
(
key
))
{
parent
=
cur
;
if
(
key
.
compareTo
(
cur
.
cle
)
<
0
)
cur
=
cur
.
gauche
;
else
cur
=
cur
.
droit
;
}
if
(
cur
==
null
)
return
false
;
// Cas où le nœud a deux enfants
if
(
cur
.
gauche
!=
null
&&
cur
.
droit
!=
null
)
{
Noeud
succParent
=
cur
,
succ
=
cur
.
droit
;
// Successeur = minimum du sous-arbre droit
while
(
succ
.
gauche
!=
null
)
{
succParent
=
succ
;
succ
=
succ
.
gauche
;
}
// Remplacer la clé
cur
.
cle
=
succ
.
cle
;
parent
=
succParent
;
cur
=
succ
;
}
// Cas 0 ou 1 enfant
Noeud
child
=
(
cur
.
gauche
!=
null
)
?
cur
.
gauche
:
cur
.
droit
;
if
(
parent
==
null
)
racine
=
child
;
else
if
(
parent
.
gauche
==
cur
)
parent
.
gauche
=
child
;
else
parent
.
droit
=
child
;
size
--;
return
true
;
}
}
}
@Override
@Override
public
Iterator
<
E
>
iterator
()
{
public
boolean
remove
(
Object
o
)
{
if
(
o
==
null
)
{
// Parcours en ordre croissant (in-order)
return
false
;
return
new
Iterator
<
E
>()
{
private
final
Stack
<
Noeud
>
st
=
init
(
racine
);
private
Stack
<
Noeud
>
init
(
Noeud
r
)
{
Stack
<
Noeud
>
s
=
new
Stack
<>();
Noeud
c
=
r
;
while
(
c
!=
null
)
{
s
.
push
(
c
);
c
=
c
.
gauche
;
}
return
s
;
}
@Override
public
boolean
hasNext
()
{
return
!
st
.
isEmpty
();
}
@Override
public
E
next
()
{
Noeud
n
=
st
.
pop
();
E
res
=
n
.
cle
;
Noeud
c
=
n
.
droit
;
while
(
c
!=
null
)
{
st
.
push
(
c
);
c
=
c
.
gauche
;
}
return
res
;
}
};
}
}
@Override
try
{
public
int
size
()
{
@SuppressWarnings
(
"unchecked"
)
return
size
;
E
e
=
(
E
)
o
;
}
catch
(
ClassCastException
ex
)
{
return
false
;
}
}
@Override
// Suppression simple (remplacement par successeur)
public
boolean
isEmpty
()
{
// (Pour les benchmarks, remove n'est pas essentiel)
return
size
==
0
;
E
key
=
(
E
)
o
;
Noeud
parent
=
null
;
Noeud
actuel
=
racine
;
// Recherche du nœud à supprimer
while
(
actuel
!=
null
&&
!
actuel
.
cle
.
equals
(
key
))
{
parent
=
actuel
;
if
(
key
.
compareTo
(
actuel
.
cle
)
<
0
)
{
actuel
=
actuel
.
gauche
;
}
else
{
actuel
=
actuel
.
droit
;
}
}
}
@Override
if
(
actuel
==
null
)
{
public
void
clear
()
{
return
false
;
racine
=
null
;
size
=
0
;
}
}
@Override
// Cas où le nœud a deux enfants
public
Object
[]
toArray
()
{
if
(
actuel
.
gauche
!=
null
&&
actuel
.
droit
!=
null
)
{
Object
[]
arr
=
new
Object
[
size
];
Noeud
succParent
=
actuel
;
int
i
=
0
;
Noeud
suivant
=
actuel
.
droit
;
// Successeur = minimum du sous-arbre droit
while
(
suivant
.
gauche
!=
null
)
{
succParent
=
suivant
;
suivant
=
suivant
.
gauche
;
}
// Remplacer la clé
actuel
.
cle
=
suivant
.
cle
;
parent
=
succParent
;
actuel
=
suivant
;
}
for
(
E
e
:
this
)
// Cas 0 ou 1 enfant
arr
[
i
++]
=
e
;
Noeud
child
=
(
actuel
.
gauche
!=
null
)
?
actuel
.
gauche
:
actuel
.
droit
;
return
arr
;
if
(
parent
==
null
)
{
racine
=
child
;
}
else
if
(
parent
.
gauche
==
actuel
)
{
parent
.
gauche
=
child
;
}
else
{
parent
.
droit
=
child
;
}
}
@Override
taille
--;
public
<
T
>
T
[]
toArray
(
T
[]
a
)
{
return
true
;
return
null
;
// même logique que RBTree ; omis pour brièveté
}
@Override
public
Iterator
<
E
>
iterator
()
{
// Parcours en ordre croissant (in-order)
return
new
Iterator
<
E
>()
{
private
final
Stack
<
Noeud
>
st
=
init
(
racine
);
private
Stack
<
Noeud
>
init
(
Noeud
r
)
{
Stack
<
Noeud
>
s
=
new
Stack
<>();
Noeud
c
=
r
;
while
(
c
!=
null
)
{
s
.
push
(
c
);
c
=
c
.
gauche
;
}
return
s
;
}
@Override
public
boolean
hasNext
()
{
return
!
st
.
isEmpty
();
}
@Override
public
E
next
()
{
Noeud
n
=
st
.
pop
();
E
res
=
n
.
cle
;
Noeud
c
=
n
.
droit
;
while
(
c
!=
null
)
{
st
.
push
(
c
);
c
=
c
.
gauche
;
}
return
res
;
}
};
}
@Override
public
int
size
()
{
return
taille
;
}
@Override
public
boolean
isEmpty
()
{
return
taille
==
0
;
}
@Override
public
void
clear
()
{
racine
=
null
;
taille
=
0
;
}
@Override
public
Object
[]
toArray
()
{
Object
[]
arr
=
new
Object
[
taille
];
int
i
=
0
;
for
(
E
e
:
this
)
{
arr
[
i
++]
=
e
;
}
}
@Override
return
arr
;
public
boolean
containsAll
(
Collection
<?>
c
)
{
}
for
(
Object
o
:
c
)
if
(!
contains
(
o
))
@Override
return
false
;
public
<
T
>
T
[]
toArray
(
T
[]
a
)
{
return
null
;
// même logique que RBTree ; omis pour brièveté
}
return
true
;
@Override
public
boolean
containsAll
(
Collection
<?>
c
)
{
for
(
Object
o
:
c
)
{
if
(!
contains
(
o
))
{
return
false
;
}
}
}
@Override
return
true
;
public
boolean
addAll
(
Collection
<?
extends
E
>
c
)
{
}
boolean
ch
=
false
;
for
(
E
e
:
c
)
@Override
ch
|=
add
(
e
);
public
boolean
addAll
(
Collection
<?
extends
E
>
c
)
{
boolean
ch
=
false
;
return
ch
;
for
(
E
e
:
c
)
{
ch
|=
add
(
e
);
}
}
@Override
return
ch
;
public
boolean
removeAll
(
Collection
<?>
c
)
{
}
boolean
ch
=
false
;
for
(
Object
o
:
c
)
@Override
ch
|=
remove
(
o
);
public
boolean
removeAll
(
Collection
<?>
c
)
{
boolean
ch
=
false
;
return
ch
;
for
(
Object
o
:
c
)
{
ch
|=
remove
(
o
);
}
}
@Override
return
ch
;
public
boolean
retainAll
(
Collection
<?>
c
)
{
}
List
<
E
>
del
=
new
ArrayList
<>();
// Construire la liste des éléments à supprimer
@Override
for
(
E
e
:
this
)
public
boolean
retainAll
(
Collection
<?>
c
)
{
if
(!
c
.
contains
(
e
))
List
<
E
>
del
=
new
ArrayList
<>();
del
.
add
(
e
);
// Supprimer les éléments
// Construire la liste des éléments à supprimer
for
(
E
e
:
del
)
for
(
E
e
:
this
)
{
remove
(
e
);
if
(!
c
.
contains
(
e
))
{
del
.
add
(
e
);
}
}
return
!
del
.
isEmpty
();
// Supprimer les éléments
for
(
E
e
:
del
)
{
remove
(
e
);
}
}
return
!
del
.
isEmpty
();
}
}
}
src/main/java/collection/Benchmark.java
Voir le fichier @
48bfbd49
...
@@ -11,128 +11,136 @@ import java.util.Random;
...
@@ -11,128 +11,136 @@ import java.util.Random;
public
class
Benchmark
{
public
class
Benchmark
{
private
static
final
Random
RNG
=
new
Random
(
12345
);
private
static
final
Random
RNG
=
new
Random
(
12345
);
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
final
int
[]
N_LIST
=
{
1000
,
2000
,
5000
,
10000
,
20000
,
50000
};
final
int
[]
nList
=
{
1000
,
2000
,
5000
,
10000
,
20000
,
50000
};
final
int
REP
=
5
;
final
int
repetition
=
5
;
// --- Create the 4 CSV writers ---
// --- Creation des 4 CSV avec leur enTete ---
PrintWriter
abrInsert
=
new
PrintWriter
(
new
FileWriter
(
"ABR_insert.csv"
));
PrintWriter
abrInsert
=
new
PrintWriter
(
new
FileWriter
(
"ABR_insert.csv"
));
PrintWriter
abrSearch
=
new
PrintWriter
(
new
FileWriter
(
"ABR_search.csv"
));
writeHeader
(
abrInsert
,
nList
);
PrintWriter
arnInsert
=
new
PrintWriter
(
new
FileWriter
(
"ARN_insert.csv"
));
PrintWriter
arnSearch
=
new
PrintWriter
(
new
FileWriter
(
"ARN_search.csv"
));
// Header line : n,1000,2000,...
PrintWriter
abrSearch
=
new
PrintWriter
(
new
FileWriter
(
"ABR_search.csv"
));
writeHeader
(
abrInsert
,
N_LIST
);
writeHeader
(
abrSearch
,
nList
);
writeHeader
(
abrSearch
,
N_LIST
);
writeHeader
(
arnInsert
,
N_LIST
);
writeHeader
(
arnSearch
,
N_LIST
);
// Scenarios
PrintWriter
arnInsert
=
new
PrintWriter
(
new
FileWriter
(
"ARN_insert.csv"
));
List
<
String
>
scenarios
=
Arrays
.
asList
(
"ASCENDANT"
,
"ALEATOIRE"
);
writeHeader
(
arnInsert
,
nList
);
// Process
each
structure
PrintWriter
arnS
ea
r
ch
=
new
PrintWriter
(
new
FileWriter
(
"ARN_search.csv"
));
for
(
String
structure
:
Arrays
.
asList
(
"ABR"
,
"ARN"
))
{
writeHeader
(
arnSearch
,
nList
);
for
(
String
scenario
:
scenarios
)
{
// Scenarios
List
<
String
>
scenarios
=
Arrays
.
asList
(
"ASCENDANT"
,
"ALEATOIRE"
);
// Buffers for one line of insert & search results
// Process each structure
List
<
Double
>
insertLine
=
new
ArrayList
<>();
for
(
String
structure
:
Arrays
.
asList
(
"ABR"
,
"ARN"
))
{
List
<
Double
>
searchLine
=
new
ArrayList
<>();
for
(
int
n
:
N_LIST
)
{
for
(
String
scenario
:
scenarios
)
{
long
insertSum
=
0
;
// Buffers for one line of insert & search results
long
searchSum
=
0
;
List
<
Double
>
insertLine
=
new
ArrayList
<>();
List
<
Double
>
searchLine
=
new
ArrayList
<>();
for
(
int
r
=
0
;
r
<
REP
;
r
++
)
{
for
(
int
n
:
nList
)
{
List
<
Integer
>
keys
=
new
ArrayList
<>();
long
insertSum
=
0
;
for
(
int
i
=
0
;
i
<
n
;
i
++)
long
searchSum
=
0
;
keys
.
add
(
i
);
if
(
scenario
.
equals
(
"ALEATOIRE"
))
{
for
(
int
r
=
0
;
r
<
repetition
;
r
++)
{
Collections
.
shuffle
(
keys
,
new
Random
(
RNG
.
nextLong
()));
}
long
[]
result
=
structure
.
equals
(
"ABR"
)
?
benchmarkABR
(
keys
,
n
)
:
benchmarkARN
(
keys
,
n
);
List
<
Integer
>
keys
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
keys
.
add
(
i
);
}
insertSum
+=
result
[
0
];
if
(
scenario
.
equals
(
"ALEATOIRE"
))
{
searchSum
+=
result
[
1
]
;
Collections
.
shuffle
(
keys
,
new
Random
(
RNG
.
nextLong
()))
;
}
}
insertLine
.
add
(
insertSum
/
(
double
)
REP
);
long
[]
result
=
structure
.
equals
(
"ABR"
)
?
benchmarkAbr
(
keys
,
n
)
:
benchmarkArn
(
keys
,
n
);
searchLine
.
add
(
searchSum
/
(
double
)
REP
);
System
.
out
.
printf
(
"Done %s %s n=%d\n"
,
structure
,
scenario
,
n
);
insertSum
+=
result
[
0
];
}
searchSum
+=
result
[
1
];
}
// Write to correct CSV
insertLine
.
add
(
insertSum
/
(
double
)
repetition
);
if
(
structure
.
equals
(
"ABR"
))
{
searchLine
.
add
(
searchSum
/
(
double
)
repetition
);
writeScenarioLine
(
abrInsert
,
scenario
,
insertLine
);
writeScenarioLine
(
abrSearch
,
scenario
,
searchLine
);
}
else
{
writeScenarioLine
(
arnInsert
,
scenario
,
insertLine
);
writeScenarioLine
(
arnSearch
,
scenario
,
searchLine
);
}
}
}
abrInsert
.
close
();
System
.
out
.
printf
(
"Done %s %s n=%d\n"
,
structure
,
scenario
,
n
);
abrSearch
.
close
();
}
arnInsert
.
close
();
arnSearch
.
close
();
System
.
out
.
println
(
"4 CSV créés au format tableau."
);
// Write to correct CSV
if
(
structure
.
equals
(
"ABR"
))
{
writeScenarioLine
(
abrInsert
,
scenario
,
insertLine
);
writeScenarioLine
(
abrSearch
,
scenario
,
searchLine
);
}
else
{
writeScenarioLine
(
arnInsert
,
scenario
,
insertLine
);
writeScenarioLine
(
arnSearch
,
scenario
,
searchLine
);
}
}
}
}
// -------------------------------------------------------
abrInsert
.
close
();
// Helper: header line
abrSearch
.
close
();
// -------------------------------------------------------
arnInsert
.
close
();
private
static
void
writeHeader
(
PrintWriter
pw
,
int
[]
nList
)
{
arnSearch
.
close
();
pw
.
print
(
"n"
);
for
(
int
n
:
nList
)
System
.
out
.
println
(
"4 CSV créés au format tableau."
);
pw
.
print
(
","
+
n
);
}
pw
.
println
();
// -------------------------------------------------------
// Helper: header line
// -------------------------------------------------------
private
static
void
writeHeader
(
PrintWriter
pw
,
int
[]
nlist
)
{
pw
.
print
(
"n"
);
for
(
int
n
:
nlist
)
{
pw
.
print
(
","
+
n
);
}
}
// -------------------------------------------------------
pw
.
println
();
// Helper: write one scenario line
}
// -------------------------------------------------------
private
static
void
writeScenarioLine
(
PrintWriter
pw
,
String
scenario
,
List
<
Double
>
values
)
{
// -------------------------------------------------------
pw
.
print
(
scenario
);
// Helper: write one scenario line
for
(
double
v
:
values
)
// -------------------------------------------------------
pw
.
printf
(
",%.2f"
,
v
);
private
static
void
writeScenarioLine
(
PrintWriter
pw
,
String
scenario
,
List
<
Double
>
values
)
{
pw
.
println
();
pw
.
print
(
scenario
);
for
(
double
v
:
values
)
{
pw
.
printf
(
",%.2f"
,
v
);
}
}
// -------------------------------------------------------
pw
.
println
();
// Benchmark ABR / ARN
}
// -------------------------------------------------------
private
static
long
[]
benchmarkABR
(
List
<
Integer
>
keys
,
int
n
)
{
// -------------------------------------------------------
Collection
<
Integer
>
tree
=
new
ArbreBinaireRecherche
<>();
// Benchmark ABR / ARN
return
runBenchmark
(
tree
,
keys
,
n
);
// -------------------------------------------------------
}
private
static
long
[]
benchmarkA
RN
(
List
<
Integer
>
keys
,
int
n
)
{
private
static
long
[]
benchmarkA
br
(
List
<
Integer
>
keys
,
int
n
)
{
Collection
<
Integer
>
tree
=
new
RedBlackTre
e
<>();
Collection
<
Integer
>
tree
=
new
ArbreBinaireRecherch
e
<>();
return
runBenchmark
(
tree
,
keys
,
n
);
return
runBenchmark
(
tree
,
keys
,
n
);
}
}
private
static
long
[]
runBenchmark
(
Collection
<
Integer
>
tree
,
List
<
Integer
>
keys
,
int
n
)
{
private
static
long
[]
benchmarkArn
(
List
<
Integer
>
keys
,
int
n
)
{
long
t0
=
System
.
nanoTime
();
Collection
<
Integer
>
tree
=
new
RedBlackTree
<>();
for
(
Integer
k
:
keys
)
return
runBenchmark
(
tree
,
keys
,
n
);
tree
.
add
(
k
);
}
long
t1
=
System
.
nanoTime
();
long
t2
=
System
.
nanoTime
();
private
static
long
[]
runBenchmark
(
Collection
<
Integer
>
tree
,
List
<
Integer
>
keys
,
int
n
)
{
for
(
int
x
=
0
;
x
<
2
*
n
;
x
++)
long
t0
=
System
.
nanoTime
();
tree
.
contains
(
x
);
for
(
Integer
k
:
keys
)
{
long
t3
=
System
.
nanoTime
();
tree
.
add
(
k
);
}
long
t1
=
System
.
nanoTime
();
return
new
long
[]
{
t1
-
t0
,
t3
-
t2
};
long
t2
=
System
.
nanoTime
();
for
(
int
x
=
0
;
x
<
2
*
n
;
x
++)
{
tree
.
contains
(
x
);
}
}
long
t3
=
System
.
nanoTime
();
return
new
long
[]
{
t1
-
t0
,
t3
-
t2
};
}
}
}
src/main/java/collection/RedBlackTree.java
Voir le fichier @
48bfbd49
...
@@ -16,497 +16,543 @@ import java.util.Stack;
...
@@ -16,497 +16,543 @@ import java.util.Stack;
* contiennent le même nombre de nœuds noirs
* contiennent le même nombre de nœuds noirs
*/
*/
public
class
RedBlackTree
<
E
extends
Comparable
<
E
>>
implements
Collection
<
E
>
{
public
class
RedBlackTree
<
E
extends
Comparable
<
E
>>
implements
Collection
<
E
>
{
private
static
final
boolean
RED
=
true
;
private
static
final
boolean
ROUGE
=
true
;
private
static
final
boolean
BLACK
=
false
;
private
static
final
boolean
NOIR
=
false
;
/** Classe interne représentant un nœud de l'arbre */
/** Classe interne représentant un nœud de l'arbre */
private
class
Node
{
private
class
Noeud
{
E
key
;
E
cle
;
Node
left
,
right
,
parent
;
Noeud
gauche
;
boolean
color
=
RED
;
// par défaut, un nouveau nœud est rouge
Noeud
droit
;
Noeud
parent
;
Node
(
E
key
,
Node
parent
)
{
boolean
color
=
ROUGE
;
// par défaut, un nouveau nœud est rouge
this
.
key
=
key
;
this
.
parent
=
parent
;
Noeud
(
E
cle
,
Noeud
parent
)
{
}
this
.
cle
=
cle
;
this
.
parent
=
parent
;
}
}
}
private
No
de
root
;
private
No
eud
racine
;
private
int
siz
e
=
0
;
private
int
taill
e
=
0
;
/** Rotation gauche standard */
/** Rotation gauche standard */
private
void
rotateLeft
(
No
d
e
x
)
{
private
void
rotateLeft
(
Noe
ud
x
)
{
Node
y
=
x
.
righ
t
;
Noeud
y
=
x
.
droi
t
;
x
.
right
=
y
.
left
;
x
.
droit
=
y
.
gauche
;
if
(
y
.
left
!=
null
)
if
(
y
.
gauche
!=
null
)
{
y
.
left
.
parent
=
x
;
y
.
gauche
.
parent
=
x
;
}
y
.
parent
=
x
.
parent
;
if
(
x
.
parent
==
null
)
y
.
parent
=
x
.
parent
;
root
=
y
;
else
if
(
x
==
x
.
parent
.
left
)
x
.
parent
.
left
=
y
;
else
x
.
parent
.
right
=
y
;
y
.
left
=
x
;
if
(
x
.
parent
==
null
)
{
x
.
parent
=
y
;
racine
=
y
;
}
else
if
(
x
==
x
.
parent
.
gauche
)
{
x
.
parent
.
gauche
=
y
;
}
else
{
x
.
parent
.
droit
=
y
;
}
}
/** Rotation droite standard */
y
.
gauche
=
x
;
private
void
rotateRight
(
Node
x
)
{
x
.
parent
=
y
;
Node
y
=
x
.
left
;
}
x
.
left
=
y
.
right
;
if
(
y
.
right
!=
null
)
/** Rotation droite standard */
y
.
right
.
parent
=
x
;
private
void
rotateRight
(
Noeud
x
)
{
Noeud
y
=
x
.
gauche
;
x
.
gauche
=
y
.
droit
;
y
.
parent
=
x
.
parent
;
if
(
y
.
droit
!=
null
)
{
y
.
droit
.
parent
=
x
;
}
if
(
x
.
parent
==
null
)
y
.
parent
=
x
.
parent
;
root
=
y
;
else
if
(
x
==
x
.
parent
.
right
)
x
.
parent
.
right
=
y
;
else
x
.
parent
.
left
=
y
;
y
.
right
=
x
;
if
(
x
.
parent
==
null
)
{
x
.
parent
=
y
;
racine
=
y
;
}
else
if
(
x
==
x
.
parent
.
droit
)
{
x
.
parent
.
droit
=
y
;
}
else
{
x
.
parent
.
gauche
=
y
;
}
}
/**
y
.
droit
=
x
;
* Correction après insertion. Assure que les propriétés RB sont conservées.
x
.
parent
=
y
;
*/
}
private
void
fixAfterInsert
(
Node
z
)
{
while
(
z
.
parent
!=
null
&&
z
.
parent
.
color
==
RED
)
{
/**
if
(
z
.
parent
==
z
.
parent
.
parent
.
left
)
{
* Correction après insertion. Assure que les propriétés RB sont conservées.
Node
y
=
z
.
parent
.
parent
.
right
;
// oncle
*/
private
void
fixAfterInsert
(
Noeud
z
)
{
if
(
y
!=
null
&&
y
.
color
==
RED
)
{
while
(
z
.
parent
!=
null
&&
z
.
parent
.
color
==
ROUGE
)
{
// Cas 1 : parent rouge + oncle rouge -> recolorations
if
(
z
.
parent
==
z
.
parent
.
parent
.
gauche
)
{
z
.
parent
.
color
=
BLACK
;
Noeud
y
=
z
.
parent
.
parent
.
droit
;
// oncle
y
.
color
=
BLACK
;
z
.
parent
.
parent
.
color
=
RED
;
if
(
y
!=
null
&&
y
.
color
==
ROUGE
)
{
z
=
z
.
parent
.
parent
;
// Cas 1 : parent rouge + oncle rouge -> recolorations
}
else
{
z
.
parent
.
color
=
NOIR
;
if
(
z
==
z
.
parent
.
right
)
{
y
.
color
=
NOIR
;
// Cas 2 : triangle -> rotation gauche
z
.
parent
.
parent
.
color
=
ROUGE
;
z
=
z
.
parent
;
z
=
z
.
parent
.
parent
;
rotateLeft
(
z
);
}
else
{
}
if
(
z
==
z
.
parent
.
droit
)
{
// Cas 2 : triangle -> rotation gauche
// Cas 3 : ligne -> rotation droite
z
=
z
.
parent
;
z
.
parent
.
color
=
BLACK
;
rotateLeft
(
z
);
z
.
parent
.
parent
.
color
=
RED
;
}
rotateRight
(
z
.
parent
.
parent
);
}
// Cas 3 : ligne -> rotation droite
}
else
{
z
.
parent
.
color
=
NOIR
;
// Symétrique : parent est enfant droit
z
.
parent
.
parent
.
color
=
ROUGE
;
Node
y
=
z
.
parent
.
parent
.
left
;
rotateRight
(
z
.
parent
.
parent
);
}
if
(
y
!=
null
&&
y
.
color
==
RED
)
{
}
else
{
z
.
parent
.
color
=
BLACK
;
// Symétrique : parent est enfant droit
y
.
color
=
BLACK
;
Noeud
y
=
z
.
parent
.
parent
.
gauche
;
z
.
parent
.
parent
.
color
=
RED
;
z
=
z
.
parent
.
parent
;
if
(
y
!=
null
&&
y
.
color
==
ROUGE
)
{
}
else
{
z
.
parent
.
color
=
NOIR
;
if
(
z
==
z
.
parent
.
left
)
{
y
.
color
=
NOIR
;
z
=
z
.
parent
;
z
.
parent
.
parent
.
color
=
ROUGE
;
rotateRight
(
z
);
z
=
z
.
parent
.
parent
;
}
}
else
{
z
.
parent
.
color
=
BLACK
;
if
(
z
==
z
.
parent
.
gauche
)
{
z
.
parent
.
parent
.
color
=
RED
;
z
=
z
.
parent
;
rotateLeft
(
z
.
parent
.
parent
);
rotateRight
(
z
);
}
}
}
z
.
parent
.
color
=
NOIR
;
}
z
.
parent
.
parent
.
color
=
ROUGE
;
rotateLeft
(
z
.
parent
.
parent
);
root
.
color
=
BLACK
;
}
}
}
}
/** Remplace un nœud par un autre dans l’arbre */
racine
.
color
=
NOIR
;
private
void
transplant
(
Node
u
,
Node
v
)
{
}
if
(
u
.
parent
==
null
)
root
=
v
;
/** Remplace un nœud par un autre dans l’arbre */
else
if
(
u
==
u
.
parent
.
left
)
private
void
transplant
(
Noeud
u
,
Noeud
v
)
{
u
.
parent
.
left
=
v
;
if
(
u
.
parent
==
null
)
{
else
racine
=
v
;
u
.
parent
.
right
=
v
;
}
else
if
(
u
==
u
.
parent
.
gauche
)
{
u
.
parent
.
gauche
=
v
;
if
(
v
!=
null
)
}
else
{
v
.
parent
=
u
.
parent
;
u
.
parent
.
droit
=
v
;
}
}
/** Renvoie le minimum du sous-arbre */
if
(
v
!=
null
)
{
private
Node
minimum
(
Node
x
)
{
v
.
parent
=
u
.
parent
;
while
(
x
.
left
!=
null
)
x
=
x
.
left
;
return
x
;
}
}
}
/**
/** Renvoie le minimum du sous-arbre */
* Correction après suppression. Restaure les propriétés Rouge-Noir.
private
Noeud
minimum
(
Noeud
x
)
{
*/
while
(
x
.
gauche
!=
null
)
{
private
void
fixAfterDelete
(
Node
x
,
Node
parent
)
{
x
=
x
.
gauche
;
while
((
x
!=
root
)
&&
(
x
==
null
||
x
.
color
==
BLACK
))
{
if
(
parent
!=
null
&&
x
==
parent
.
left
)
{
Node
w
=
parent
.
right
;
if
(
w
!=
null
&&
w
.
color
==
RED
)
{
w
.
color
=
BLACK
;
parent
.
color
=
RED
;
rotateLeft
(
parent
);
w
=
parent
.
right
;
}
if
((
w
==
null
)
||
((
w
.
left
==
null
||
w
.
left
.
color
==
BLACK
)
&&
(
w
.
right
==
null
||
w
.
right
.
color
==
BLACK
)))
{
if
(
w
!=
null
)
w
.
color
=
RED
;
x
=
parent
;
parent
=
x
.
parent
;
}
else
{
if
(
w
.
right
==
null
||
w
.
right
.
color
==
BLACK
)
{
if
(
w
.
left
!=
null
)
w
.
left
.
color
=
BLACK
;
w
.
color
=
RED
;
rotateRight
(
w
);
w
=
parent
.
right
;
}
if
(
w
!=
null
)
w
.
color
=
parent
.
color
;
parent
.
color
=
BLACK
;
if
(
w
!=
null
&&
w
.
right
!=
null
)
w
.
right
.
color
=
BLACK
;
rotateLeft
(
parent
);
x
=
root
;
break
;
}
}
else
{
if
(
parent
==
null
)
break
;
Node
w
=
parent
.
left
;
if
(
w
!=
null
&&
w
.
color
==
RED
)
{
w
.
color
=
BLACK
;
parent
.
color
=
RED
;
rotateRight
(
parent
);
w
=
parent
.
left
;
}
if
((
w
==
null
)
||
((
w
.
right
==
null
||
w
.
right
.
color
==
BLACK
)
&&
(
w
.
left
==
null
||
w
.
left
.
color
==
BLACK
)))
{
if
(
w
!=
null
)
w
.
color
=
RED
;
x
=
parent
;
parent
=
x
.
parent
;
}
else
{
if
(
w
.
left
==
null
||
w
.
left
.
color
==
BLACK
)
{
if
(
w
.
right
!=
null
)
w
.
right
.
color
=
BLACK
;
w
.
color
=
RED
;
rotateLeft
(
w
);
w
=
parent
.
left
;
}
if
(
w
!=
null
)
w
.
color
=
parent
.
color
;
parent
.
color
=
BLACK
;
if
(
w
!=
null
&&
w
.
left
!=
null
)
w
.
left
.
color
=
BLACK
;
rotateRight
(
parent
);
x
=
root
;
break
;
}
}
}
if
(
x
!=
null
)
x
.
color
=
BLACK
;
}
}
@Override
return
x
;
public
boolean
add
(
E
e
)
{
}
Objects
.
requireNonNull
(
e
);
/**
// Arbre vide : nouvelle racine noire
* Correction après suppression. Restaure les propriétés Rouge-Noir.
if
(
root
==
null
)
{
*/
root
=
new
Node
(
e
,
null
);
private
void
fixAfterDelete
(
Noeud
x
,
Noeud
parent
)
{
root
.
color
=
BLACK
;
while
((
x
!=
racine
)
&&
(
x
==
null
||
x
.
color
==
NOIR
))
{
size
=
1
;
if
(
parent
!=
null
&&
x
==
parent
.
gauche
)
{
return
true
;
Noeud
w
=
parent
.
droit
;
}
if
(
w
!=
null
&&
w
.
color
==
ROUGE
)
{
Node
cur
=
root
,
parent
=
null
;
w
.
color
=
NOIR
;
int
cmp
=
0
;
parent
.
color
=
ROUGE
;
rotateLeft
(
parent
);
// Recherche de la position d'insertion
w
=
parent
.
droit
;
while
(
cur
!=
null
)
{
}
parent
=
cur
;
cmp
=
e
.
compareTo
(
cur
.
key
);
if
((
w
==
null
)
||
((
w
.
gauche
==
null
||
w
.
gauche
.
color
==
NOIR
)
&&
(
w
.
droit
==
null
||
w
.
droit
.
color
==
NOIR
)))
{
if
(
cmp
<
0
)
if
(
w
!=
null
)
{
cur
=
cur
.
left
;
w
.
color
=
ROUGE
;
else
if
(
cmp
>
0
)
}
cur
=
cur
.
right
;
else
x
=
parent
;
return
false
;
// pas de doublons
parent
=
x
.
parent
;
}
}
else
{
if
(
w
.
droit
==
null
||
w
.
droit
.
color
==
NOIR
)
{
Node
node
=
new
Node
(
e
,
parent
);
if
(
w
.
gauche
!=
null
)
{
w
.
gauche
.
color
=
NOIR
;
if
(
cmp
<
0
)
}
parent
.
left
=
node
;
else
w
.
color
=
ROUGE
;
parent
.
right
=
node
;
rotateRight
(
w
);
w
=
parent
.
droit
;
// Correction RB après insertion
}
fixAfterInsert
(
node
);
size
++;
if
(
w
!=
null
)
{
w
.
color
=
parent
.
color
;
return
true
;
}
parent
.
color
=
NOIR
;
if
(
w
!=
null
&&
w
.
droit
!=
null
)
{
w
.
droit
.
color
=
NOIR
;
}
rotateLeft
(
parent
);
x
=
racine
;
break
;
}
}
else
{
if
(
parent
==
null
)
{
break
;
}
Noeud
w
=
parent
.
gauche
;
if
(
w
!=
null
&&
w
.
color
==
ROUGE
)
{
w
.
color
=
NOIR
;
parent
.
color
=
ROUGE
;
rotateRight
(
parent
);
w
=
parent
.
gauche
;
}
if
((
w
==
null
)
||
((
w
.
droit
==
null
||
w
.
droit
.
color
==
NOIR
)
&&
(
w
.
gauche
==
null
||
w
.
gauche
.
color
==
NOIR
)))
{
if
(
w
!=
null
)
{
w
.
color
=
ROUGE
;
}
x
=
parent
;
parent
=
x
.
parent
;
}
else
{
if
(
w
.
gauche
==
null
||
w
.
gauche
.
color
==
NOIR
)
{
if
(
w
.
droit
!=
null
)
{
w
.
droit
.
color
=
NOIR
;
}
w
.
color
=
ROUGE
;
rotateLeft
(
w
);
w
=
parent
.
gauche
;
}
if
(
w
!=
null
)
{
w
.
color
=
parent
.
color
;
}
parent
.
color
=
NOIR
;
if
(
w
!=
null
&&
w
.
gauche
!=
null
)
{
w
.
gauche
.
color
=
NOIR
;
}
rotateRight
(
parent
);
x
=
racine
;
break
;
}
}
}
}
/** Recherche un nœud contenant la clé */
if
(
x
!=
null
)
{
private
Node
findNode
(
E
e
)
{
x
.
color
=
NOIR
;
Node
cur
=
root
;
}
}
@Override
public
boolean
add
(
E
e
)
{
Objects
.
requireNonNull
(
e
);
// Arbre vide : nouvelle racine noire
if
(
racine
==
null
)
{
racine
=
new
Noeud
(
e
,
null
);
racine
.
color
=
NOIR
;
taille
=
1
;
return
true
;
}
while
(
cur
!=
null
)
{
Noeud
cur
=
racine
;
int
cmp
=
e
.
compareTo
(
cur
.
key
);
Noeud
parent
=
null
;
int
cmp
=
0
;
// Recherche de la position d'insertion
while
(
cur
!=
null
)
{
parent
=
cur
;
cmp
=
e
.
compareTo
(
cur
.
cle
);
if
(
cmp
<
0
)
{
cur
=
cur
.
gauche
;
}
else
if
(
cmp
>
0
)
{
cur
=
cur
.
droit
;
}
else
{
return
false
;
// pas de doublons
}
}
if
(
cmp
==
0
)
Noeud
node
=
new
Noeud
(
e
,
parent
);
return
cur
;
if
(
cmp
<
0
)
cur
=
cur
.
left
;
else
cur
=
cur
.
right
;
}
return
null
;
if
(
cmp
<
0
)
{
parent
.
gauche
=
node
;
}
else
{
parent
.
droit
=
node
;
}
}
@Override
// Correction RB après insertion
public
boolean
contains
(
Object
o
)
{
fixAfterInsert
(
node
);
if
(
o
==
null
)
taille
++;
return
false
;
try
{
return
true
;
@SuppressWarnings
(
"unchecked"
)
}
E
e
=
(
E
)
o
;
return
findNode
(
e
)
!=
null
;
/** Recherche un nœud contenant la clé */
}
catch
(
ClassCastException
ex
)
{
private
Noeud
findNode
(
E
e
)
{
return
false
;
Noeud
cur
=
racine
;
}
while
(
cur
!=
null
)
{
int
cmp
=
e
.
compareTo
(
cur
.
cle
);
if
(
cmp
==
0
)
{
return
cur
;
}
if
(
cmp
<
0
)
{
cur
=
cur
.
gauche
;
}
else
{
cur
=
cur
.
droit
;
}
}
}
@Override
return
null
;
public
boolean
remove
(
Object
o
)
{
}
if
(
o
==
null
)
return
false
;
@Override
public
boolean
contains
(
Object
o
)
{
E
e
;
if
(
o
==
null
)
{
return
false
;
try
{
e
=
(
E
)
o
;
}
catch
(
ClassCastException
ex
)
{
return
false
;
}
Node
z
=
findNode
(
e
);
if
(
z
==
null
)
return
false
;
Node
y
=
z
;
boolean
yOriginalColor
=
y
.
color
;
Node
x
;
Node
xParent
;
// Cas 1 : un seul enfant
if
(
z
.
left
==
null
)
{
x
=
z
.
right
;
xParent
=
z
.
parent
;
transplant
(
z
,
z
.
right
);
}
else
if
(
z
.
right
==
null
)
{
x
=
z
.
left
;
xParent
=
z
.
parent
;
transplant
(
z
,
z
.
left
);
}
// Cas 2 : deux enfants → successeur
else
{
y
=
minimum
(
z
.
right
);
yOriginalColor
=
y
.
color
;
x
=
y
.
right
;
if
(
y
.
parent
==
z
)
{
if
(
x
!=
null
)
x
.
parent
=
y
;
xParent
=
y
;
}
else
{
transplant
(
y
,
y
.
right
);
y
.
right
=
z
.
right
;
if
(
y
.
right
!=
null
)
y
.
right
.
parent
=
y
;
xParent
=
y
.
parent
;
}
transplant
(
z
,
y
);
y
.
left
=
z
.
left
;
if
(
y
.
left
!=
null
)
y
.
left
.
parent
=
y
;
y
.
color
=
z
.
color
;
}
if
(
yOriginalColor
==
BLACK
)
fixAfterDelete
(
x
,
xParent
);
size
--;
return
true
;
}
}
@Override
try
{
public
Iterator
<
E
>
iterator
()
{
@SuppressWarnings
(
"unchecked"
)
return
new
Iterator
<
E
>()
{
E
e
=
(
E
)
o
;
private
final
Stack
<
Node
>
stack
=
initStack
(
root
);
return
findNode
(
e
)
!=
null
;
}
catch
(
ClassCastException
ex
)
{
private
Stack
<
Node
>
initStack
(
Node
r
)
{
return
false
;
Stack
<
Node
>
s
=
new
Stack
<>();
Node
cur
=
r
;
while
(
cur
!=
null
)
{
s
.
push
(
cur
);
cur
=
cur
.
left
;
}
return
s
;
}
@Override
public
boolean
hasNext
()
{
return
!
stack
.
isEmpty
();
}
@Override
public
E
next
()
{
if
(!
hasNext
())
throw
new
NoSuchElementException
();
Node
n
=
stack
.
pop
();
E
res
=
n
.
key
;
Node
cur
=
n
.
right
;
// Descente maximale à gauche
while
(
cur
!=
null
)
{
stack
.
push
(
cur
);
cur
=
cur
.
left
;
}
return
res
;
}
@Override
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
};
}
}
}
@Override
@Override
public
int
size
()
{
public
boolean
remove
(
Object
o
)
{
return
size
;
if
(
o
==
null
)
{
return
false
;
}
}
@Override
E
e
;
public
boolean
isEmpty
()
{
return
size
==
0
;
try
{
e
=
(
E
)
o
;
}
catch
(
ClassCastException
ex
)
{
return
false
;
}
}
@Override
Noeud
z
=
findNode
(
e
);
public
void
clear
()
{
root
=
null
;
if
(
z
=
=
null
)
{
size
=
0
;
return
false
;
}
}
@Override
Noeud
y
=
z
;
public
Object
[]
toArray
()
{
boolean
yorigColor
=
y
.
color
;
Object
[]
arr
=
new
Object
[
size
];
Noeud
x
;
int
i
=
0
;
Noeud
xparent
;
// Cas 1 : un seul enfant
if
(
z
.
gauche
==
null
)
{
x
=
z
.
droit
;
xparent
=
z
.
parent
;
transplant
(
z
,
z
.
droit
);
}
else
if
(
z
.
droit
==
null
)
{
x
=
z
.
gauche
;
xparent
=
z
.
parent
;
transplant
(
z
,
z
.
gauche
);
}
else
{
// Cas 2 : deux enfants → successeur
y
=
minimum
(
z
.
droit
);
yorigColor
=
y
.
color
;
x
=
y
.
droit
;
if
(
y
.
parent
==
z
)
{
if
(
x
!=
null
)
{
x
.
parent
=
y
;
}
xparent
=
y
;
}
else
{
transplant
(
y
,
y
.
droit
);
y
.
droit
=
z
.
droit
;
if
(
y
.
droit
!=
null
)
{
y
.
droit
.
parent
=
y
;
}
xparent
=
y
.
parent
;
}
transplant
(
z
,
y
);
y
.
gauche
=
z
.
gauche
;
if
(
y
.
gauche
!=
null
)
{
y
.
gauche
.
parent
=
y
;
}
y
.
color
=
z
.
color
;
}
for
(
E
e
:
this
)
if
(
yorigColor
==
NOIR
)
{
arr
[
i
++]
=
e
;
fixAfterDelete
(
x
,
xparent
);
}
return
arr
;
taille
--;
return
true
;
}
@Override
public
Iterator
<
E
>
iterator
()
{
return
new
Iterator
<
E
>()
{
private
final
Stack
<
Noeud
>
stack
=
initStack
(
racine
);
private
Stack
<
Noeud
>
initStack
(
Noeud
r
)
{
Stack
<
Noeud
>
s
=
new
Stack
<>();
Noeud
cur
=
r
;
while
(
cur
!=
null
)
{
s
.
push
(
cur
);
cur
=
cur
.
gauche
;
}
return
s
;
}
@Override
public
boolean
hasNext
()
{
return
!
stack
.
isEmpty
();
}
@Override
public
E
next
()
{
if
(!
hasNext
())
{
throw
new
NoSuchElementException
();
}
Noeud
n
=
stack
.
pop
();
E
res
=
n
.
cle
;
Noeud
cur
=
n
.
droit
;
// Descente maximale à gauche
while
(
cur
!=
null
)
{
stack
.
push
(
cur
);
cur
=
cur
.
gauche
;
}
return
res
;
}
@Override
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
};
}
@Override
public
int
size
()
{
return
taille
;
}
@Override
public
boolean
isEmpty
()
{
return
taille
==
0
;
}
@Override
public
void
clear
()
{
racine
=
null
;
taille
=
0
;
}
@Override
public
Object
[]
toArray
()
{
Object
[]
arr
=
new
Object
[
taille
];
int
i
=
0
;
for
(
E
e
:
this
)
{
arr
[
i
++]
=
e
;
}
}
@Override
return
arr
;
public
<
T
>
T
[]
toArray
(
T
[]
a
)
{
}
if
(
a
.
length
<
size
)
a
=
(
T
[])
java
.
lang
.
reflect
.
Array
.
newInstance
(
a
.
getClass
().
getComponentType
(),
size
);
int
i
=
0
;
@Override
public
<
T
>
T
[]
toArray
(
T
[]
a
)
{
if
(
a
.
length
<
taille
)
{
a
=
(
T
[])
java
.
lang
.
reflect
.
Array
.
newInstance
(
a
.
getClass
().
getComponentType
(),
taille
);
}
for
(
E
e
:
this
)
int
i
=
0
;
a
[
i
++]
=
(
T
)
e
;
if
(
a
.
length
>
size
)
for
(
E
e
:
this
)
{
a
[
size
]
=
null
;
a
[
i
++]
=
(
T
)
e
;
}
return
a
;
if
(
a
.
length
>
taille
)
{
a
[
taille
]
=
null
;
}
}
@Override
return
a
;
public
boolean
containsAll
(
Collection
<?>
c
)
{
}
for
(
Object
o
:
c
)
if
(!
contains
(
o
))
@Override
return
false
;
public
boolean
containsAll
(
Collection
<?>
c
)
{
return
true
;
for
(
Object
o
:
c
)
{
if
(!
contains
(
o
))
{
return
false
;
}
}
}
@Override
return
true
;
public
boolean
addAll
(
Collection
<?
extends
E
>
c
)
{
}
boolean
changed
=
false
;
for
(
E
e
:
c
)
@Override
changed
|=
add
(
e
);
public
boolean
addAll
(
Collection
<?
extends
E
>
c
)
{
return
changed
;
boolean
changed
=
false
;
for
(
E
e
:
c
)
{
changed
|=
add
(
e
);
}
}
@Override
return
changed
;
public
boolean
removeAll
(
Collection
<?>
c
)
{
}
boolean
changed
=
false
;
for
(
Object
o
:
c
)
@Override
changed
|=
remove
(
o
);
public
boolean
removeAll
(
Collection
<?>
c
)
{
return
changed
;
boolean
changed
=
false
;
for
(
Object
o
:
c
)
{
changed
|=
remove
(
o
);
}
}
@Override
return
changed
;
public
boolean
retainAll
(
Collection
<?>
c
)
{
}
List
<
E
>
toRemove
=
new
ArrayList
<>();
for
(
E
e
:
this
)
@Override
if
(!
c
.
contains
(
e
))
public
boolean
retainAll
(
Collection
<?>
c
)
{
toRemove
.
add
(
e
);
List
<
E
>
toRemove
=
new
ArrayList
<>(
);
for
(
E
e
:
toRemove
)
for
(
E
e
:
this
)
{
remove
(
e
);
if
(!
c
.
contains
(
e
))
{
toRemove
.
add
(
e
);
}
}
return
!
toRemove
.
isEmpty
();
for
(
E
e
:
toRemove
)
{
remove
(
e
);
}
}
return
!
toRemove
.
isEmpty
();
}
}
}
src/test/java/collection/ArbreBinaireRechercheTest.java
0 → 100644
Voir le fichier @
48bfbd49
package
collection
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertArrayEquals
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertDoesNotThrow
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertEquals
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertFalse
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertNull
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertTrue
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
java.util.List
;
import
org.junit.jupiter.api.BeforeEach
;
import
org.junit.jupiter.api.Test
;
public
class
ArbreBinaireRechercheTest
{
private
ArbreBinaireRecherche
<
Integer
>
arbre
;
@BeforeEach
void
setUp
()
{
arbre
=
new
ArbreBinaireRecherche
<>();
}
@Test
void
testAdd
()
{
assertTrue
(
arbre
.
add
(
5
));
assertTrue
(
arbre
.
add
(
3
));
assertTrue
(
arbre
.
add
(
7
));
assertFalse
(
arbre
.
add
(
5
));
// doublon
assertEquals
(
3
,
arbre
.
size
());
}
@Test
void
testContains
()
{
arbre
.
add
(
5
);
arbre
.
add
(
2
);
arbre
.
add
(
8
);
assertTrue
(
arbre
.
contains
(
5
));
assertTrue
(
arbre
.
contains
(
2
));
assertFalse
(
arbre
.
contains
(
10
));
assertFalse
(
arbre
.
contains
(
null
));
}
@Test
void
testRemoveFeuille
()
{
arbre
.
add
(
5
);
arbre
.
add
(
3
);
arbre
.
add
(
8
);
assertTrue
(
arbre
.
remove
(
3
));
assertFalse
(
arbre
.
contains
(
3
));
assertEquals
(
2
,
arbre
.
size
());
}
@Test
void
testRemoveNoeudAvecUnEnfant
()
{
arbre
.
add
(
5
);
arbre
.
add
(
3
);
arbre
.
add
(
2
);
// enfant de 3
assertTrue
(
arbre
.
remove
(
3
));
assertTrue
(
arbre
.
contains
(
2
));
assertFalse
(
arbre
.
contains
(
3
));
assertEquals
(
2
,
arbre
.
size
());
}
@Test
void
testRemoveNoeudDeuxEnfants
()
{
arbre
.
add
(
5
);
arbre
.
add
(
3
);
arbre
.
add
(
7
);
arbre
.
add
(
6
);
arbre
.
add
(
8
);
assertTrue
(
arbre
.
remove
(
7
));
assertFalse
(
arbre
.
contains
(
7
));
assertEquals
(
4
,
arbre
.
size
());
}
@Test
void
testIteratorOrdreCroissant
()
{
arbre
.
add
(
5
);
arbre
.
add
(
2
);
arbre
.
add
(
8
);
arbre
.
add
(
1
);
arbre
.
add
(
3
);
Iterator
<
Integer
>
it
=
arbre
.
iterator
();
assertEquals
(
1
,
it
.
next
());
assertEquals
(
2
,
it
.
next
());
assertEquals
(
3
,
it
.
next
());
assertEquals
(
5
,
it
.
next
());
assertEquals
(
8
,
it
.
next
());
assertFalse
(
it
.
hasNext
());
}
@Test
void
testClear
()
{
arbre
.
add
(
4
);
arbre
.
add
(
1
);
arbre
.
add
(
9
);
arbre
.
clear
();
assertTrue
(
arbre
.
isEmpty
());
assertEquals
(
0
,
arbre
.
size
());
assertFalse
(
arbre
.
contains
(
4
));
}
@Test
void
testToArray
()
{
arbre
.
add
(
3
);
arbre
.
add
(
1
);
arbre
.
add
(
2
);
Object
[]
arr
=
arbre
.
toArray
();
assertEquals
(
3
,
arr
.
length
);
assertArrayEquals
(
new
Object
[]
{
1
,
2
,
3
},
arr
);
}
@Test
void
testAddAll
()
{
List
<
Integer
>
list
=
Arrays
.
asList
(
5
,
2
,
8
);
assertTrue
(
arbre
.
addAll
(
list
));
assertEquals
(
3
,
arbre
.
size
());
assertTrue
(
arbre
.
contains
(
8
));
}
@Test
void
testRemoveAll
()
{
arbre
.
add
(
5
);
arbre
.
add
(
2
);
arbre
.
add
(
8
);
List
<
Integer
>
list
=
Arrays
.
asList
(
2
,
8
);
assertTrue
(
arbre
.
removeAll
(
list
));
assertFalse
(
arbre
.
contains
(
2
));
assertFalse
(
arbre
.
contains
(
8
));
assertTrue
(
arbre
.
contains
(
5
));
}
@Test
void
testRetainAll
()
{
arbre
.
add
(
5
);
arbre
.
add
(
2
);
arbre
.
add
(
8
);
List
<
Integer
>
list
=
Arrays
.
asList
(
5
);
assertTrue
(
arbre
.
retainAll
(
list
));
assertTrue
(
arbre
.
contains
(
5
));
assertFalse
(
arbre
.
contains
(
2
));
assertFalse
(
arbre
.
contains
(
8
));
assertEquals
(
1
,
arbre
.
size
());
}
@Test
void
testContainsAvecTypeIncorrect
()
{
arbre
.
add
(
5
);
arbre
.
add
(
3
);
// Un type incompatible doit entraîner catch(ClassCastException) → false
assertFalse
(
arbre
.
contains
(
"texte"
));
// String ≠ Integer
}
@Test
void
testRemoveNull
()
{
arbre
.
add
(
5
);
assertFalse
(
arbre
.
remove
(
null
));
// ne doit jamais lancer d’exception
assertEquals
(
1
,
arbre
.
size
());
assertTrue
(
arbre
.
contains
(
5
));
}
@Test
void
testRemoveRacineNull
()
{
// racine = null
assertTrue
(
arbre
.
isEmpty
());
assertFalse
(
arbre
.
remove
(
10
));
// retirer un élément dans un arbre vide => false
assertTrue
(
arbre
.
isEmpty
());
}
@Test
void
testRemoveSansException
()
{
arbre
.
add
(
10
);
arbre
.
add
(
5
);
arbre
.
add
(
15
);
// Cas normaux
assertDoesNotThrow
(()
->
arbre
.
remove
(
5
));
assertDoesNotThrow
(()
->
arbre
.
remove
(
15
));
assertDoesNotThrow
(()
->
arbre
.
remove
(
10
));
// Retrait sur arbre vide
assertDoesNotThrow
(()
->
arbre
.
remove
(
999
));
// Retrait d’un null
assertDoesNotThrow
(()
->
arbre
.
remove
(
null
));
}
@Test
void
testRemoveAvecSuccesseurProfond
()
{
arbre
.
add
(
10
);
arbre
.
add
(
5
);
arbre
.
add
(
20
);
arbre
.
add
(
15
);
arbre
.
add
(
13
);
// successeur profond
// Suppression du nœud ayant deux enfants
assertTrue
(
arbre
.
remove
(
10
));
// Le successeur (13) doit avoir remplacé la racine
Iterator
<
Integer
>
it
=
arbre
.
iterator
();
assertEquals
(
5
,
it
.
next
());
assertEquals
(
13
,
it
.
next
());
// remplace 10
assertEquals
(
15
,
it
.
next
());
assertEquals
(
20
,
it
.
next
());
assertFalse
(
it
.
hasNext
());
}
@Test
void
testRemoveRacineAvecUnEnfant
()
{
arbre
.
add
(
10
);
arbre
.
add
(
20
);
// enfant droit unique
assertTrue
(
arbre
.
remove
(
10
));
// La racine doit être remplacée par l’enfant (20)
assertEquals
(
20
,
arbre
.
iterator
().
next
());
assertEquals
(
1
,
arbre
.
size
());
}
@Test
void
testIsEmpty
()
{
ArbreBinaireRecherche
<
Integer
>
a
=
new
ArbreBinaireRecherche
<>();
// L'arbre vide
assertTrue
(
a
.
isEmpty
());
// Après insertion
a
.
add
(
1
);
assertFalse
(
a
.
isEmpty
());
// Après suppression
a
.
remove
(
1
);
assertTrue
(
a
.
isEmpty
());
}
@Test
void
testToArrayComplet
()
{
arbre
.
add
(
4
);
arbre
.
add
(
1
);
arbre
.
add
(
3
);
arbre
.
add
(
2
);
Object
[]
arr
=
arbre
.
toArray
();
assertEquals
(
4
,
arr
.
length
);
assertArrayEquals
(
new
Object
[]
{
1
,
2
,
3
,
4
},
arr
);
// Vérification cohérence avec iterator()
int
index
=
0
;
for
(
int
value
:
arbre
)
{
assertEquals
(
value
,
arr
[
index
++]);
}
}
@Test
void
testContainsAll
()
{
arbre
.
add
(
5
);
arbre
.
add
(
2
);
arbre
.
add
(
8
);
// Tous présents
assertTrue
(
arbre
.
containsAll
(
Arrays
.
asList
(
2
,
5
)));
// Un absent
assertFalse
(
arbre
.
containsAll
(
Arrays
.
asList
(
2
,
10
)));
// Collection vide → doit être true
assertTrue
(
arbre
.
containsAll
(
Arrays
.
asList
()));
// Mauvais type → contains(o) doit retourner false
assertFalse
(
arbre
.
containsAll
(
Arrays
.
asList
(
"test"
)));
}
@Test
void
testToArrayGenericRetourNull
()
{
arbre
.
add
(
5
);
arbre
.
add
(
2
);
arbre
.
add
(
9
);
Integer
[]
cible
=
new
Integer
[
3
];
// L’implémentation actuelle doit renvoyer null
assertNull
(
arbre
.
toArray
(
cible
));
}
}
src/test/java/collection/RedBlackTree.java
0 → 100644
Voir le fichier @
48bfbd49
package
collection
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertArrayEquals
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertEquals
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertFalse
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertTrue
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
java.util.List
;
import
org.junit.jupiter.api.BeforeEach
;
import
org.junit.jupiter.api.Test
;
class
RedBlackTreeTest
{
private
RedBlackTree
<
Integer
>
tree
;
@BeforeEach
void
setUp
()
{
tree
=
new
RedBlackTree
<>();
}
@Test
void
testAddAndContains
()
{
assertTrue
(
tree
.
add
(
10
));
assertTrue
(
tree
.
contains
(
10
));
assertFalse
(
tree
.
add
(
10
));
// pas de doublons
}
@Test
void
testRemove
()
{
tree
.
add
(
20
);
tree
.
add
(
10
);
tree
.
add
(
30
);
assertTrue
(
tree
.
remove
(
20
));
assertFalse
(
tree
.
contains
(
20
));
assertFalse
(
tree
.
remove
(
40
));
// élément inexistant
}
@Test
void
testSizeAndIsEmpty
()
{
assertTrue
(
tree
.
isEmpty
());
tree
.
add
(
1
);
tree
.
add
(
2
);
tree
.
add
(
3
);
assertEquals
(
3
,
tree
.
size
());
assertFalse
(
tree
.
isEmpty
());
}
@Test
void
testClear
()
{
tree
.
add
(
5
);
tree
.
add
(
15
);
tree
.
clear
();
assertEquals
(
0
,
tree
.
size
());
assertTrue
(
tree
.
isEmpty
());
}
@Test
void
testIterator
()
{
tree
.
add
(
3
);
tree
.
add
(
1
);
tree
.
add
(
4
);
tree
.
add
(
2
);
Iterator
<
Integer
>
it
=
tree
.
iterator
();
int
[]
expectedOrder
=
{
1
,
2
,
3
,
4
};
int
i
=
0
;
while
(
it
.
hasNext
())
{
assertEquals
(
expectedOrder
[
i
++],
it
.
next
());
}
assertEquals
(
expectedOrder
.
length
,
i
);
}
@Test
void
testToArray
()
{
tree
.
add
(
7
);
tree
.
add
(
3
);
tree
.
add
(
9
);
Object
[]
arr
=
tree
.
toArray
();
Arrays
.
sort
(
arr
);
// pour comparaison
assertArrayEquals
(
new
Object
[]
{
3
,
7
,
9
},
arr
);
}
@Test
void
testToArrayWithType
()
{
tree
.
add
(
5
);
tree
.
add
(
1
);
tree
.
add
(
8
);
Integer
[]
arr
=
new
Integer
[
3
];
arr
=
tree
.
toArray
(
arr
);
Arrays
.
sort
(
arr
);
assertArrayEquals
(
new
Integer
[]
{
1
,
5
,
8
},
arr
);
}
@Test
void
testAddAllAndContainsAll
()
{
List
<
Integer
>
list
=
Arrays
.
asList
(
10
,
20
,
30
);
assertTrue
(
tree
.
addAll
(
list
));
assertTrue
(
tree
.
containsAll
(
list
));
}
@Test
void
testRemoveAll
()
{
tree
.
add
(
1
);
tree
.
add
(
2
);
tree
.
add
(
3
);
List
<
Integer
>
toRemove
=
Arrays
.
asList
(
2
,
3
,
4
);
assertTrue
(
tree
.
removeAll
(
toRemove
));
assertFalse
(
tree
.
contains
(
2
));
assertFalse
(
tree
.
contains
(
3
));
assertTrue
(
tree
.
contains
(
1
));
}
@Test
void
testRetainAll
()
{
tree
.
add
(
1
);
tree
.
add
(
2
);
tree
.
add
(
3
);
List
<
Integer
>
toRetain
=
Arrays
.
asList
(
2
,
3
,
4
);
assertTrue
(
tree
.
retainAll
(
toRetain
));
assertFalse
(
tree
.
contains
(
1
));
assertTrue
(
tree
.
contains
(
2
));
assertTrue
(
tree
.
contains
(
3
));
}
}