Skip to content

Commit af8e6c9

Browse files
author
Alex Klymenko
committed
refactor: Deque
1 parent f5c0314 commit af8e6c9

File tree

2 files changed

+121
-97
lines changed
  • src
    • main/java/com/thealgorithms/datastructures/queues
    • test/java/com/thealgorithms/datastructures/queues

2 files changed

+121
-97
lines changed

src/main/java/com/thealgorithms/datastructures/queues/Deques.java renamed to src/main/java/com/thealgorithms/datastructures/queues/Deque.java

Lines changed: 31 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.thealgorithms.datastructures.queues;
22

3+
import java.util.NoSuchElementException;
4+
35
/**
46
* A [deque](https://en.wikipedia.org/wiki/Double-ended_queue) is short for a
57
* double ended queue pronounced "deck" and sometimes referred to as a head-tail
@@ -9,72 +11,39 @@
911
*
1012
* @author [Ian Cowan](https://github.com/iccowan)
1113
*/
12-
public class Deques<T> {
14+
public class Deque<T> {
1315

1416
/**
1517
* Node for the deque
1618
*/
17-
class DequeNode<S> {
18-
19-
/**
20-
* Value of the node
21-
*/
19+
private static class DequeNode<S> {
2220
S val;
23-
24-
/**
25-
* Next node in the deque from this node
26-
*/
2721
DequeNode<S> next = null;
28-
29-
/**
30-
* Previous node in the deque from this node
31-
*/
3222
DequeNode<S> prev = null;
3323

34-
/**
35-
* Constructor
36-
*/
3724
DequeNode(S val) {
3825
this.val = val;
3926
}
4027
}
4128

42-
/**
43-
* Head of the deque
44-
*/
45-
DequeNode<T> head = null;
46-
47-
/**
48-
* Tail of the deque
49-
*/
50-
DequeNode<T> tail = null;
51-
52-
/**
53-
* Size of the deque
54-
*/
55-
int size = 0;
29+
private DequeNode<T> head = null;
30+
private DequeNode<T> tail = null;
31+
private int size = 0;
5632

5733
/**
5834
* Adds the specified value to the head of the deque
5935
*
6036
* @param val Value to add to the deque
6137
*/
6238
public void addFirst(T val) {
63-
// Create a new node with the given value
64-
DequeNode<T> newNode = new DequeNode<T>(val);
65-
66-
// Add the node
39+
DequeNode<T> newNode = new DequeNode<>(val);
6740
if (head == null) {
68-
// If the deque is empty, add the node as the head and tail
69-
head = newNode;
70-
tail = newNode;
41+
head = tail = newNode;
7142
} else {
72-
// If the deque is not empty, insert the node as the new head
7343
newNode.next = head;
7444
head.prev = newNode;
7545
head = newNode;
7646
}
77-
7847
size++;
7948
}
8049

@@ -84,54 +53,35 @@ public void addFirst(T val) {
8453
* @param val Value to add to the deque
8554
*/
8655
public void addLast(T val) {
87-
// Create a new node with the given value
88-
DequeNode<T> newNode = new DequeNode<T>(val);
89-
90-
// Add the node
56+
DequeNode<T> newNode = new DequeNode<>(val);
9157
if (tail == null) {
92-
// If the deque is empty, add the node as the head and tail
93-
head = newNode;
58+
head = tail = newNode;
9459
} else {
95-
// If the deque is not empty, insert the node as the new tail
9660
newNode.prev = tail;
9761
tail.next = newNode;
62+
tail = newNode;
9863
}
99-
tail = newNode;
100-
10164
size++;
10265
}
10366

10467
/**
10568
* Removes and returns the first (head) value in the deque
10669
*
10770
* @return the value of the head of the deque
71+
* @throws NoSuchElementException if the deque is empty
10872
*/
10973
public T pollFirst() {
110-
// If the head is null, return null
11174
if (head == null) {
112-
return null;
75+
throw new NoSuchElementException("Deque is empty");
11376
}
11477

115-
// First, let's get the value of the old head
11678
T oldHeadVal = head.val;
117-
118-
// Now, let's remove the head
11979
if (head == tail) {
120-
// If there is only one node, remove it
121-
head = null;
122-
tail = null;
80+
head = tail = null;
12381
} else {
124-
// If there is more than one node, fix the references
125-
head.next.prev = null;
126-
DequeNode<T> oldHead = head;
12782
head = head.next;
128-
129-
// Can be considered unnecessary...
130-
// Unlinking the old head to make sure there are no random
131-
// references possibly affecting garbage collection
132-
oldHead.next = null;
83+
head.prev = null;
13384
}
134-
13585
size--;
13686
return oldHeadVal;
13787
}
@@ -140,52 +90,40 @@ public T pollFirst() {
14090
* Removes and returns the last (tail) value in the deque
14191
*
14292
* @return the value of the tail of the deque
93+
* @throws NoSuchElementException if the deque is empty
14394
*/
14495
public T pollLast() {
145-
// If the tail is null, return null
14696
if (tail == null) {
147-
return null;
97+
throw new NoSuchElementException("Deque is empty");
14898
}
14999

150-
// Let's get the value of the old tail
151100
T oldTailVal = tail.val;
152-
153-
// Now, remove the tail
154101
if (head == tail) {
155-
// If there is only one node, remove it
156-
head = null;
157-
tail = null;
102+
head = tail = null;
158103
} else {
159-
// If there is more than one node, fix the references
160-
tail.prev.next = null;
161-
DequeNode<T> oldTail = tail;
162104
tail = tail.prev;
163-
164-
// Similarly to above, can be considered unnecessary
165-
// See `pollFirst()` for explanation
166-
oldTail.prev = null;
105+
tail.next = null;
167106
}
168-
169107
size--;
170108
return oldTailVal;
171109
}
172110

173111
/**
174112
* Returns the first (head) value of the deque WITHOUT removing
175113
*
176-
* @return the value of the head of the deque
114+
* @return the value of the head of the deque, or null if empty
177115
*/
178116
public T peekFirst() {
179-
return head.val;
117+
return head != null ? head.val : null;
180118
}
181119

182120
/**
183121
* Returns the last (tail) value of the deque WITHOUT removing
184122
*
185-
* @return the value of the tail of the deque
123+
* @return the value of the tail of the deque, or null if empty
186124
*/
187125
public T peekLast() {
188-
return tail.val;
126+
return tail != null ? tail.val : null;
189127
}
190128

191129
/**
@@ -203,7 +141,7 @@ public int size() {
203141
* @return whether or not the deque is empty
204142
*/
205143
public boolean isEmpty() {
206-
return head == null;
144+
return size == 0;
207145
}
208146

209147
/**
@@ -216,25 +154,21 @@ public boolean isEmpty() {
216154
*/
217155
@Override
218156
public String toString() {
219-
String dequeString = "Head -> ";
157+
StringBuilder dequeString = new StringBuilder("Head -> ");
220158
DequeNode<T> currNode = head;
221159
while (currNode != null) {
222-
dequeString += currNode.val;
223-
160+
dequeString.append(currNode.val);
224161
if (currNode.next != null) {
225-
dequeString += " <-> ";
162+
dequeString.append(" <-> ");
226163
}
227-
228164
currNode = currNode.next;
229165
}
230-
231-
dequeString += " <- Tail";
232-
233-
return dequeString;
166+
dequeString.append(" <- Tail");
167+
return dequeString.toString();
234168
}
235169

236170
public static void main(String[] args) {
237-
Deques<Integer> myDeque = new Deques<Integer>();
171+
Deque<Integer> myDeque = new Deque<>();
238172
for (int i = 0; i < 42; i++) {
239173
if (i / 42.0 < 0.5) {
240174
myDeque.addFirst(i);
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package com.thealgorithms.datastructures.queues;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.assertNull;
6+
7+
import org.junit.jupiter.api.Test;
8+
import java.util.NoSuchElementException;
9+
10+
class DequeTest {
11+
12+
@Test
13+
void testAddFirst() {
14+
Deque<Integer> deque = new Deque<>();
15+
deque.addFirst(10);
16+
assertEquals(10, deque.peekFirst());
17+
assertEquals(10, deque.peekLast());
18+
assertEquals(1, deque.size());
19+
}
20+
21+
@Test
22+
void testAddLast() {
23+
Deque<Integer> deque = new Deque<>();
24+
deque.addLast(20);
25+
assertEquals(20, deque.peekFirst());
26+
assertEquals(20, deque.peekLast());
27+
assertEquals(1, deque.size());
28+
}
29+
30+
@Test
31+
void testPollFirst() {
32+
Deque<Integer> deque = new Deque<>();
33+
deque.addFirst(10);
34+
deque.addLast(20);
35+
assertEquals(10, deque.pollFirst());
36+
assertEquals(20, deque.peekFirst());
37+
assertEquals(1, deque.size());
38+
}
39+
40+
@Test
41+
void testPollLast() {
42+
Deque<Integer> deque = new Deque<>();
43+
deque.addFirst(10);
44+
deque.addLast(20);
45+
assertEquals(20, deque.pollLast());
46+
assertEquals(10, deque.peekLast());
47+
assertEquals(1, deque.size());
48+
}
49+
50+
@Test
51+
void testIsEmpty() {
52+
Deque<Integer> deque = new Deque<>();
53+
org.junit.jupiter.api.Assertions.assertTrue(deque.isEmpty());
54+
deque.addFirst(10);
55+
assertFalse(deque.isEmpty());
56+
}
57+
58+
@Test
59+
void testPeekFirstEmpty() {
60+
Deque<Integer> deque = new Deque<>();
61+
assertNull(deque.peekFirst());
62+
}
63+
64+
@Test
65+
void testPeekLastEmpty() {
66+
Deque<Integer> deque = new Deque<>();
67+
assertNull(deque.peekLast());
68+
}
69+
70+
@Test
71+
void testPollFirstEmpty() {
72+
Deque<Integer> deque = new Deque<>();
73+
org.junit.jupiter.api.Assertions.assertThrows(NoSuchElementException.class, deque::pollFirst);
74+
}
75+
76+
@Test
77+
void testPollLastEmpty() {
78+
Deque<Integer> deque = new Deque<>();
79+
org.junit.jupiter.api.Assertions.assertThrows(NoSuchElementException.class, deque::pollLast);
80+
}
81+
82+
@Test
83+
void testToString() {
84+
Deque<Integer> deque = new Deque<>();
85+
deque.addFirst(10);
86+
deque.addLast(20);
87+
deque.addFirst(5);
88+
assertEquals("Head -> 5 <-> 10 <-> 20 <- Tail", deque.toString());
89+
}
90+
}

0 commit comments

Comments
 (0)