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 );
65
-
66
- // Add the node
39
+ DequeNode <T > newNode = new DequeNode <>(val );
67
40
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 ;
71
42
} else {
72
- // If the deque is not empty, insert the node as the new head
73
43
newNode .next = head ;
74
44
head .prev = newNode ;
75
45
head = newNode ;
76
46
}
77
-
78
47
size ++;
79
48
}
80
49
@@ -84,54 +53,35 @@ public void addFirst(T val) {
84
53
* @param val Value to add to the deque
85
54
*/
86
55
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 );
91
57
if (tail == null ) {
92
- // If the deque is empty, add the node as the head and tail
93
- head = newNode ;
58
+ head = tail = newNode ;
94
59
} else {
95
- // If the deque is not empty, insert the node as the new tail
96
60
newNode .prev = tail ;
97
61
tail .next = newNode ;
62
+ tail = newNode ;
98
63
}
99
- tail = newNode ;
100
-
101
64
size ++;
102
65
}
103
66
104
67
/**
105
68
* Removes and returns the first (head) value in the deque
106
69
*
107
70
* @return the value of the head of the deque
71
+ * @throws NoSuchElementException if the deque is empty
108
72
*/
109
73
public T pollFirst () {
110
- // If the head is null, return null
111
74
if (head == null ) {
112
- return null ;
75
+ throw new NoSuchElementException ( "Deque is empty" ) ;
113
76
}
114
77
115
- // First, let's get the value of the old head
116
78
T oldHeadVal = head .val ;
117
-
118
- // Now, let's remove the head
119
79
if (head == tail ) {
120
- // If there is only one node, remove it
121
- head = null ;
122
- tail = null ;
80
+ head = tail = null ;
123
81
} else {
124
- // If there is more than one node, fix the references
125
- head .next .prev = null ;
126
- DequeNode <T > oldHead = head ;
127
82
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 ;
133
84
}
134
-
135
85
size --;
136
86
return oldHeadVal ;
137
87
}
@@ -140,52 +90,40 @@ public T pollFirst() {
140
90
* Removes and returns the last (tail) value in the deque
141
91
*
142
92
* @return the value of the tail of the deque
93
+ * @throws NoSuchElementException if the deque is empty
143
94
*/
144
95
public T pollLast () {
145
- // If the tail is null, return null
146
96
if (tail == null ) {
147
- return null ;
97
+ throw new NoSuchElementException ( "Deque is empty" ) ;
148
98
}
149
99
150
- // Let's get the value of the old tail
151
100
T oldTailVal = tail .val ;
152
-
153
- // Now, remove the tail
154
101
if (head == tail ) {
155
- // If there is only one node, remove it
156
- head = null ;
157
- tail = null ;
102
+ head = tail = null ;
158
103
} else {
159
- // If there is more than one node, fix the references
160
- tail .prev .next = null ;
161
- DequeNode <T > oldTail = tail ;
162
104
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 ;
167
106
}
168
-
169
107
size --;
170
108
return oldTailVal ;
171
109
}
172
110
173
111
/**
174
112
* Returns the first (head) value of the deque WITHOUT removing
175
113
*
176
- * @return the value of the head of the deque
114
+ * @return the value of the head of the deque, or null if empty
177
115
*/
178
116
public T peekFirst () {
179
- return head .val ;
117
+ return head != null ? head .val : null ;
180
118
}
181
119
182
120
/**
183
121
* Returns the last (tail) value of the deque WITHOUT removing
184
122
*
185
- * @return the value of the tail of the deque
123
+ * @return the value of the tail of the deque, or null if empty
186
124
*/
187
125
public T peekLast () {
188
- return tail .val ;
126
+ return tail != null ? tail .val : null ;
189
127
}
190
128
191
129
/**
@@ -203,7 +141,7 @@ public int size() {
203
141
* @return whether or not the deque is empty
204
142
*/
205
143
public boolean isEmpty () {
206
- return head == null ;
144
+ return size == 0 ;
207
145
}
208
146
209
147
/**
@@ -216,25 +154,21 @@ public boolean isEmpty() {
216
154
*/
217
155
@ Override
218
156
public String toString () {
219
- String dequeString = "Head -> " ;
157
+ StringBuilder dequeString = new StringBuilder ( "Head -> " ) ;
220
158
DequeNode <T > currNode = head ;
221
159
while (currNode != null ) {
222
- dequeString += currNode .val ;
223
-
160
+ dequeString .append (currNode .val );
224
161
if (currNode .next != null ) {
225
- dequeString += " <-> " ;
162
+ dequeString . append ( " <-> " ) ;
226
163
}
227
-
228
164
currNode = currNode .next ;
229
165
}
230
-
231
- dequeString += " <- Tail" ;
232
-
233
- return dequeString ;
166
+ dequeString .append (" <- Tail" );
167
+ return dequeString .toString ();
234
168
}
235
169
236
170
public static void main (String [] args ) {
237
- Deques <Integer > myDeque = new Deques < Integer >();
171
+ Deque <Integer > myDeque = new Deque < >();
238
172
for (int i = 0 ; i < 42 ; i ++) {
239
173
if (i / 42.0 < 0.5 ) {
240
174
myDeque .addFirst (i );
0 commit comments