Completed
Push — master ( b96842...c6925e )
by Siro Díaz
01:44
created

SimpleLinkedList   C

Complexity

Total Complexity 56

Size/Duplication

Total Lines 339
Duplicated Lines 37.46 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 56
lcom 1
cbo 3
dl 127
loc 339
rs 6.5957
c 0
b 0
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A contains() 0 15 4
A indexOf() 19 19 4
A lastIndexOf() 19 19 4
B remove() 11 29 5
A __construct() 6 6 1
A get() 8 8 2
B search() 4 14 5
A getLast() 0 4 2
A searchLast() 12 12 3
A getAll() 11 11 3
A insertAt() 14 14 2
A insertEnd() 10 13 3
A insertBeginning() 9 9 2
C delete() 4 39 8
A deleteBeginning() 0 1 1
A deleteAt() 0 1 1
A deleteEnd() 0 1 1
A rewind() 0 4 1
A current() 0 3 1
A key() 0 3 1
A next() 0 4 1
A valid() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like SimpleLinkedList often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SimpleLinkedList, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * DataStructures for PHP
4
 *
5
 * @link      https://github.com/SiroDiaz/DataStructures
6
 * @copyright Copyright (c) 2017 Siro Díaz Palazón
7
 * @license   https://github.com/SiroDiaz/DataStructures/blob/master/README.md (MIT License)
8
 */
9
namespace DataStructures\Lists;
10
11
use DataStructures\Lists\Traits\{CountTrait, ArrayAccessTrait};
12
use DataStructures\Lists\Nodes\SimpleLinkedListNode;
13
use OutOfBoundsException;
14
use Iterator;
15
16
/**
17
 * SimpleLinkedList
18
 *
19
 * SimpleLinkedList is a singly linked list that has
20
 * a pointer to the next node but last node points to null.
21
 *
22
 * @author Siro Diaz Palazon <[email protected]>
23
 */
24
class SimpleLinkedList extends ListAbstract {
25
    use ArrayAccessTrait;
26
    
27
    protected $head;
28
    private $position;
29
    private $current;
30
31 View Code Duplication
    public function __construct() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
32
        $this->head = null;
33
        $this->size = 0;
34
        $this->position = 0;
35
        $this->current = &$this->head;
36
    }
37
38
    /**
39
     * Gets the data stored in the position especified.
40
     *
41
     * @param integer $index Index that must be greater than 0
42
     *  and lower than the list size.
43
     * @return mixed The data stored in the given index
44
     * @throws OutOfBoundsException if index is out bounds.
45
     */
46 View Code Duplication
    public function get($index) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
47
        $node = $this->search($index);
48
        if($node === null) {
49
            return null;
50
        }
51
52
        return $node->data;
53
    }
54
55
    /**
56
     * Returns the node stored in the given position.
57
     *
58
     * @param integer $index the position.
59
     * @throws OutOfBoundsException if it is out of limits (< 0 or > size - 1)
60
     * @return DataStructures\Lists\Nodes\SimpleLinkedListNode|null the node stored in $index.
61
     */
62
    protected function search($index) {
63
        if($index > $this->size - 1 || $index < 0) {
64
            throw new OutOfBoundsException();
65
        }
66
67
        $current = $this->head;
68
        $i = 0;
69 View Code Duplication
        while($i < $index && $current->next !== null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
70
            $current = $current->next;
71
            $i++;
72
        }
73
74
        return $current;
75
    }
76
77
    /**
78
     *
79
     */
80
    public function getLast() {
81
        $lastNode = $this->searchLast();
82
        return $lastNode === null ? null : $lastNode->data;
83
    }
84
85
    /**
86
     *
87
     */
88 View Code Duplication
    public function searchLast() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
89
        if($this->head === null) {
90
            return null;
91
        }
92
93
        $current = $this->head;
94
        while($current->next !== null) {
95
            $current = $current->next;
96
        }
97
98
        return $current;
99
    }
100
101
    /**
102
     * Generator for retrieve all nodes stored.
103
     * 
104
     * @return null if the head is null (or list is empty)
105
     */
106 View Code Duplication
    public function getAll() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
107
        if($this->head === null) {
108
            return;
109
        }
110
111
        $current = $this->head;
112
        while($current !== null) {
113
            yield $current->data;
114
            $current = $current->next;
115
        }
116
    }
117
118
    /**
119
     * {@inheritDoc}
120
     */
121
    public function contains($data) : bool {
122
        if($this->empty()) {
123
            return false;
124
        }
125
126
        $current = $this->head;
127
        while($current !== null) {
128
            if($current->data === $data) {
129
                return true;
130
            }
131
            $current = $current->next;
132
        }
133
134
        return false;
135
    }
136
137
    /**
138
     * {@inheritDoc}
139
     */
140 View Code Duplication
    public function indexOf($data) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
141
        if($this->head === null) {
142
            return false;
143
        }
144
        
145
        $current = $this->head;
146
        $i = 0;
147
        
