Commits (2)
n,1000,2000,5000,10000,20000,50000 n,1000,2000,5000,10000,20000,50000
ASCENDANT,1231700,00,4418640,00,30034160,00,116455020,00,474819140,00,3056061360,00 ASCENDANT,2741266,60,4242239,60,25764592,60,103848038,60,427439882,20,2674167635,60
ALEATOIRE,149580,00,167500,00,356340,00,830320,00,1814660,00,5609920,00 ALEATOIRE,296387,40,450203,40,656077,20,1670061,80,3761467,60,11957840,20
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
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,00 ASCENDANT,429293,00,541214,60,1492209,80,1450807,80,1846437,80,4429069,40
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
n,1000,2000,5000,10000,20000,50000 n,1000,2000,5000,10000,20000,50000
ASCENDANT,136940,00,128920,00,320120,00,733100,00,1475920,00,4872060,00 ASCENDANT,353458,80,290777,00,621226,20,1336956,20,2635875,60,9406446,40
ALEATOIRE,51780,00,101540,00,308340,00,616120,00,1244160,00,3500360,00 ALEATOIRE,63701,80,132267,60,378176,00,815282,80,1745943,60,5169691,20
...@@ -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>
...@@ -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();
}
} }
...@@ -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 arnSearch = 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[] benchmarkARN(List<Integer> keys, int n) { private static long[] benchmarkAbr(List<Integer> keys, int n) {
Collection<Integer> tree = new RedBlackTree<>(); Collection<Integer> tree = new ArbreBinaireRecherche<>();
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 };
}
} }
Ce diff est replié.
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));
}
}
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));
}
}