Completed
Push — master ( c6925e...1b130f )
by Siro Díaz
01:40
created

SimpleLinkedList   B

Complexity

Total Complexity 54

Size/Duplication

Total Lines 318
Duplicated Lines 37.42 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 54
lcom 1
cbo 3
dl 119
loc 318
rs 7.0642
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 6 6 1
B search() 4 14 5
A getLast() 0 4 2
A searchLast() 12 12 3
A getAll() 11 11 3
A contains() 0 15 4
A indexOf() 19 19 4
A lastIndexOf() 19 19 4
B remove() 11 29 5
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
     * {@inheritDoc}
40
     */
41
    protected function search($index) {
42
        if($index > $this->size - 1 || $index < 0) {
43
            throw new OutOfBoundsException();
44
        }
45
46
        $current = $this->head;
47
        $i = 0;
48 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...
49
            $current = $current->next;
50
            $i++;
51
        }
52
53
        return $current;
54
    }
55
56
    /**
57
     *
58
     */
59
    public function getLast() {
60
        $lastNode = $this->searchLast();
61
        return $lastNode === null ? null : $lastNode->data;
62
    }
63
64
    /**
65
     *
66
     */
67 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...
68
        if($this->head === null) {
69
            return null;
70
        }
71
72
        $current = $this->head;
73
        while($current->next !== null) {
74
            $current = $current->next;
75
        }
76
77
        return $current;
78
    }
79
80
    /**
81
     * Generator for retrieve all nodes stored.
82
     * 
83
     * @return null if the head is null (or list is empty)
84
     */
85 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...
86
        if($this->head === null) {
87
            return;
88
        }
89
90
        $current = $this->head;
91
        while($current !== null) {
92
            yield $current->data;
93
            $current = $current->next;
94
        }
95
    }
96
97
    /**
98
     * {@inheritDoc}
99
     */
100
    public function contains($data) : bool {
101
        if($this->empty()) {
102
            return false;
103
        }
104
105
        $current = $this->head;
106
        while($current !== null) {
107
            if($current->data === $data) {
108
                return true;
109
            }
110
            $current = $current->next;
111
        }
112
113
        return false;
114
    }
115
116
    /**
117
     * {@inheritDoc}
118
     */
119 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...
120
        if($this->head === null) {
121
            return false;
122
        }
123
        
124
        $current = $this->head;
125
        $i = 0;
126
        
127
        while($i < $this->size) {
128
            if($current->data === $data) {
129
                return $i;
130
            }
131
132
            $current = $current->next;
133
            $i++;
134
        }
135
136
        return false;
137
    }
138
139
    /**
140
     * {@inheritDoc}
141
     */
142 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...
143
        if($this->head === null) {
144
            return false;
145
        }
146
        
147
        $current = $this->head;
148
        $i = 0;
149
        $pos = false;
150
        while($i < $this->size) {
151
            if($current->data == $data) {
152
                $pos = $i;
153
            }
154
155
            $current = $current->next;
156
            $i++;
157
        }
158
159
        return $pos;
160
    }
161
162
    /**
163
     * {@inheritDoc}
164
     */
165
    public function remove($data) {
166
        $current = &$this->head;
167
        $prev = null;
168
        $i = 0;
169
        
170
        if($this->head === null) {
171
            return null;
172
        }
173
174
        if($this->head->data === $data) {
175
            $this->head = &$this->head->next;
176
            $this->size--;
177
            return $data;
178
        }
179
        
180 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...
181
            if($current->data === $data) {
182
                $prev->next = &$current->next;
183
                $this->size--;
184
185
                return $data;
186
            }
187
188
            $prev = $current;
189
            $current = $current->next;
190
        }
191
192
        return null;
193
    }
194
195
    /**
196
     * Add a new node in the specified index.
197
     *
198
     * @param integer $index the position.
199
     * @param mixed $data the data to be stored.
200
     */
201 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...
202
        $newNode = new SimpleLinkedListNode($data);
203
        $current = $this->head;
204
        $prev = null;
205
        $i = 0;
206
        while($i < $index) {
207
            $prev = $current;
208
            $current = $current->next;
209
            $i++;
210
        }
211
        
212
        $prev->next = &$newNode;
213
        $newNode->next = &$current;
214
    }
215
216
    protected function insertEnd($data) {
217
        $newNode = new SimpleLinkedListNode($data);
218 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...
219
            $this->head = &$newNode;
220
            $this->current = &$this->head;
221
        } else {
222
            $current = $this->head;
223
            while($current->next !== null) {
224
                $current = $current->next;
225
            }
226
            $current->next = &$newNode;
227
        }
228
    }
229
230
    /**
231
     * {@inheritDoc}
232
     */
233 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...
234
        $newNode = new SimpleLinkedListNode($data);
235
        if($this->head === null) {
236
            $this->head = &$newNode;
237
        } else {
238
            $newNode->next = $this->head;
239
            $this->head = &$newNode;
240
        }
241
    }
242
243
    /**
244
     * Delete a node in the given position and returns it back.
245
     *
246
     * @param integer $index the position.
247
     * @throws OutOfBoundsException if index is negative
248
     *  or is greater than the size of the list.
249
     */
250
    public function delete($index) {
251
        if($index < 0) {
252
            throw new OutOfBoundsException();
253
        }
254
        if($this->head === null) {
255
            return null;
256
        }
257
258
        if($index >= $this->size) {
259
            return null;    // It should return an exception
260
        }
261
262
        if($index === 0) {
263
            $node = $this->head;
264
            $this->head = $this->head->next;
265
            $this->current = &$this->head;
266
            $this->size--;
267
            return $node->data;
268
        }
269
        
270
        $i = 0;
271
        $current = $this->head;
272
        $prev = $current;
273 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...
274
            $prev = $current;
275
            $current = $current->next;
276
        }
277
278
        if($index === $this->size - 1) {
279
            $prev->next = null;
280
            $this->size--;
281
            return $current->data;
282
        } else {
283
            $prev->next = $current->next;
284
        }
285
        $this->size--;
286
287
        return $prev->data;
288
    }
289
290
    protected function deleteBeginning() {}
291
292
    protected function deleteAt($index) {}
293
294
    protected function deleteEnd() {}
295
296
    
297
298
    /**
299
     * Reset the cursor position.
300
     */
301
    public function rewind() {
302
        $this->position = 0;
303
        $this->current = $this->head;
304
    }
305
306
    /**
307
     * Returns the current node data.
308
     *
309
     * @return mixed
310
     */
311
    public function current() {
312
        return $this->current->data;
313
    }
314
315
    /**
316
     * Key or index that indicates the cursor position.
317
     *
318
     * @return integer The current position.
319
     */
320
    public function key() {
321
        return $this->position;
322
    }
323
324
    /**
325
     * Move the cursor to the next node and increments the
326
     * position counter.
327
     */
328
    public function next() {
329
        ++$this->position;
330
        $this->current = $this->current->next;
331
    }
332
333
    /**
334
     * Returns if the current pointer position is valid.
335
     *
336
     * @return boolean true if pointer is not last, else false.
337
     */
338
    public function valid() {
339
        return $this->current !== null;
340
    }
341
}