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

CircularLinkedList::get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 8
Ratio 100 %

Importance

Changes 0
Metric Value
dl 8
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
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 DataStructures\Lists\ListAbstract;
14
use OutOfBoundsException;
15
16
/**
17
 * CircularLinkedList
18
 *
19
 * CircularLinkedList is a single and circular linked list that has
20
 * a pointer to the next node and also and last node points to head.
21
 *
22
 * @author Siro Diaz Palazon <[email protected]>
23
 */
24
class CircularLinkedList extends ListAbstract {
25
    use ArrayAccessTrait;
26
    protected $head;
27
    private $tail;
28
    private $current;
29
    private $position;
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->tail = &$this->head;
34
        $this->size = 0;
35
        $this->position = 0;
36
        $this->current = &$this->head;
37
    }
38
39
    
40
    /**
41
     * Inserts at the beginning of the list.
42
     *
43
     * @param mixed $data
44
     */
45
    protected function insertBeginning($data) {
46
        $newNode = new SimpleLinkedListNode($data);
47
        if($this->head === null) {
48
            $newNode->next = &$this->head;
49
            $this->head = &$newNode;
50
            $this->tail = &$newNode;
51
        } else {
52
            $this->tail->next = &$newNode;
53
            $newNode->next = $this->head;
54
            $this->head = &$newNode;
55
        }
56
    }
57
58
    /**
59
     * Add a new node in the specified index.
60
     *
61
     * @param integer $index the position.
0 ignored issues
show
Bug introduced by
There is no parameter named $index. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
62
     * @param mixed $data the data to be stored.
63
     */
64 View Code Duplication
    protected function insertEnd($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...
65
        $newNode = new SimpleLinkedListNode($data);
66
        $this->tail->next = &$newNode;
67
        $newNode->next = &$this->head;
68
        $this->tail = &$newNode;
69
    }
70
71
    /**
72
     * Add a new node in the specified index.
73
     *
74
     * @param integer $index the position.
75
     * @param mixed $data the data to be stored.
76
     */
77 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...
78
        $newNode = new SimpleLinkedListNode($data);
79
        $current = $this->head;
80
        $prev = null;
81
        $i = 0;
82
        while($i < $index) {
83
            $prev = $current;
84
            $current = $current->next;
85
            $i++;
86
        }
87
        
88
        $prev->next = &$newNode;
89
        $newNode->next = &$current;
90
    }
91
92
    /**
93
     * Returns the last node data with O(1).
94
     *
95
     * @return mixed null if the list is empty.
96
     */
97
    public function getLast() {
98
        $node = $this->searchLast();
99
100
        return $node !== null ? $node->data : null;
101
    }
102
103
    /**
104
     * Returns the last node with O(1).
105
     *
106
     * @return mixed null if the list is empty.
107
     */
108
    protected function searchLast() {
109
        if($this->head === null) {
110
            return null;
111
        }
112
113
        return $this->tail;
114
    }
115
116
    /**
117
     * Returns the node stored in the given position.
118
     * If index is 0 or (size - 1) the method is O(1) else O(n).
119
     *
120
     * @param integer $index the position.
121
     * @throws OutOfBoundsException if it is out of limits (< 0 or > size - 1)
122
     * @return DataStructures\Lists\Nodes\SimpleLinkedListNode the node stored in $index.
123
     */
124
    protected function search($index) {
125
        if($index < 0 || $index > $this->size - 1) {
126
            throw new OutOfBoundsException();
127
        }
128
129
        if($index === 0) {
130
            return $this->head;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->head; of type null|DataStructures\List...es\SimpleLinkedListNode adds the type DataStructures\Lists\Nodes\SimpleLinkedListNode to the return on line 130 which is incompatible with the return type declared by the abstract method DataStructures\Lists\ListAbstract::search of type DataStructures\Lists\Dat...ublyLinkedListNode|null.
Loading history...
131
        }
132
133
        if($index === $this->size - 1) {
134
            return $this->searchLast();
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->searchLast(); of type null|DataStructures\List...es\SimpleLinkedListNode adds the type DataStructures\Lists\Nodes\SimpleLinkedListNode to the return on line 134 which is incompatible with the return type declared by the abstract method DataStructures\Lists\ListAbstract::search of type DataStructures\Lists\Dat...ublyLinkedListNode|null.
Loading history...
135
        }
136
137
        $i = 0;
138
        $current = $this->head;
139
        while($i < $index) {
140
            $current = $current->next;
141
            $i++;
142
        }
143
144
        return $current;
145
    }
146
147
    /**
148
     * {@inheritDoc}
149
     */
150
    public function contains($data) : bool {
151
        if($this->size === 0) {
152
            return false;
153
        }
154
155
        $current = $this->head->next;
156
        $prev = $this->head;
157
        while($current !== $this->head) {
158
            if($prev->data === $data) {
159
                return true;
160
            }
161
            
162
            $prev = $current;
163
            $current = $current->next;
164
        }
165
166
        if($prev->data === $data) {
167
            return true;
168
        }
169
170
        return false;
171
    }