148
        while($i < $this->size) {
149
            if($current->data === $data) {
150
                return $i;
151
            }
152
153
            $current = $current->next;
154
            $i++;
155
        }
156
157
        return false;
158
    }
159
160
    /**
161
     * {@inheritDoc}
162
     */
163 View Code Duplication
    public function lastIndexOf($data) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
        if($this->head === null) {
165
            return false;
166
        }
167
        
168
        $current = $this->head;
169
        $i = 0;
170
        $pos = false;
171
        while($i < $this->size) {
172
            if($current->data == $data) {
173
                $pos = $i;
174
            }
175
176
            $current = $current->next;
177
            $i++;
178
        }
179
180
        return $pos;
181
    }
182
183
    /**
184
     * {@inheritDoc}
185
     */
186
    public function remove($data) {
187
        $current = &$this->head;
188
        $prev = null;
189
        $i = 0;
190
        
191
        if($this->head === null) {
192
            return null;
193
        }
194
195
        if($this->head->data === $data) {
196
            $this->head = &$this->head->next;
197
            $this->size--;
198
            return $data;
199
        }
200
        
201 View Code Duplication
        while($i < $this->size) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
202
            if($current->data === $data) {
203
                $prev->next = &$current->next;
204
                $this->size--;
205
206
                return $data;
207
            }
208
209
            $prev = $current;
210
            $current = $current->next;
211
        }
212
213
        return null;
214
    }
215
216
    /**
217
     * Add a new node in the specified index.
218
     *
219
     * @param integer $index the position.
220
     * @param mixed $data the data to be stored.
221
     */
222 View Code Duplication
    protected function insertAt($index, $data) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
223
        $newNode = new SimpleLinkedListNode($data);
224
        $current = $this->head;
225
        $prev = null;
226
        $i = 0;
227
        while($i < $index) {
228
            $prev = $current;
229
            $current = $current->next;
230
            $i++;
231
        }
232
        
233
        $prev->next = &$newNode;
234
        $newNode->next = &$current;
235
    }
236
237
    protected function insertEnd($data) {
238
        $newNode = new SimpleLinkedListNode($data);
239 View Code Duplication
        if($this->head === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
240
            $this->head = &$newNode;
241
            $this->current = &$this->head;
242
        } else {
243
            $current = $this->head;
244
            while($current->next !== null) {
245
                $current = $current->next;
246
            }
247
            $current->next = &$newNode;
248
        }
249
    }
250
251
    /**
252
     * {@inheritDoc}
253
     */
254 View Code Duplication
    protected function insertBeginning($data) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
255
        $newNode = new SimpleLinkedListNode($data);
256
        if($this->head === null) {
257
            $this->head = &$newNode;
258
        } else {
259
            $newNode->next = $this->head;
260
            $this->head = &$newNode;
261
        }
262
    }
263
264
    /**
265
     * Delete a node in the given position and returns it back.
266
     *
267
     * @param integer $index the position.
268
     * @throws OutOfBoundsException if index is negative
269
     *  or is greater than the size of the list.
270
     */
271
    public function delete($index) {
272
        if($index < 0) {
273
            throw new OutOfBoundsException();
274
        }
275
        if($this->head === null) {
276
            return null;
277
        }
278
279
        if($index >= $this->size) {
280
            return null;    // It should return an exception
281
        }
282
283
        if($index === 0) {
284
            $node = $this->head;
285
            $this->head = $this->head->next;
286
            $this->current = &$this->head;
287
            $this->size--;
288
            return $node->data;
289
        }
290
        
291
        $i = 0;
292
        $current = $this->head;
293
        $prev = $current;
294 View Code Duplication
        while($i < $index && $current->next !== null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
295
            $prev = $current;
296
            $current = $current->next;
297
        }
298
299
        if($index === $this->size - 1) {
300
            $prev->next = null;
301
            $this->size--;
302
            return $current->data;
303
        } else {
304
            $prev->next = $current->next;
305
        }
306
        $this->size--;
307
308
        return $prev->data;
309
    }
310
311
    protected function deleteBeginning() {}
312
313
    protected function deleteAt($index) {}
314
315
    protected function deleteEnd() {}
316
317
    
318
319
    /**
320
     * Reset the cursor position.
321
     */
322
    public function rewind() {
323
        $this->position = 0;
324
        $this->current = $this->head;
325
    }
326
327
    /**
328
     * Returns the current node data.
329
     *
330
     * @return mixed
331
     */
332
    public function current() {
333
        return $this->current->data;
334
    }
335
336
    /**
337
     * Key or index that indicates the cursor position.
338
     *
339
     * @return integer The current position.
340
     */
341
    public function key() {
342
        return $this->position;
343
    }
344
345
    /**
346
     * Move the cursor to the next node and increments the
347
     * position counter.
348
     */
349
    public function next() {
350
        ++$this->position;
351
        $this->current = $this->current->next;
352
    }
353
354
    /**
355
     * Returns if the current pointer position is valid.
356
     *
357
     * @return boolean true if pointer is not last, else false.
358
     */
359
    public function valid() {
360
        return $this->current !== null;
361
    }
362
}