Completed
Push — master ( bb3a8c...43409a )
by Siro Díaz
01:31
created

SimpleLinkedList   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 310
Duplicated Lines 38.39 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 52
lcom 1
cbo 3
dl 119
loc 310
rs 7.9487
c 0
b 0
f 0

20 Methods

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