172
173
    /**
174
     * {@inheritDoc}
175
     */
176 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...
177
        if($this->head === null) {
178
            return false;
179
        }
180
        
181
        $current = $this->head;
182
        $i = 0;
183
        
184
        while($i < $this->size) {
185
            if($current->data === $data) {
186
                return $i;
187
            }
188
189
            $current = $current->next;
190
            $i++;
191
        }
192
193
        return false;
194
    }
195
196
    /**
197
     * {@inheritDoc}
198
     */
199 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...
200
        if($this->head === null) {
201
            return false;
202
        }
203
        
204
        $current = $this->head;
205
        $i = 0;
206
        $pos = false;
207
        while($i < $this->size) {
208
            if($current->data === $data) {
209
                $pos = $i;
210
            }
211
212
            $current = $current->next;
213
            $i++;
214
        }
215
        
216
        return $pos;
217
    }
218
219
    /**
220
     * {@inheritDoc}
221
     */
222
    public function remove($data) {
223
        $current = $this->head;
224
        $prev = $this->tail;
225
        $i = 0;
226
        
227
        if($this->head === null) {
228
            return null;
229
        }
230
231
        if($this->head->data === $data) {
232
            $this->head = &$this->head->next;
233
            $this->tail->next = &$this->head;
234
            $this->size--;
235
            return $current->data;
236
        }
237 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...
238
            if($prev->data === $data) {
239
                $prev->next = &$current->next;
240
                $this->size--;
241
242
                return $current->data;
243
            }
244
245
            $prev = $current;
246
            $current = $current->next;
247
        }
248
249
        return null;
250
    }
251
252
    /**
253
     * Generator for retrieve all nodes stored.
254
     * 
255
     * @return null if the head is null (or list is empty)
256
     */
257 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...
258
        if($this->head === null) {
259
            return;
260
        }
261
        
262
        if($this->head->next === $this->tail) {
263
            yield $this->head->data;
264
        } else {
265
            $current = $this->head;
266
            $i = 0;
267
            while($i < $this->size) {
268
                yield $current->data;
269
                $current = $current->next;
270
                $i++;
271
            }
272
        }
273
    }
274
275
    /**
276
     * {@inheritDoc}
277
     */
278 View Code Duplication
    protected function deleteBeginning() {
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...
279
        // if only there is an element
280
        if($this->head->next === $this->head) {
281
            $temp = $this->head;
282
            $this->head = null;
283
            return $temp->data;
284
        }
285
        
286
        $temp = $this->head;
287
        $this->head = &$this->head->next;
288
        $this->tail->next = &$this->head;
289
290
        return $temp->data;
291
    }
292
293
    /**
294
     * {@inheritDoc}
295
     */
296
    protected function deleteAt($index) {
297
        $i = 0;
298
        $prev = $this->head;
299
        $current = $this->head;
300
        
301
        while($i < $index) {
302
            $prev = $current;
303
            $current = $current->next;
304
            $i++;
305
        }
306
307
        $prev->next = &$current->next;
308
309
        return $current->data;
310
    }
311
312
    /**
313
     * {@inheritDoc}
314
     */
315 View Code Duplication
    protected function deleteEnd() {
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...
316
        $prev = $this->head;
317
        $current = $this->head;
318
        
319
        while($current !== $this->tail) {
320
            $prev = $current;
321
            $current = $current->next;
322
        }
323
        
324
        $temp = $current;
325
        $prev->next = &$this->head;
326
        $this->tail = &$prev;
327
        $current = null;
0 ignored issues
show
Unused Code introduced by
$current is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
328
329
        return $temp->data;
330
    }
331
332
    public function clear() {
333
        while($this->head !== null) {
334
            $this->shift();
335
        }
336
    }
337
338
    /**
339
     * Reset the cursor position.
340
     */
341
    public function rewind() {
342
        $this->position = 0;
343
        $this->current = &$this->head;
344
    }
345
346
    /**
347
     * Returns the current node data.
348
     *
349
     * @return mixed
350
     */
351
    public function current() {
352
        return $this->current->data;
353
    }
354
355
    /**
356
     * Key or index that indicates the cursor position.
357
     *
358
     * @return integer The current position.
359
     */
360
    public function key() {
361
        return $this->position;
362
    }
363
364
    /**
365
     * Move the cursor to the next node and increments the
366
     * position counter.
367
     */
368
    public function next() {
369
        ++$this->position;
370
        $this->current = $this->current->next;
371
    }
372
373
    /**
374
     * Returns if the current pointer position is valid.
375
     *
376
     * @return boolean true if pointer is not last, else false.
377
     */
378
    public function valid() {
379
        return $this->position < $this->size;
380
    }
381
}