@@ -2,94 +2,135 @@ package structures
2
2
3
3
/* *
4
4
*
5
- * data structure: doubly linked list
5
+ * LinkedList a data structure consisting of a collection of nodes that contain a link to the next/previous node.
6
6
*
7
- * description: in a doubly linked list, each element stores a link to the previous and next elements
8
- *
9
- * time to insert an element at the beginning and end of the list: O(1)
10
- * insertion time in the middle by index: O(n)
11
- * delete: O(n)
7
+ * In the double LinkedList each node contains a link to the previous and next elements
12
8
*
13
9
*/
14
10
15
- class DoubleLinkedList <T >(
16
- /* *
17
- * stores a reference to the first element of the list
18
- *
19
- * if the list is empty, then the reference is null
20
- */
21
- private var first : Node <T >? = null ,
22
- /* *
23
- * stores a reference to the last element of the list
24
- *
25
- * if the list is empty, then the reference is null
26
- */
27
- private var last : Node <T >? = null
28
- ) {
11
+ class DoubleLinkedList <T > {
29
12
30
- /* *
31
- * stores the number of elements in the list
32
- *
33
- */
34
- private var count: Int = 0
13
+ private var head: Node <T >? = null
14
+ private var tail: Node <T >? = null
35
15
36
- /* *
37
- * doubly linked list node
38
- *
39
- * @property value - node value
40
- * @property prev - link to the previous element (assuming the element is not the first one)
41
- * @property next - link to the next element (assuming the element is not the last one)
42
- */
43
- class Node <T >(
44
- private val value : T ,
45
- private var prev : Node <T >? = null ,
46
- private var next : Node <T >? = null
47
- ) {
16
+ private var size: Int = 0
17
+
18
+ val isEmpty: Boolean
19
+ get() = head == null
48
20
49
- fun changeNext (next : Node <T >? = null) {
50
- this .next = next
21
+ // Complexity: O(n)
22
+ val list: List <T >
23
+ get() {
24
+ val nodes = mutableListOf<T >()
25
+ var node = head
26
+ while (node != null ) {
27
+ val nodeValue = node.value()
28
+ if (nodeValue != null ) {
29
+ nodes.add(nodeValue)
30
+ }
31
+ node = node.next()
32
+ }
33
+ return nodes
51
34
}
52
35
53
- fun changePrev (prev : Node <T >? = null) {
54
- this .prev = prev
36
+ // Complexity: O(n)
37
+ val reversedList: List <T >
38
+ get() {
39
+ val nodes = mutableListOf<T >()
40
+ var node = tail
41
+ while (node != null ) {
42
+ val nodeValue = node.value()
43
+ if (nodeValue != null ) {
44
+ nodes.add(nodeValue)
45
+ }
46
+ node = node.previous()
47
+ }
48
+ return nodes
55
49
}
56
50
57
- fun next () = next
58
- fun prev () = prev
59
- fun value () = value
51
+ /* *
52
+ * Complexity:
53
+ * worst time: O(n)
54
+ * best time: O(1)
55
+ * average time: O(n)
56
+ */
57
+ fun add (index : Int , value : T ) : Boolean {
58
+ if (head == null ) return false
60
59
61
- fun isOne () = prev == null && next == null
62
- fun isFirst () = prev == null
63
- fun isLast () = next == null
60
+ var i = 0
61
+ var node = head
62
+ var prevNode = head
63
+ while (prevNode != null && node != null ) {
64
+ if (i == index) {
65
+ val newNode = Node (value)
66
+ newNode.changeNext(node)
67
+ newNode.changePrevious(prevNode)
68
+ prevNode.changeNext(newNode)
69
+ size++
70
+ return true
71
+ }
72
+ i++
73
+ prevNode = node
74
+ node = node.next()
75
+ }
76
+
77
+ return false
64
78
}
65
79
80
+ fun add (value : T ) = addLast(value)
81
+
66
82
/* *
67
- * returns the number of elements in the list
83
+ * Complexity:
84
+ * worst time: O(1)
85
+ * best time: O(1)
86
+ * average time: O(1)
68
87
*/
69
- fun size () = count
88
+ fun addFirst (value : T ) {
89
+ val headNode = head
90
+ head = if (headNode == null ) {
91
+ Node (value)
92
+ } else {
93
+ val newNode = Node (value = value, next = headNode)
94
+ headNode.changePrevious(newNode)
95
+ newNode
96
+ }
97
+ if (tail == null ) {
98
+ tail = head
99
+ }
100
+ size++
101
+ }
70
102
71
103
/* *
72
- * converts a list into a normal Kotlin list for visual representation, returns Kotlin a list of elements
104
+ * Complexity:
105
+ * worst time: O(1)
106
+ * best time: O(1)
107
+ * average time: O(1)
73
108
*/
74
- fun toList () : List <T > {
75
- if (first == null ) return listOf ()
76
-
77
- val list = mutableListOf<T >()
78
- var node = first
79
- while (node != null ) {
80
- list.add(node.value())
81
- node = node.next()
109
+ fun addLast (value : T ) {
110
+ val tailNode = tail
111
+ tail = if (tailNode == null ) {
112
+ Node (value)
113
+ } else {
114
+ val newNode = Node (value = value, previous = tailNode)
115
+ tailNode.changeNext(newNode)
116
+ newNode
117
+ }
118
+ if (head == null ) {
119
+ head = tail
82
120
}
83
- return list
121
+ size ++
84
122
}
85
123
86
124
/* *
87
- * checks if an element [value] is in the list, returns true if the value exists in the list
125
+ * Complexity:
126
+ * worst time: O(n)
127
+ * best time: O(1)
128
+ * average time: O(n)
88
129
*/
89
130
fun contains (value : T ) : Boolean {
90
- if (first == null ) return false
131
+ if (head == null ) return false
91
132
92
- var node = first
133
+ var node = head
93
134
while (node != null ) {
94
135
if (node.value() == value) {
95
136
return true
@@ -100,113 +141,110 @@ class DoubleLinkedList<T>(
100
141
}
101
142
102
143
/* *
103
- * checks if the list is empty, returns true if the list is empty
104
- */
105
- fun isEmpty () = first == null
106
-
107
- /* *
108
- * removes an element [value] from the list, returns true if the element was successfully removed
144
+ * Complexity:
145
+ * worst time: O(n)
146
+ * best time: O(1)
147
+ * average time: O(n)
109
148
*/
110
149
fun remove (value : T ) : Boolean {
111
- if (first == null ) return false
150
+ if (head == null ) return false
112
151
113
- var node = first
152
+ var previous: Node <T >? = null
153
+ var node = head
114
154
115
155
while (node != null ) {
116
156
if (node.value() == value) {
117
- if (node.isOne()) {
118
- first = null
119
- last = null
120
- } else if (node.isFirst()) {
121
- val next = node.next()
122
- next?.changePrev(null )
123
- first = next
124
- } else if (node.isLast()) {
125
- val prev = node.prev()
126
- prev?.changeNext(null )
127
- last = prev
128
- } else {
129
- node.prev()?.changeNext(node.next())
130
- node.next()?.changePrev(node.prev())
157
+ val nextNode = node.next()
158
+ previous?.changeNext(nextNode)
159
+ nextNode?.changePrevious(previous)
160
+
161
+ if (node == = head) {
162
+ head = nextNode
131
163
}
132
- count--
164
+
165
+ if (node == = tail) {
166
+ tail = previous
167
+ }
168
+
169
+ node.changePrevious(null )
170
+ node.changeNext(null )
171
+ node.changeValue(null )
172
+
173
+ size--
133
174
return true
134
175
}
176
+ previous = node
135
177
node = node.next()
136
178
}
179
+
137
180
return false
138
181
}
139
182
140
- /* *
141
- * adds element [value] by index [index], returns true if the element was successfully added at the specified index
142
- */
143
- fun add (index : Int , value : T ) : Boolean {
183
+ // Complexity: O(n)
184
+ fun clear () {
185
+ var node = head
186
+ while (node != null ) {
187
+ val currentNode = node
188
+
189
+ node = node.next()
144
190
145
- if (first == null ) return false
191
+ currentNode.changeNext(null )
192
+ currentNode.changePrevious(null )
193
+ currentNode.changeValue(null )
194
+ }
146
195
147
- var i = 0
148
- var node = first
196
+ head = null
197
+ tail = null
198
+ size = 0
199
+ }
200
+
201
+ override fun toString (): String {
202
+ val builder = StringBuilder ()
203
+ builder.append(" size: $size \n " )
204
+ builder.append(" elements: " )
205
+
206
+ var node = head
149
207
while (node != null ) {
150
- if (i == index) {
151
- val newNode = Node (value)
152
208
153
- newNode.changePrev(node.prev())
154
- newNode.changeNext(node)
209
+ // it's necessary to see the correct node connections
210
+ if (node.previous() != null ) {
211
+ builder.append(" - " )
212
+ }
155
213
156
- node.prev()?.changeNext(newNode)
157
- node.changePrev(newNode)
214
+ builder.append(node.value())
158
215
159
- count++
160
- return true
216
+ // it's necessary to see the correct node connections
217
+ if (node.next() != null ) {
218
+ builder.append(" -" )
161
219
}
162
- i ++
220
+
163
221
node = node.next()
164
222
}
165
223
166
- return false
224
+ return builder.toString()
167
225
}
168
226
169
- /* *
170
- * similar addLast [addLast] method
171
- */
172
- fun add (value : T ) = addLast(value)
227
+ class Node <T >(
228
+ private var value : T ? = null ,
229
+ private var previous : Node <T >? = null ,
230
+ private var next : Node <T >? = null
231
+ ) {
173
232
174
- /* *
175
- * adds an element [value] to the beginning of the list
176
- */
177
- fun addFirst (value : T ) {
178
- val firstNode = first
179
- first = if (firstNode == null ) {
180
- Node (value)
181
- } else {
182
- val newNode = Node (value)
183
- newNode.changeNext(firstNode)
184
- firstNode.changePrev(newNode)
185
- newNode
186
- }
187
- if (last == null ) {
188
- last = first
233
+ fun next () = next
234
+ fun changeNext (node : Node <T >? = null) {
235
+ next = node
189
236
}
190
- count++
191
- }
192
237
193
- /* *
194
- * adds an element [value] to the end of the list
195
- */
196
- fun addLast (value : T ) {
197
- val lastNode = last
198
- last = if (lastNode == null ) {
199
- Node (value)
200
- } else {
201
- val newNode = Node (value)
202
- lastNode.changeNext(newNode)
203
- newNode.changePrev(lastNode)
204
- newNode
238
+ fun previous () = previous
239
+ fun changePrevious (node : Node <T >? = null) {
240
+ previous = node
205
241
}
206
- if (first == null ) {
207
- first = last
242
+
243
+ fun value () = value
244
+ fun changeValue (newValue : T ? ) {
245
+ value = newValue
208
246
}
209
- count ++
247
+
210
248
}
211
249
212
250
}
0 commit comments