Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,21 @@
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<!-- Library sources only: every public/protected member needs complete Javadoc. -->
<id>default-compile</id>
<configuration>
<compilerArgs>
<arg>-Xdoclint:all/protected</arg>
<arg>-Werror</arg>
Comment on lines +159 to +160

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

-Xdoclint is a Javadoc-tool option, not a javac option, so configuring it under the compiler plugin cannot reliably enforce API documentation and may make compilation fail with an unsupported flag. Move doclint and warning-as-error enforcement to the Maven Javadoc plugin, configured for the protected API, and keep only compiler-supported arguments under the compiler plugin.

TIP React 👍 if this review is right, or reply with what's wrong and how it could be better to help improve the reviewer.

</compilerArgs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>${maven-enforcer-plugin.version}</version>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
package io.github.diegourban.algorithms.datastructure;

/**
* A named value stored by the data structures in this package. Two elements are equal when their names are equal.
*/
public class Element {

private final String name;

/**
* Creates an element with the given name.
*
* @param name the element's name
*/
public Element(final String name) {
this.name = name;
}

/**
* Returns the element's name.
*
* @return the name given at construction
*/
public String getName() {
return name;
}

/**
* Compares this element with another by name. The argument is cast without a type check, so passing an object
* that is not an {@code Element} fails with a {@code ClassCastException}. {@code hashCode} is not overridden.
*
* @param obj the object to compare with; must be an {@code Element} or {@code null}
* @return {@code true} if {@code obj} is an element with an equal name, {@code false} if {@code obj} is
* {@code null}
*/
@Override
public boolean equals(final Object obj) {
if (obj == null) {
Expand All @@ -21,6 +42,11 @@ public boolean equals(final Object obj) {
return other.getName().equals(this.getName());
}

/**
* Returns the element's name.
*
* @return the name, same as {@link #getName()}
*/
@Override
public String toString() {
return this.getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.util.Random;

/**
* Static helper methods for arrays.
*/
public final class ArrayUtils {

private ArrayUtils() {}
Expand All @@ -16,8 +19,10 @@ private ArrayUtils() {}
* Crucially, once an item is placed at an index it can't be moved. So for the first index we choose from n items, for the second index we choose from n-1 items, etc
* <p>
* Complexity: O(1) space, and O(n) time.
* <p>
* Arrays with zero or one element are left unchanged.
*
* @param theArray the array to shuffle
* @param theArray the array to shuffle; modified in place
*/
public static void shuffle(final int[] theArray) {
// if it's 1 or 0 items, just return
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,44 @@
package io.github.diegourban.algorithms.datastructure.binarytree;

/**
* A node of a binary tree holding an {@code int} value. The tree is built by linking nodes through the public
* {@link #left} and {@link #right} fields.
*/
public class BinaryTreeNode {

/** The value stored in this node. */
public int value;
/** The left child, or {@code null} if there is none. */
public BinaryTreeNode left;
/** The right child, or {@code null} if there is none. */
public BinaryTreeNode right;

/**
* Creates a leaf node with the given value.
*
* @param value the value to store
*/
public BinaryTreeNode(final int value) {
this.value = value;
}

/**
* Sets a new leaf node as the left child, replacing any existing left subtree.
*
* @param leftValue the value of the new left child
* @return the new left child
*/
public BinaryTreeNode insertLeft(final int leftValue) {
this.left = new BinaryTreeNode(leftValue);
return this.left;
}

/**
* Sets a new leaf node as the right child, replacing any existing right subtree.
*
* @param rightValue the value of the new right child
* @return the new right child
*/
public BinaryTreeNode insertRight(final int rightValue) {
this.right = new BinaryTreeNode(rightValue);
return this.right;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@

import io.github.diegourban.algorithms.datastructure.Element;

/**
* A list of {@link Element}s implemented as a doubly linked chain of {@link LinkedListNode}s, keeping references to
* the first and last nodes and a running size. Positions are zero-based.
*/
public class LinkedList {

private LinkedListNode first = null;
private LinkedListNode last = null;
private int totalElements = 0;

/** Creates an empty list. */
public LinkedList() {}

/**
* Inserts an element at the start of the list.
*
* @param element the element to insert
*/
public void addAtStart(final Element element) {
if (this.totalElements == 0) {
final LinkedListNode newNode = new LinkedListNode(element);
Expand All @@ -22,6 +34,11 @@ public void addAtStart(final Element element) {
this.totalElements++;
}

/**
* Appends an element at the end of the list.
*
* @param element the element to append
*/
public void addAtEnd(final Element element) {
if (this.totalElements == 0) {
addAtStart(element);
Expand All @@ -35,6 +52,18 @@ public void addAtEnd(final Element element) {
}
}

/**
* Inserts an element at the given position, shifting later elements one position back.
* <p>
* If the list is empty the element is added regardless of {@code position}. If {@code position} equals
* {@link #size()} the element is appended. Otherwise the element is linked after the node at
* {@code position - 1}, so inserting at position {@code 0} of a non-empty list is not supported.
*
* @param position the position for the new element, from {@code 1} to {@link #size()} on a non-empty list
* @param element the element to insert
* @throws IllegalArgumentException if the list is not empty and {@code position - 1} is not an occupied position
* (including {@code position == 0})
*/
public void add(final int position, final Element element) {
if (this.totalElements == 0) {
addAtStart(element);
Expand Down Expand Up @@ -68,14 +97,31 @@ private LinkedListNode getNode(final int position) {
return current;
}

/**
* Returns the first node, giving direct access to the chain.
*
* @return the first node, or {@code null} if the list is empty
*/
public LinkedListNode getFirst() {
return this.first;
}

/**
* Returns the element at the given position by walking from the first node.
*
* @param position the zero-based position
* @return the element at {@code position}
* @throws IllegalArgumentException if {@code position} is negative or not less than {@link #size()}
*/
public Element get(final int position) {
return this.getNode(position).getElement();
}

/**
* Removes the first element.
*
* @throws IllegalStateException if the list is empty
*/
public void removeFromStart() {
if (this.totalElements == 0) {
throw new IllegalStateException("Lista vazia");
Expand All @@ -89,6 +135,10 @@ public void removeFromStart() {
}
}

/**
* Removes the last element. Unlike {@link #removeFromStart()}, calling this on an empty list fails with a
* {@code NullPointerException} rather than an {@code IllegalStateException}.
*/
public void removeFromEnd() {
if (this.totalElements == 1) {
this.removeFromStart();
Expand All @@ -100,6 +150,20 @@ public void removeFromEnd() {
}
}

/**
* Removes the element at the given position.
* <p>
* Position {@code 0} delegates to {@link #removeFromStart()} and position {@code size() - 1} to
* {@link #removeFromEnd()}; any other position unlinks the node after {@code position - 1}.
* <p>
* Positions are not fully validated: on a non-empty list, {@code position == size()} fails with a
* {@code NullPointerException}, as does {@code -1} on an empty list.
*
* @param position the zero-based position, from {@code 0} to {@code size() - 1}
* @throws IllegalStateException if {@code position} is {@code 0} and the list is empty
* @throws IllegalArgumentException if {@code position} is negative or greater than {@link #size()}, except
* {@code -1} on an empty list
*/
public void remove(final int position) {
if (position == 0) {
this.removeFromStart();
Expand All @@ -116,10 +180,21 @@ public void remove(final int position) {
}
}

/**
* Returns the number of elements.
*
* @return the number of elements in the list
*/
public int size() {
return this.totalElements;
}

/**
* Tells whether the list holds an element equal to the given one, comparing with {@link Element#equals(Object)}.
*
* @param element the element to look for
* @return {@code true} if an equal element is found
*/
public boolean contains(final Element element) {
LinkedListNode current = this.first;
while (current != null) {
Expand All @@ -131,6 +206,12 @@ public boolean contains(final Element element) {
return false;
}

/**
* Returns the element names in order, each followed by a comma, inside brackets, for example {@code "[a,b,]"};
* an empty list gives {@code "[]"}.
*
* @return the string form of the list
*/
@Override
public String toString() {
if (this.totalElements == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,87 @@

import io.github.diegourban.algorithms.datastructure.Element;

/**
* A node of a doubly linked {@link LinkedList}, holding an {@link Element} and links to the previous and next nodes.
*/
public class LinkedListNode {

private Element element;

private LinkedListNode previous;
private LinkedListNode next;

/**
* Creates a node with no previous or next node.
*
* @param element the element to hold
*/
public LinkedListNode(final Element element) {
this(element, null);
}

/**
* Creates a node linked forward to {@code next}. The previous link is left {@code null}, and {@code next} is not
* updated to point back.
*
* @param element the element to hold
* @param next the next node, or {@code null}
*/
public LinkedListNode(final Element element, final LinkedListNode next) {
this.element = element;
this.next = next;
}

/**
* Returns the element held by this node.
*
* @return the element
*/
public Element getElement() {
return element;
}

/**
* Replaces the element held by this node.
*
* @param element the new element
*/
public void setElement(final Element element) {
this.element = element;
}

/**
* Returns the next node.
*
* @return the next node, or {@code null} if this is the last node
*/
public LinkedListNode getNext() {
return next;
}

/**
* Sets the next node.
*
* @param next the next node, or {@code null}
*/
public void setNext(final LinkedListNode next) {
this.next = next;
}

/**
* Returns the previous node.
*
* @return the previous node, or {@code null} if none is linked
*/
public LinkedListNode getPrevious() {
return previous;
}

/**
* Sets the previous node.
*
* @param previous the previous node, or {@code null}
*/
public void setPrevious(final LinkedListNode previous) {
this.previous = previous;
}
Expand Down
Loading
Loading