While reviewing the Union Find algorithms that Dr. Robert Sedgewick and Dr. Kevin Wayne instructed via their book and website:
https://algs4.cs.princeton.edu/10fundamentals/
I created a Maven project (which I imported into IntelliJ IDEA) with the following pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.princeton.cs.algs4</groupId>
<artifactId>algs4</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>10</source>
<target>10</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<show>private</show> <!--javadoc shows all classes and members-->
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<stylesheetfile>${basedir}/src/main/javadoc/stylesheet.css</stylesheetfile>
<show>public</show>
</configuration>
</plugin>
</plugins>
</reporting>
</project>
Project File Structure:
algs4
|
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── edu
│ │ └── princeton
│ │ └── cs
│ │ └── algs4
│ │ ├── QuickFindUF.java
│ │ ├── QuickUnionUF.java
│ │ ├── StdIn.java
│ │ ├── StdOut.java
│ │ └── WeightedQuickUnionUF.java
│ └── resources
│ ├── largeUF.txt
│ ├── mediumUF.txt
│ └── tinyUF.txt
└── test
└── java
QuickFindUF.java:
public class QuickFindUF {
private int[] id; // id[i] = component identifier of i
private int count; // number of components
public QuickFindUF(int n) {
count = n;
id = new int[n];
for (int i = 0; i < n; i++)
id[i] = i;
}
public int count() {
return count;
}
public int find(int p) {
validate(p);
return id[p];
}
// validate that p is a valid index
private void validate(int p) {
int n = id.length;
if (p < 0 || p >= n) {
throw new IllegalArgumentException("index " + p + " is not between 0 and " + (n-1));
}
}
public void union(int p, int q) {
validate(p);
validate(q);
int pID = id[p]; // needed for correctness
int qID = id[q]; // to reduce the number of array accesses
// p and q are already in the same component
if (pID == qID) return;
for (int i = 0; i < id.length; i++)
if (id[i] == pID) id[i] = qID;
count--;
}
public static void main(String[] args) {
int n = StdIn.readInt();
QuickFindUF uf = new QuickFindUF(n);
while (!StdIn.isEmpty()) {
int p = StdIn.readInt();
int q = StdIn.readInt();
if (uf.find(p) == uf.find(q)) continue;
uf.union(p, q);
StdOut.println(p + " " + q);
}
StdOut.println(uf.count() + " components");
}
}
QuickUnionUF.java:
public class QuickUnionUF {
private int[] parent; // parent[i] = parent of i
private int count; // number of components
public QuickUnionUF(int n) {
parent = new int[n];
count = n;
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
public int count() {
return count;
}
public int find(int p) {
validate(p);
while (p != parent[p])
p = parent[p];
return p;
}
// validate that p is a valid index
private void validate(int p) {
int n = parent.length;
if (p < 0 || p >= n) {
throw new IllegalArgumentException("index " + p + " is not between 0 and " + (n-1));
}
}
public void union(int p, int q) {
int rootP = find(p);
int rootQ = find(q);
if (rootP == rootQ) return;
parent[rootP] = rootQ;
count--;
}
public static void main(String[] args) {
int n = StdIn.readInt();
QuickUnionUF uf = new QuickUnionUF(n);
while (!StdIn.isEmpty()) {
int p = StdIn.readInt();
int q = StdIn.readInt();
if (uf.find(p) == uf.find(q)) continue;
uf.union(p, q);
StdOut.println(p + " " + q);
}
StdOut.println(uf.count() + " components");
}
}
WeightedQuickUnionUF.java:
public class WeightedQuickUnionUF {
private int[] parent; // parent[i] = parent of i
private int[] size; // size[i] = number of elements in subtree rooted at i
private int count; // number of components
public WeightedQuickUnionUF(int n) {
count = n;
parent = new int[n];
size = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
size[i] = 1;
}
}
public int count() {
return count;
}
public int find(int p) {
validate(p);
while (p != parent[p])
p = parent[p];
return p;
}
// validate that p is a valid index
private void validate(int p) {
int n = parent.length;
if (p < 0 || p >= n) {
throw new IllegalArgumentException("index " + p + " is not between 0 and " + (n-1));
}
}
public void union(int p, int q) {
int rootP = find(p);
int rootQ = find(q);
if (rootP == rootQ) return;
// make smaller root point to larger one
if (size[rootP] < size[rootQ]) {
parent[rootP] = rootQ;
size[rootQ] += size[rootP];
}
else {
parent[rootQ] = rootP;
size[rootP] += size[rootQ];
}
count--;
}
public static void main(String[] args) {
int n = StdIn.readInt();
WeightedQuickUnionUF uf = new WeightedQuickUnionUF(n);
while (!StdIn.isEmpty()) {
int p = StdIn.readInt();
int q = StdIn.readInt();
if (uf.find(p) == uf.find(q)) continue;
uf.union(p, q);
StdOut.println(p + " " + q);
}
StdOut.println(uf.count() + " components");
}
}
Implementation for StdIn can be found at:
https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/StdIn.java.html
Implementation for StdOut can be found at:
https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/StdOut.java.html
Data files can be found at:
- https://algs4.cs.princeton.edu/15uf/tinyUF.txt
- https://algs4.cs.princeton.edu/15uf/mediumUF.txt
- https://algs4.cs.princeton.edu/15uf/largeUF.txt
When I conduct a mvn clean install
or mvn test
It created the appropriate target directory, as follows:
target
├── classes
├── edu
│ └── princeton
│ └── cs
│ └── algs4
│ ├── QuickFindUF.class
│ ├── QuickUnionUF.class
│ ├── StdIn.class
│ ├── StdOut.class
│ └── WeightedQuickUnionUF.class
├── largeUF.txt
├── mediumUF.txt
└── tinyUF.txt
Since, I created and imported this into IntelliJ as a maven project, I couldn't figure out how to setup a "Run as a standalone Java application" (with the txt file as args to the main() method.
So, what I did was issue a "mvn test"
Nothing happened... Is there a way to do this via Terminal or IntelliJ IDEA?
For running in terminal use java edu.princeton.cs.algs4.QuickFindUF < tinyUF.txt
or cat tinyUF.txt | java edu.princeton.cs.algs4.QuickFindUF
.
For running in IntelliJ IDEA use the Redirect input from option. Note that the path is relative to the working directory.
I can't see the Application configuration that Crazy Coder referred
You can create a new Application or Jar Application configuration in IntelliJ IDEA by clicking the + button. See help for details.
When I tried that, it couldn't find the jar file located inside the target directory.
JAR file will be available in the target directory after you run mvn package
goal. You can do it from the command line Maven or from the IDE. It's also possible to set up a trigger to build the jar before run/debug or add this Maven goal to the Before Launch steps of the run/debug configuration.
See also my other answer to the similar question. It suggests another way to do it without redirect option using the wrapper class.