1
1
package com .thealgorithms .datastructures .queues ;
2
2
3
+ import java .util .NoSuchElementException ;
4
+
3
5
/**
4
6
* A [deque](https://en.wikipedia.org/wiki/Double-ended_queue) is short for a
5
7
* double ended queue pronounced "deck" and sometimes referred to as a head-tail
9
11
*
10
12
* @author [Ian Cowan](https://github.com/iccowan)
11
13
*/
12
- public class Deques <T > {
14
+ public class Deque <T > {
13
15
14
16
/**
15
17
* Node for the deque
16
18
*/
17
- class DequeNode <S > {
18
-
19
- /**
20
- * Value of the node
21
- */
19
+ private static class DequeNode <S > {
22
20
S val ;
23
-
24
- /**
25
- * Next node in the deque from this node
26
- */
27
21
DequeNode <S > next = null ;
28
-
29
- /**
30
- * Previous node in the deque from this node
31
- */
32
22
DequeNode <S > prev = null ;
33
23
34
- /**
35
- * Constructor
36
- */
37
24
DequeNode (S val ) {
38
25
this .val = val ;
39
26
}
40
27
}
41
28
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 ;
56
32
57
33
/**
58
34
* Adds the specified value to the head of the deque
59
35
*
60
36
* @param val Value to add to the deque
61
37
*/
62
38
public void addFirst (T val ) {
63
- // Create a new node with the given value
64
- DequeNode <T > newNode = new DequeNode <T >(val );
39
+ DequeNode <T > newNode = new DequeNode <>(val );
65
40
66
- // Add the node
67
- if (head == null ) {
68
- // If the deque is empty, add the node as the head and tail
41
+ if (isEmpty ()) {
69
42
head = newNode ;
70
43
tail = newNode ;
71
44
} else {
72
- // If the deque is not empty, insert the node as the new head
73
45
newNode .next = head ;
74
46
head .prev = newNode ;
75
47
head = newNode ;
@@ -84,54 +56,37 @@ public void addFirst(T val) {
84
56
* @param val Value to add to the deque
85
57
*/
86
58
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
59
+ DequeNode <T > newNode = new DequeNode <>(val );
91
60
if (tail == null ) {
92
- // If the deque is empty, add the node as the head and tail
93
61
head = newNode ;
62
+ tail = newNode ;
94
63
} else {
95
- // If the deque is not empty, insert the node as the new tail
96
64
newNode .prev = tail ;
97
65
tail .next = newNode ;
66
+ tail = newNode ;
98
67
}
99
- tail = newNode ;
100
-
101
68
size ++;
102
69
}
103
70
104
71
/**
105
72
* Removes and returns the first (head) value in the deque
106
73
*
107
74
* @return the value of the head of the deque
75
+ * @throws NoSuchElementException if the deque is empty
108
76
*/
109
77
public T pollFirst () {
110
- // If the head is null, return null
111
78
if (head == null ) {
112
- return null ;
79
+ throw new NoSuchElementException ( "Deque is empty" ) ;
113
80
}
114
81
115
- // First, let's get the value of the old head
116
82
T oldHeadVal = head .val ;
117
-
118
- // Now, let's remove the head
119
83
if (head == tail ) {
120
- // If there is only one node, remove it
121
84
head = null ;
122
85
tail = null ;
123
86
} else {
124
- // If there is more than one node, fix the references
125
- head .next .prev = null ;
126
- DequeNode <T > oldHead = head ;
127
87
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 ;
88
+ head .prev = null ;
133
89
}
134
-
135
90
size --;
136
91
return oldHeadVal ;
137
92
}
@@ -140,52 +95,41 @@ public T pollFirst() {
140
95
* Removes and returns the last (tail) value in the deque
141
96
*
142
97
* @return the value of the tail of the deque
98
+ * @throws NoSuchElementException if the deque is empty
143
99
*/
144
100
public T pollLast () {
145
- // If the tail is null, return null
146
101
if (tail == null ) {
147
- return null ;
102
+ throw new NoSuchElementException ( "Deque is empty" ) ;
148
103
}
149
104
150
- // Let's get the value of the old tail
151
105
T oldTailVal = tail .val ;
152
-
153
- // Now, remove the tail
154
106
if (head == tail ) {
155
- // If there is only one node, remove it
156
107
head = null ;
157
108
tail = null ;
158
109
} else {
159
- // If there is more than one node, fix the references
160
- tail .prev .next = null ;
161
- DequeNode <T > oldTail = tail ;
162
110
tail = tail .prev ;
163
-
164
- // Similarly to above, can be considered unnecessary
165
- // See `pollFirst()` for explanation
166
- oldTail .prev = null ;
111
+ tail .next = null ;
167
112
}
168
-
169
113
size --;
170
114
return oldTailVal ;
171
115
}
172
116
173
117
/**
174
118
* Returns the first (head) value of the deque WITHOUT removing
175
119
*
176
- * @return the value of the head of the deque
120
+ * @return the value of the head of the deque, or null if empty
177
121
*/
178
122
public T peekFirst () {
179
- return head .val ;
123
+ return head != null ? head .val : null ;
180
124
}
181
125
182
126
/**
183
127
* Returns the last (tail) value of the deque WITHOUT removing
184
128
*
185
- * @return the value of the tail of the deque
129
+ * @return the value of the tail of the deque, or null if empty
186
130
*/
187
131
public T peekLast () {
188
- return tail .val ;
132
+ return tail != null ? tail .val : null ;
189
133
}
190
134
191
135
/**
@@ -203,7 +147,7 @@ public int size() {
203
147
* @return whether or not the deque is empty
204
148
*/
205
149
public boolean isEmpty () {
206
- return head == null ;
150
+ return size == 0 ;
207
151
}
208
152
209
153
/**
@@ -216,25 +160,21 @@ public boolean isEmpty() {
216
160
*/
217
161
@ Override
218
162
public String toString () {
219
- String dequeString = "Head -> " ;
163
+ StringBuilder dequeString = new StringBuilder ( "Head -> " ) ;
220
164
DequeNode <T > currNode = head ;
221
165
while (currNode != null ) {
222
- dequeString += currNode .val ;
223
-
166
+ dequeString .append (currNode .val );
224
167
if (currNode .next != null ) {
225
- dequeString += " <-> " ;
168
+ dequeString . append ( " <-> " ) ;
226
169
}
227
-
228
170
currNode = currNode .next ;
229
171
}
230
-
231
- dequeString += " <- Tail" ;
232
-
233
- return dequeString ;
172
+ dequeString .append (" <- Tail" );
173
+ return dequeString .toString ();
234
174
}
235
175
236
176
public static void main (String [] args ) {
237
- Deques <Integer > myDeque = new Deques < Integer >();
177
+ Deque <Integer > myDeque = new Deque < >();
238
178
for (int i = 0 ; i < 42 ; i ++) {
239
179
if (i / 42.0 < 0.5 ) {
240
180
myDeque .addFirst (i );
0 commit comments