From af8e6c9a41f5f5fbdf5413cd49d90146ab4bd17c Mon Sep 17 00:00:00 2001 From: Alex Klymenko Date: Wed, 21 Aug 2024 00:01:41 +0200 Subject: [PATCH 1/3] refactor: Deque --- .../queues/{Deques.java => Deque.java} | 128 +++++------------- .../datastructures/queues/DequeTest.java | 90 ++++++++++++ 2 files changed, 121 insertions(+), 97 deletions(-) rename src/main/java/com/thealgorithms/datastructures/queues/{Deques.java => Deque.java} (59%) create mode 100644 src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java diff --git a/src/main/java/com/thealgorithms/datastructures/queues/Deques.java b/src/main/java/com/thealgorithms/datastructures/queues/Deque.java similarity index 59% rename from src/main/java/com/thealgorithms/datastructures/queues/Deques.java rename to src/main/java/com/thealgorithms/datastructures/queues/Deque.java index 5c4e9b641445..6a9f312478a8 100644 --- a/src/main/java/com/thealgorithms/datastructures/queues/Deques.java +++ b/src/main/java/com/thealgorithms/datastructures/queues/Deque.java @@ -1,5 +1,7 @@ package com.thealgorithms.datastructures.queues; +import java.util.NoSuchElementException; + /** * A [deque](https://en.wikipedia.org/wiki/Double-ended_queue) is short for a * double ended queue pronounced "deck" and sometimes referred to as a head-tail @@ -9,50 +11,24 @@ * * @author [Ian Cowan](https://github.com/iccowan) */ -public class Deques { +public class Deque { /** * Node for the deque */ - class DequeNode { - - /** - * Value of the node - */ + private static class DequeNode { S val; - - /** - * Next node in the deque from this node - */ DequeNode next = null; - - /** - * Previous node in the deque from this node - */ DequeNode prev = null; - /** - * Constructor - */ DequeNode(S val) { this.val = val; } } - /** - * Head of the deque - */ - DequeNode head = null; - - /** - * Tail of the deque - */ - DequeNode tail = null; - - /** - * Size of the deque - */ - int size = 0; + private DequeNode head = null; + private DequeNode tail = null; + private int size = 0; /** * Adds the specified value to the head of the deque @@ -60,21 +36,14 @@ class DequeNode { * @param val Value to add to the deque */ public void addFirst(T val) { - // Create a new node with the given value - DequeNode newNode = new DequeNode(val); - - // Add the node + DequeNode newNode = new DequeNode<>(val); if (head == null) { - // If the deque is empty, add the node as the head and tail - head = newNode; - tail = newNode; + head = tail = newNode; } else { - // If the deque is not empty, insert the node as the new head newNode.next = head; head.prev = newNode; head = newNode; } - size++; } @@ -84,20 +53,14 @@ public void addFirst(T val) { * @param val Value to add to the deque */ public void addLast(T val) { - // Create a new node with the given value - DequeNode newNode = new DequeNode(val); - - // Add the node + DequeNode newNode = new DequeNode<>(val); if (tail == null) { - // If the deque is empty, add the node as the head and tail - head = newNode; + head = tail = newNode; } else { - // If the deque is not empty, insert the node as the new tail newNode.prev = tail; tail.next = newNode; + tail = newNode; } - tail = newNode; - size++; } @@ -105,33 +68,20 @@ public void addLast(T val) { * Removes and returns the first (head) value in the deque * * @return the value of the head of the deque + * @throws NoSuchElementException if the deque is empty */ public T pollFirst() { - // If the head is null, return null if (head == null) { - return null; + throw new NoSuchElementException("Deque is empty"); } - // First, let's get the value of the old head T oldHeadVal = head.val; - - // Now, let's remove the head if (head == tail) { - // If there is only one node, remove it - head = null; - tail = null; + head = tail = null; } else { - // If there is more than one node, fix the references - head.next.prev = null; - DequeNode oldHead = head; head = head.next; - - // Can be considered unnecessary... - // Unlinking the old head to make sure there are no random - // references possibly affecting garbage collection - oldHead.next = null; + head.prev = null; } - size--; return oldHeadVal; } @@ -140,32 +90,20 @@ public T pollFirst() { * Removes and returns the last (tail) value in the deque * * @return the value of the tail of the deque + * @throws NoSuchElementException if the deque is empty */ public T pollLast() { - // If the tail is null, return null if (tail == null) { - return null; + throw new NoSuchElementException("Deque is empty"); } - // Let's get the value of the old tail T oldTailVal = tail.val; - - // Now, remove the tail if (head == tail) { - // If there is only one node, remove it - head = null; - tail = null; + head = tail = null; } else { - // If there is more than one node, fix the references - tail.prev.next = null; - DequeNode oldTail = tail; tail = tail.prev; - - // Similarly to above, can be considered unnecessary - // See `pollFirst()` for explanation - oldTail.prev = null; + tail.next = null; } - size--; return oldTailVal; } @@ -173,19 +111,19 @@ public T pollLast() { /** * Returns the first (head) value of the deque WITHOUT removing * - * @return the value of the head of the deque + * @return the value of the head of the deque, or null if empty */ public T peekFirst() { - return head.val; + return head != null ? head.val : null; } /** * Returns the last (tail) value of the deque WITHOUT removing * - * @return the value of the tail of the deque + * @return the value of the tail of the deque, or null if empty */ public T peekLast() { - return tail.val; + return tail != null ? tail.val : null; } /** @@ -203,7 +141,7 @@ public int size() { * @return whether or not the deque is empty */ public boolean isEmpty() { - return head == null; + return size == 0; } /** @@ -216,25 +154,21 @@ public boolean isEmpty() { */ @Override public String toString() { - String dequeString = "Head -> "; + StringBuilder dequeString = new StringBuilder("Head -> "); DequeNode currNode = head; while (currNode != null) { - dequeString += currNode.val; - + dequeString.append(currNode.val); if (currNode.next != null) { - dequeString += " <-> "; + dequeString.append(" <-> "); } - currNode = currNode.next; } - - dequeString += " <- Tail"; - - return dequeString; + dequeString.append(" <- Tail"); + return dequeString.toString(); } public static void main(String[] args) { - Deques myDeque = new Deques(); + Deque myDeque = new Deque<>(); for (int i = 0; i < 42; i++) { if (i / 42.0 < 0.5) { myDeque.addFirst(i); diff --git a/src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java b/src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java new file mode 100644 index 000000000000..eb0094fec27c --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java @@ -0,0 +1,90 @@ +package com.thealgorithms.datastructures.queues; + +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 org.junit.jupiter.api.Test; +import java.util.NoSuchElementException; + +class DequeTest { + + @Test + void testAddFirst() { + Deque deque = new Deque<>(); + deque.addFirst(10); + assertEquals(10, deque.peekFirst()); + assertEquals(10, deque.peekLast()); + assertEquals(1, deque.size()); + } + + @Test + void testAddLast() { + Deque deque = new Deque<>(); + deque.addLast(20); + assertEquals(20, deque.peekFirst()); + assertEquals(20, deque.peekLast()); + assertEquals(1, deque.size()); + } + + @Test + void testPollFirst() { + Deque deque = new Deque<>(); + deque.addFirst(10); + deque.addLast(20); + assertEquals(10, deque.pollFirst()); + assertEquals(20, deque.peekFirst()); + assertEquals(1, deque.size()); + } + + @Test + void testPollLast() { + Deque deque = new Deque<>(); + deque.addFirst(10); + deque.addLast(20); + assertEquals(20, deque.pollLast()); + assertEquals(10, deque.peekLast()); + assertEquals(1, deque.size()); + } + + @Test + void testIsEmpty() { + Deque deque = new Deque<>(); + org.junit.jupiter.api.Assertions.assertTrue(deque.isEmpty()); + deque.addFirst(10); + assertFalse(deque.isEmpty()); + } + + @Test + void testPeekFirstEmpty() { + Deque deque = new Deque<>(); + assertNull(deque.peekFirst()); + } + + @Test + void testPeekLastEmpty() { + Deque deque = new Deque<>(); + assertNull(deque.peekLast()); + } + + @Test + void testPollFirstEmpty() { + Deque deque = new Deque<>(); + org.junit.jupiter.api.Assertions.assertThrows(NoSuchElementException.class, deque::pollFirst); + } + + @Test + void testPollLastEmpty() { + Deque deque = new Deque<>(); + org.junit.jupiter.api.Assertions.assertThrows(NoSuchElementException.class, deque::pollLast); + } + + @Test + void testToString() { + Deque deque = new Deque<>(); + deque.addFirst(10); + deque.addLast(20); + deque.addFirst(5); + assertEquals("Head -> 5 <-> 10 <-> 20 <- Tail", deque.toString()); + } +} From 630f377a9d00699ea63667618025bad0b51d52e9 Mon Sep 17 00:00:00 2001 From: Alex Klymenko Date: Wed, 21 Aug 2024 00:03:21 +0200 Subject: [PATCH 2/3] checkstyle: fix import ordering --- .../java/com/thealgorithms/datastructures/queues/DequeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java b/src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java index eb0094fec27c..1244a2e260d2 100644 --- a/src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java +++ b/src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java @@ -4,8 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; -import org.junit.jupiter.api.Test; import java.util.NoSuchElementException; +import org.junit.jupiter.api.Test; class DequeTest { From c58d15f243d9d55f7c0367fb79ac3b8eea1c63fc Mon Sep 17 00:00:00 2001 From: Alex Klymenko Date: Wed, 21 Aug 2024 00:10:16 +0200 Subject: [PATCH 3/3] checkstyle: multiple one line assigment --- .../datastructures/queues/Deque.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/thealgorithms/datastructures/queues/Deque.java b/src/main/java/com/thealgorithms/datastructures/queues/Deque.java index 6a9f312478a8..4cfa2b442ca0 100644 --- a/src/main/java/com/thealgorithms/datastructures/queues/Deque.java +++ b/src/main/java/com/thealgorithms/datastructures/queues/Deque.java @@ -37,13 +37,16 @@ private static class DequeNode { */ public void addFirst(T val) { DequeNode newNode = new DequeNode<>(val); - if (head == null) { - head = tail = newNode; + + if (isEmpty()) { + head = newNode; + tail = newNode; } else { newNode.next = head; head.prev = newNode; head = newNode; } + size++; } @@ -55,7 +58,8 @@ public void addFirst(T val) { public void addLast(T val) { DequeNode newNode = new DequeNode<>(val); if (tail == null) { - head = tail = newNode; + head = newNode; + tail = newNode; } else { newNode.prev = tail; tail.next = newNode; @@ -77,7 +81,8 @@ public T pollFirst() { T oldHeadVal = head.val; if (head == tail) { - head = tail = null; + head = null; + tail = null; } else { head = head.next; head.prev = null; @@ -99,7 +104,8 @@ public T pollLast() { T oldTailVal = tail.val; if (head == tail) { - head = tail = null; + head = null; + tail = null; } else { tail = tail.prev; tail.next = null;