Commits (6)
......@@ -4,4 +4,5 @@ target/
*.classpath
*.project
classes/
test-classes/
\ No newline at end of file
test-classes/
/bin/
n,1000,2000,5000,10000,20000,50000
ASCENDANT,1231700,00,4418640,00,30034160,00,116455020,00,474819140,00,3056061360,00
ALEATOIRE,149580,00,167500,00,356340,00,830320,00,1814660,00,5609920,00
n,1000,2000,5000,10000,20000,50000
ASCENDANT,2658220,00,9699160,00,60452520,00,233926280,00,907753720,00,5800536280,00
ALEATOIRE,128340,00,122680,00,310240,00,577920,00,1311820,00,3409080,00
n,1000,2000,5000,10000,20000,50000
ASCENDANT,221140,00,242880,00,405760,00,720540,00,761520,00,1803680,00
ALEATOIRE,153900,00,219500,00,457300,00,938200,00,2106160,00,6222500,00
n,1000,2000,5000,10000,20000,50000
ASCENDANT,136940,00,128920,00,320120,00,733100,00,1475920,00,4872060,00
ALEATOIRE,51780,00,101540,00,308340,00,616120,00,1244160,00,3500360,00
structure,scenario,n,phase,avg_millis
ABR,random,1000,insert,260220,00
ABR,random,1000,search,191900,00
ABR,random,2000,insert,206640,00
ABR,random,2000,search,221760,00
ABR,random,5000,insert,435200,00
ABR,random,5000,search,438360,00
ABR,random,10000,insert,855380,00
ABR,random,10000,search,705300,00
ABR,random,20000,insert,2177680,00
ABR,random,20000,search,1845920,00
ABR,random,50000,insert,6423600,00
ABR,random,50000,search,5389400,00
ABR,ascending,1000,insert,718120,00
ABR,ascending,1000,search,2531360,00
ABR,ascending,2000,insert,4253440,00
ABR,ascending,2000,search,10143660,00
ABR,ascending,5000,insert,28879760,00
ABR,ascending,5000,search,63836740,00
ABR,ascending,10000,insert,115510000,00
ABR,ascending,10000,search,266706780,00
ABR,ascending,20000,insert,475341800,00
ABR,ascending,20000,search,1121616340,00
ABR,ascending,50000,insert,3014206600,00
ABR,ascending,50000,search,6716530900,00
ARN,random,1000,insert,221560,00
ARN,random,1000,search,139960,00
ARN,random,2000,insert,224680,00
ARN,random,2000,search,134720,00
ARN,random,5000,insert,432000,00
ARN,random,5000,search,305080,00
ARN,random,10000,insert,989980,00
ARN,random,10000,search,896760,00
ARN,random,20000,insert,2126220,00
ARN,random,20000,search,1506000,00
ARN,random,50000,insert,7219200,00
ARN,random,50000,search,3469420,00
ARN,ascending,1000,insert,33160,00
ARN,ascending,1000,search,47440,00
ARN,ascending,2000,insert,76180,00
ARN,ascending,2000,search,135580,00
ARN,ascending,5000,insert,216960,00
ARN,ascending,5000,search,374500,00
ARN,ascending,10000,insert,436280,00
ARN,ascending,10000,search,815480,00
ARN,ascending,20000,insert,901520,00
ARN,ascending,20000,search,1773640,00
ARN,ascending,50000,insert,2840800,00
ARN,ascending,50000,search,4844200,00
......@@ -6,148 +6,102 @@
<groupId>edu.Univ-lehavre.MACIA</groupId>
<artifactId>ArbreRougeNoir</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ArbreRougeNoir</name>
<!-- FIXME change it to the project's website -->
<url>http://maven.apache.org</url>
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>14</maven.compiler.source>
<maven.compiler.target>14</maven.compiler.target>
<maven.compiler.release>17</maven.compiler.release>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>6.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>6.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>6.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.6.0</version>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<configLocation>
src/properties/stylePerso.xml
</configLocation>
</configuration>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>12.1.1</version>
</dependency>
</dependencies>
<archive>
<manifest>
<mainClass>collection.Benchmark</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.5.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.21.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<mainClass>collection.Benchmark</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>4.0.0-M16</version>
</plugin>
<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>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.6.0</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>12.1.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.11.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.11.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.10.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>3.5.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>3.5.1</version>
</plugin>
<plugin>
<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>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.6.0</version>
</plugin>
</plugins>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>3.6.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>3.5.4</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.6.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.12.0</version>
</plugin>
</plugins>
</reporting>
</project>
......@@ -10,7 +10,7 @@ import java.util.Stack;
/**
* Arbre binaire de recherche simple. Implémente l’interface Collection.
*/
public class BinarySearchTree<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 */
private class Noeud {
......
......@@ -9,71 +9,130 @@ import java.util.Collections;
import java.util.List;
import java.util.Random;
class Benchmark {
private static final Random RNG = new Random(12345);
public static void main(final String[] args) throws Exception {
final int[] ns = {1000, 2000, 5000, 10000, 20000, 50000}; // adapte
final int reps = 5; // répétitions pour moyenne
String outFile = "benchmark_results.csv";
try (PrintWriter pw = new PrintWriter(new FileWriter(outFile))) {
pw.println("structure,scenario,n,phase,avg_millis");
for (String structure : Arrays.asList("ABR", "ARN")) {
for (String scenario : Arrays.asList("random", "ascending")) {
for (int n : ns) {
long insertSum = 0;
long searchSum = 0;
for (int r = 0; r < reps; r++) {
List<Integer> keys = new ArrayList<>();
for (int i = 0; i < n; i++) {
keys.add(i);
}
if (scenario.equals("random")) {
Collections.shuffle(keys, new Random(RNG.nextLong()));
}
// choose structure
Collection<Integer> tree = structure.equals("ARN")
? new RedBlackTree<>() : new BinarySearchTree<>();
long t0 = System.nanoTime();
for (Integer k : keys) {
tree.add(k);
}
long t1 = System.nanoTime();
long insertMs = (t1 - t0);
insertSum += insertMs;
// search phase: 0 .. 2n-1
long t2 = System.nanoTime();
for (int x = 0; x < 2 * n; x++) {
tree.contains(x);
}
long t3 = System.nanoTime();
long searchMs = (t3 - t2);
searchSum += searchMs;
}
pw.printf("%s,%s,%d,insert,%.2f%n", structure, scenario, n,
insertSum / (double) reps);
pw.printf("%s,%s,%d,search,%.2f%n", structure, scenario, n,
searchSum / (double) reps);
pw.flush();
System.out.printf("Done %s %s n=%d%n", structure, scenario, n);
}
}
}
public class Benchmark {
private static final Random RNG = new Random(12345);
public static void main(final String[] args) throws Exception {
final int[] N_LIST = { 1000, 2000, 5000, 10000, 20000, 50000 };
final int REP = 5;
// --- Create the 4 CSV writers ---
PrintWriter abrInsert = new PrintWriter(new FileWriter("ABR_insert.csv"));
PrintWriter abrSearch = new PrintWriter(new FileWriter("ABR_search.csv"));
PrintWriter arnInsert = new PrintWriter(new FileWriter("ARN_insert.csv"));
PrintWriter arnSearch = new PrintWriter(new FileWriter("ARN_search.csv"));
// Header line : n,1000,2000,...
writeHeader(abrInsert, N_LIST);
writeHeader(abrSearch, N_LIST);
writeHeader(arnInsert, N_LIST);
writeHeader(arnSearch, N_LIST);
// Scenarios
List<String> scenarios = Arrays.asList("ASCENDANT", "ALEATOIRE");
// Process each structure
for (String structure : Arrays.asList("ABR", "ARN")) {
for (String scenario : scenarios) {
// Buffers for one line of insert & search results
List<Double> insertLine = new ArrayList<>();
List<Double> searchLine = new ArrayList<>();
for (int n : N_LIST) {
long insertSum = 0;
long searchSum = 0;
for (int r = 0; r < REP; r++) {
List<Integer> keys = new ArrayList<>();
for (int i = 0; i < n; i++)
keys.add(i);
if (scenario.equals("ALEATOIRE")) {
Collections.shuffle(keys, new Random(RNG.nextLong()));
}
long[] result = structure.equals("ABR") ? benchmarkABR(keys, n) : benchmarkARN(keys, n);
insertSum += result[0];
searchSum += result[1];
}
insertLine.add(insertSum / (double) REP);
searchLine.add(searchSum / (double) REP);
System.out.printf("Done %s %s n=%d\n", structure, scenario, n);
}
// 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();
abrSearch.close();
arnInsert.close();
arnSearch.close();
System.out.println("4 CSV créés au format tableau.");
}
// -------------------------------------------------------
// 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);
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<>();
return runBenchmark(tree, keys, n);
}
private static long[] benchmarkARN(List<Integer> keys, int n) {
Collection<Integer> tree = new RedBlackTree<>();
return runBenchmark(tree, keys, n);
}
private static long[] runBenchmark(Collection<Integer> tree, List<Integer> keys, int n) {
long t0 = System.nanoTime();
for (Integer k : keys)
tree.add(k);
long t1 = System.nanoTime();
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 };
}
System.out.println("Wrote results to " + outFile);
}
}
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="${org.checkstyle.google.severity}" default="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Exclure module-info.java -->
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
<module name="SuppressWarningsFilter"/>
<!-- Suppressions -->
<module name="SuppressionFilter">
<property name="file" value="${org.checkstyle.google.suppressionfilter.config}"
default="checkstyle-suppressions.xml" />
<property name="optional" value="true"/>
</module>
<module name="SuppressWithNearbyTextFilter">
<property name="nearbyTextPattern"
value="CHECKSTYLE.SUPPRESS\: (\w+) for ([+-]\d+) lines"/>
<property name="checkPattern" value="$1"/>
<property name="lineRange" value="$2"/>
</module>
<!-- Tabs interdits -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<!-- Longueur max des lignes -->
<module name="LineLength">
<property name="fileExtensions" value="java"/>
<property name="max" value="1000"/>
<property name="ignorePattern"
value="^package.*|^import.*|href\s*=\s*&quot;[^&quot;]*&quot;|http://|https://|ftp://"/>
</module>
<!-- Longueur maximale du fichier = 1000 lignes -->
<module name="FileLength">
<property name="max" value="1000"/>
</module>
<module name="SuppressWithPlainTextCommentFilter">
<property name="checkFormat" value="LineLength"/>
<property name="offCommentFormat" value='^.*"""\s*$'/>
<property name="onCommentFormat" value='^\s*"""\s*(?:[,;]|.+)$'/>
</module>
<module name="TreeWalker">
<!-- Règles personnalisées ajoutées -->
<module name="MethodLength">
<property name="max" value="15"/>
</module>
<module name="ParameterNumber">
<property name="max" value="2"/>
</module>
<module name="MagicNumber">
<property name="ignoreNumbers" value="-1,0,1"/>
<property name="ignoreHashCodeMethod" value="true"/>
</module>
<module name="NestedIfDepth">
<property name="max" value="0"/>
</module>
<module name="VariableDeclarationUsageDistance">
<property name="maxDistance" value="5"/>
</module>
<!-- Début de toutes les règles Google Checkstyle… (inchangées) -->
<module name="OuterTypeFilename"/>
<module name="MatchXpath">
<property name="id" value="singleLineCommentStartWithSpace"/>
<property name="query"
value="//SINGLE_LINE_COMMENT[./COMMENT_CONTENT[not(starts-with(@text, ' '))
and not(starts-with(@text, '/'))
and not(@text = '\n') and not(ends-with(@text, '//\n'))]]"/>
<message key="matchxpath.match" value="''//'' must be followed by a whitespace."/>
</module>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL, TEXT_BLOCK_CONTENT"/>
<property name="format"
value="\\u00(09|0(a|A)|0(b|B)|(0|1)(c|C)|(0|1)(d|D)|1(d|D)|1(e|E)|1(f|F)|22|27|5(C|c))|\\u1680|\\u3000|\\u20(00|0(a|A)|28|29|(2|5)(f|F))|\\(0(10|11|12|14|15|40|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap">
<property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT"/>
</module>
<module name="NeedBraces">
<property name="tokens"
value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/>
</module>
<module name="LeftCurly">
<property name="id" value="LeftCurlyEol"/>
<property name="tokens"
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LAMBDA, LITERAL_CATCH,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
OBJBLOCK, STATIC_INIT, RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="LeftCurly">
<property name="id" value="LeftCurlyNl"/>
<property name="option" value="nl"/>
<property name="tokens"
value="LITERAL_CASE, LITERAL_DEFAULT"/>
</module>
<module name="SuppressionXpathSingleFilter">
<!-- LITERAL_CASE, LITERAL_DEFAULT are reused in SWITCH_RULE -->
<property name="id" value="LeftCurlyNl"/>
<property name="query" value="//SWITCH_RULE/SLIST"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
<module name="SuppressionXpathSingleFilter">
<property name="id" value="RightCurlySame"/>
<property name="query" value="//RCURLY[parent::SLIST[parent::LITERAL_CATCH
and not(parent::LITERAL_CATCH/following-sibling::*)]]"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF, LITERAL_SWITCH, LITERAL_CASE, LITERAL_FINALLY,
LITERAL_CATCH"/>
</module>
<module name="SuppressionXpathSingleFilter">
<!-- suppression is required till https://github.com/checkstyle/checkstyle/issues/7541 -->
<property name="id" value="RightCurlyAlone"/>
<property name="query" value="//RCURLY[parent::SLIST[count(./*)=1
and not(parent::LITERAL_CATCH)]
or (preceding-sibling::*[last()][self::LCURLY]
and not(parent::SLIST/parent::LITERAL_CATCH))
or (parent::SLIST/parent::LITERAL_CATCH
and parent::SLIST/parent::LITERAL_CATCH/following-sibling::*)]"/>
</module>
<module name="WhitespaceAfter">
<property name="tokens"
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE, LITERAL_RETURN,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, LITERAL_FINALLY, DO_WHILE, ELLIPSIS,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_CATCH, LAMBDA,
LITERAL_YIELD, LITERAL_CASE, LITERAL_WHEN, ANNOTATIONS"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyLambdas" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<property name="allowEmptySwitchBlockStatements" value="true"/>
<property name="ignoreEnhancedForColon" value="false"/>
<property name="tokens"
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT,
TYPE_EXTENSION_AND, LITERAL_WHEN"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks
may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="SuppressionXpathSingleFilter">
<property name="checks" value="WhitespaceAround"/>
<property name="query" value="//*[self::LITERAL_IF or self::LITERAL_ELSE or
self::STATIC_INIT]/SLIST[count(./*)=1]
| //*[self::STATIC_INIT or self::LITERAL_TRY or self::LITERAL_IF]
//*[self::RCURLY][parent::SLIST[count(./*)=1]]
| //SLIST[count(./*)=1][parent::LITERAL_TRY and
not(following-sibling::*)]
| //SLIST[count(./*)=1][parent::LITERAL_CATCH and
not(parent::LITERAL_CATCH/following-sibling::*)]"/>
</module>
<module name="RegexpSinglelineJava">
<property name="format" value="\{[ ]+\}"/>
<property name="message" value="Empty blocks should have no spaces. Empty blocks
may only be represented as '{}' when not part of a
multi-block statement (4.1.3)"/>
</module>
<module name="OneStatementPerLine"/>
<module name="VariableDeclarationUsageDistance">
<property name="maxDistance" value="5"/>
</module>
<module name="ArrayTypeStyle"/>
<module name="JavadocLeadingAsteriskAlign"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="tokens"
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/>
<property name="allowNoEmptyLineBetweenFields" value="true"/>
<property name="allowMultipleEmptyLines" value="false"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/259 -->
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/258 -->
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<property name="format" value="^[A-Z][a-zA-Z0-9]*(?:[0-9](?:_[0-9]+)*)?$"/>
<property name="tokens" value="CLASS_DEF"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<property name="tokens" value="INTERFACE_DEF, ENUM_DEF,
ANNOTATION_DEF, RECORD_DEF"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format"
value="^(?![a-z]$)(?![a-z][A-Z])[a-z][a-zA-Z0-9]*(?:_[0-9]+)*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="PatternVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordComponentName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Record component name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Record type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="2"/>
<property name="braceAdjustment" value="2"/>
<property name="caseIndent" value="2"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="2"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="0"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF,
RECORD_COMPONENT_DEF"/>
</module>
<module name="NoWhitespaceBeforeCaseDefaultColon"/>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="ConstructorsDeclarationGrouping"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
<property name="tokens" value="IMPORT, STATIC_IMPORT, PACKAGE_DEF"/>
</module>
<module name="MethodParamPad">
<property name="tokens"
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF, CTOR_CALL,
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF, RECORD_DEF, RECORD_PATTERN_DEF"/>
</module>
<module name="NoWhitespaceBefore">
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
LABELED_STAT, METHOD_REF, ELLIPSIS"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="SuppressionXpathSingleFilter">
<property name="checks" value="NoWhitespaceBefore"/>
<property name="query"
value="//ELLIPSIS[preceding-sibling::TYPE/ANNOTATIONS[ANNOTATION[LPAREN]
or not(following-sibling::*)]]"/>
</module>
<module name="ParenPad">
<property name="tokens"
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA,
RECORD_DEF, RECORD_PATTERN_DEF"/>
</module>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF,
TYPE_EXTENSION_AND "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF,
RECORD_DEF, COMPACT_CTOR_DEF, PACKAGE_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="InvalidJavadocPosition"/>
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph">
<property name="allowNewlineParagraph" value="false"/>
</module>
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="accessModifiers" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="MissingJavadocMethod">
<property name="scope" value="protected"/>
<property name="allowMissingPropertyJavadoc" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF,
COMPACT_CTOR_DEF"/>
</module>
<module name="SuppressionXpathSingleFilter">
<property name="checks" value="MissingJavadocMethod"/>
<property name="query" value="//*[self::METHOD_DEF or self::CTOR_DEF
or self::ANNOTATION_FIELD_DEF or self::COMPACT_CTOR_DEF]
[ancestor::*[self::INTERFACE_DEF or self::CLASS_DEF
or self::RECORD_DEF or self::ENUM_DEF]
[not(./MODIFIERS/LITERAL_PUBLIC)]]"/>
</module>
<module name="MissingJavadocType">
<property name="scope" value="protected"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
RECORD_DEF, ANNOTATION_DEF"/>
<property name="excludeScope" value="nothing"/>
</module>
<module name="MethodName">
<property name="format"
value="^(?![a-z]$)(?![a-z][A-Z])[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*(?:_[0-9]+)*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SuppressionXpathSingleFilter">
<property name="checks" value="MethodName"/>
<property name="query" value="//METHOD_DEF[
./MODIFIERS/ANNOTATION//IDENT[contains(@text, 'Test')]
]/IDENT"/>
<property name="message" value="'[a-z][a-z0-9][a-zA-Z0-9]*(?:_[a-z][a-z0-9][a-zA-Z0-9]*)*'"/>
</module>
<module name="SingleLineJavadoc"/>
<module name="TodoComment">
<property name="format" value="^[ \t]*(?!TODO:)(?i:TODO)\b:?"/>
<message key="todo.match"
value="''TODO:'' must be written in all caps and followed by a colon."/>
</module>
<module name="EmptyCatchBlock">
<property name="commentFormat" value="\w+"/>
</module>
<module name="CommentsIndentation">
<property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
</module>
<!-- https://checkstyle.org/filters/suppressionxpathfilter.html -->
<module name="SuppressionXpathFilter">
<property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}"
default="checkstyle-xpath-suppressions.xml" />
<property name="optional" value="true"/>
</module>
<module name="SuppressWarningsHolder" />
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)" />
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)" />
<property name="checkFormat" value="$1" />
</module>
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="CHECKSTYLE.SUPPRESS\: ([\w\|]+)"/>
<!-- $1 refers to the first match group in the regex defined in commentFormat -->
<property name="checkFormat" value="$1"/>
<!-- The check is suppressed in the next line of code after the comment -->
<property name="influenceFormat" value="1"/>
</module>
</module>
</module>
package collection;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import org.junit.jupiter.api.*;
public class RedBlackTreeTest {
@Test
void addContainsRemove() {
RedBlackTree<Integer> t = new RedBlackTree<>();
assertTrue(t.add(5));
assertTrue(t.contains(5));
assertFalse(t.add(5)); // no duplicates
assertTrue(t.add(3));
assertTrue(t.add(7));
assertEquals(3, t.size());
assertTrue(t.remove(3));
assertFalse(t.contains(3));
assertEquals(2, t.size());
}
@Test
void inOrderTraversalIsSorted() {
RedBlackTree<Integer> t = new RedBlackTree<>();
List<Integer> vals = Arrays.asList(5, 2, 8, 1, 3, 7, 9);
Collections.shuffle(vals, new Random(42));
t.addAll(vals);
int prev = Integer.MIN_VALUE;
for (Integer v : t) {
assertTrue(v > prev);
prev = v;
}
}
@Test
void largeRandomInsertions() {
RedBlackTree<Integer> t = new RedBlackTree<>();
int n = 10000;
Random rnd = new Random(123);
List<Integer> arr = new ArrayList<>();
for (int i = 0; i < n; i++)
arr.add(i);
Collections.shuffle(arr, rnd);
for (int x : arr)
t.add(x);
assertEquals(n, t.size());
for (int i = 0; i < n; i++)
assertTrue(t.contains(i));
}
}