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

CircularLinkedList::getLast()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 0
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 with O(1).
94
     *
95
     * @return mixed null if the list is empty.
96
     */
97
    protected function searchLast() {
98
        if($this->head === null) {
99
            return null;
100
        }
101
102
        return $this->tail;
103
    }
104
105
    /**
106
     * Returns the node stored in the given position.
107
     * If index is 0 or (size - 1) the method is O(1) else O(n).
108
     *
109
     * @param integer $index the position.
110
     * @throws OutOfBoundsException if it is out of limits (< 0 or > size - 1)
111
     * @return DataStructures\Lists\Nodes\SimpleLinkedListNode the node stored in $index.
112
     */
113
    protected function search($index) {
114
        if($index < 0 || $index > $this->size - 1) {
115
            throw new OutOfBoundsException();
116
        }
117
118
        if($index === 0) {
119
            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 119 which is incompatible with the return type declared by the abstract method DataStructures\Lists\ListAbstract::search of type DataStructures\Lists\Dat...mpleLinkedListNode|null.
Loading history...
120
        }
121
122
        if($index === $this->size - 1) {
123
            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 123 which is incompatible with the return type declared by the abstract method DataStructures\Lists\ListAbstract::search of type DataStructures\Lists\Dat...mpleLinkedListNode|null.
Loading history...
124
        }
125
126
        $i = 0;
127
        $current = $this->head;
128
        while($i < $index) {
129
            $current = $current->next;
130
            $i++;
131
        }
132
133
        return $current;
134
    }
135
136
    /**
137
     * {@inheritDoc}
138
     */
139
    public function contains($data) : bool {
140
        if($this->size === 0) {
141
            return false;
142
        }
143
144
        $current = $this->head->next;
145
        $prev = $this->head;
146
        while($current !== $this->head) {
147
            if($prev->data === $data) {
148
                return true;
149
            }
150
            
151
            $prev = $current;
152
            $current = $current->next;
153
        }
154
155
        if($prev->data === $data) {
156
            return true;
157
        }
158
159
        return false;
160
    }
161
162
    /**
163
     * {@inheritDoc}
164
     */
165 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...
166
        if($this->head === null) {
167
            return false;
168
        }
169
        
170
        $current = $this->head;
171
        $i = 0;
172
        
173
        while($i < $this->size) {
174
            if($current->data === $data) {
175
                return $i;
176
            }
177
178
            $current = $current->next;
179
            $i++;
180
        }
181
182
        return false;
183
    }
184
185
    /**
186
     * {@inheritDoc}
187
     */
188 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...
189
        if($this->head === null) {
190
            return false;
191
        }
192
        
193
        $current = $this->head;
194
        $i = 0;
195
        $pos = false;
196
        while($i < $this->size) {
197
            if($current->data === $data) {
198
                $pos = $i;
199
            }
200
201
            $current = $current->next;
202
            $i++;
203
        }
204
        
205
        return $pos;
206
    }
207
208
    /**
209
     * {@inheritDoc}
210
     */
211
    public function remove($data) {
212
        $current = $this->head;
213
        $prev = $this->tail;
214
        $i = 0;
215
        
216
        if($this->head === null) {
217
            return null;
218
        }
219
220
        if($this->head->data === $data) {
221
            $this->head = &$this->head->next;
222
            $this->tail->next = &$this->head;
223
            $this->size--;
224
            return $current->data;
225
        }
226 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...
227
            if($prev->data === $data) {
228
                $prev->next = &$current->next;
229
                $this->size--;
230
231
                return $current->data;
232
            }
233
234
            $prev = $current;
235
            $current = $current->next;
236
        }
237
238
        return null;
239
    }
240
241
    /**
242
     * Generator for retrieve all nodes stored.
243
     * 
244
     * @return null if the head is null (or list is empty)
245
     */
246 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...
247
        if($this->head === null) {
248
            return;
249
        }
250
        
251
        if($this->head->next === $this->tail) {
252
            yield $this->head->data;
253
        } else {
254
            $current = $this->head;
255
            $i = 0;
256
            while($i < $this->size) {
257
                yield $current->data;
258
                $current = $current->next;
259
                $i++;
260
            }
261
        }
262
    }
263
264
    /**
265
     * {@inheritDoc}
266
     */
267 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...
268
        // if only there is an element
269
        if($this->head->next === $this->head) {
270
            $temp = $this->head;
271
            $this->head = null;
272
            return $temp->data;
273
        }
274
        
275
        $temp = $this->head;
276
        $this->head = &$this->head->next;
277
        $this->tail->next = &$this->head;
278
279
        return $temp->data;
280
    }
281
282
    /**
283
     * {@inheritDoc}
284
     */
285
    protected function deleteAt($index) {
286
        $i = 0;
287
        $prev = $this->head;
288
        $current = $this->head;
289
        
290
        while($i < $index) {
291
            $prev = $current;
292
            $current = $current->next;
293
            $i++;
294
        }
295
296
        $prev->next = &$current->next;
297
298
        return $current->data;
299
    }
300
301
    /**
302
     * {@inheritDoc}
303
     */
304 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...
305
        $prev = $this->head;
306
        $current = $this->head;
307
        
308
        while($current !== $this->tail) {
309
            $prev = $current;
310
            $current = $current->next;
311
        }
312
        
313
        $temp = $current;
314
        $prev->next = &$this->head;
315
        $this->tail = &$prev;
316
        $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...
317
318
        return $temp->data;
319
    }
320
321
    public function clear() {
322
        while($this->head !== null) {
323
            $this->shift();
324
        }
325
    }
326
327
    /**
328
     * Reset the cursor position.
329
     */
330
    public function rewind() {
331
        $this->position = 0;
332
        $this->current = &$this->head;
333
    }
334
335
    /**
336
     * Returns the current node data.
337
     *
338
     * @return mixed
339
     */
340
    public function current() {
341
        return $this->current->data;
342
    }
343
344
    /**
345
     * Key or index that indicates the cursor position.
346
     *
347
     * @return integer The current position.
348
     */
349
    public function key() {
350
        return $this->position;
351
    }
352
353
    /**
354
     * Move the cursor to the next node and increments the
355
     * position counter.
356
     */
357
    public function next() {
358
        ++$this->position;
359
        $this->current = $this->current->next;
360
    }
361
362
    /**
363
     * Returns if the current pointer position is valid.
364
     *
365
     * @return boolean true if pointer is not last, else false.
366
     */
367
    public function valid() {
368
        return $this->position < $this->size;
369
    }
370
}