CircularLinkedList::search()   B
last analyzed

Complexity

Conditions 6
Paths 5

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 8.6737
c 0
b 0
f 0
cc 6
eloc 13
nc 5
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\SinglyLinkedListNode;
13
use DataStructures\Lists\ListAbstract;
14
use DataStructures\Exceptions\NotFoundException;
15
use OutOfBoundsException;
16
17
/**
18
 * CircularLinkedList
19
 *
20
 * CircularLinkedList is a single and circular linked list that has
21
 * a pointer to the next node and also and last node points to head.
22
 *
23
 * @author Siro Diaz Palazon <[email protected]>
24
 */
25
class CircularLinkedList extends ListAbstract {
26
    use ArrayAccessTrait;
27
    protected $head;
28
    private $tail;
29
    private $current;
30
    private $position;
31
32 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...
33
        $this->head = null;
34
        $this->tail = &$this->head;
35
        $this->size = 0;
36
        $this->position = 0;
37
        $this->current = &$this->head;
38
    }
39
40
    
41
    /**
42
     * Inserts at the beginning of the list.
43
     *
44
     * @param mixed $data
45
     */
46
    protected function insertBeginning($data) {
47
        $newNode = new SinglyLinkedListNode($data);
48
        if($this->head === null) {
49
            $newNode->next = &$this->head;
50
            $this->head = &$newNode;
51
            $this->tail = &$newNode;
52
        } else {
53
            $this->tail->next = &$newNode;
54
            $newNode->next = $this->head;
55
            $this->head = &$newNode;
56
        }
57
    }
58
59
    /**
60
     * Add a new node in the specified index.
61
     *
62
     * @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...
63
     * @param mixed $data the data to be stored.
64
     */
65 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...
66
        $newNode = new SinglyLinkedListNode($data);
67
        $this->tail->next = &$newNode;
68
        $newNode->next = &$this->head;
69
        $this->tail = &$newNode;
70
    }
71
72
    /**
73
     * Add a new node in the specified index.
74
     *
75
     * @param integer $index the position.
76
     * @param mixed $data the data to be stored.
77
     */
78 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...
79
        $newNode = new SinglyLinkedListNode($data);
80
        $current = $this->head;
81
        $prev = null;
82
        $i = 0;
83
        while($i < $index) {
84
            $prev = $current;
85
            $current = $current->next;
86
            $i++;
87
        }
88
        
89
        $prev->next = &$newNode;
90
        $newNode->next = &$current;
91
    }
92
93
    /**
94
     * Returns the last node with O(1).
95
     *
96
     * @return mixed null if the list is empty.
97
     */
98
    protected function searchLast() {
99
        if($this->head === null) {
100
            return null;
101
        }
102
103
        return $this->tail;
104
    }
105
106
    /**
107
     * Returns the node stored in the given position.
108
     * If index is 0 or (size - 1) the method is O(1) else O(n).
109
     *
110
     * @param integer $index the position.
111
     * @throws OutOfBoundsException if it is out of limits (< 0 or > size - 1)
112
     * @return DataStructures\Lists\Nodes\SinglyLinkedListNode the node stored in $index.
113
     */
114
    protected function search($index) {
115
        if($index < 0 || $index > $this->size - 1) {
116
            throw new OutOfBoundsException();
117
        }
118
119
        if($index === 0) {
120
            return $this->head;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->head; of type null|DataStructures\List...es\SinglyLinkedListNode adds the type DataStructures\Lists\Nodes\SinglyLinkedListNode to the return on line 120 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...
121
        }
122
123
        if($index === $this->size - 1) {
124
            return $this->searchLast();
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->searchLast(); of type null|DataStructures\List...es\SinglyLinkedListNode adds the type DataStructures\Lists\Nodes\SinglyLinkedListNode to the return on line 124 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...
125
        }
126
127
        $i = 0;
128
        $current = $this->head;
129
        while($i < $index) {
130
            $current = $current->next;
131
            $i++;
132
        }
133
134
        return $current;
135
    }
136
137
    /**
138
     * {@inheritDoc}
139
     */
140
    public function contains($data) : bool {
141
        if($this->size === 0) {
142
            return false;
143
        }
144
145
        $current = $this->head->next;
146
        $prev = $this->head;
147
        while($current !== $this->head) {
148
            if($prev->data === $data) {
149
                return true;
150
            }
151
            
152
            $prev = $current;
153
            $current = $current->next;
154
        }
155
156
        if($prev->data === $data) {
157
            return true;
158
        }
159
160
        return false;
161
    }
162
163
    /**
164
     * {@inheritDoc}
165
     */
166 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...
167
        if($this->head === null) {
168
            return false;
169
        }
170
        
171
        $current = $this->head;
172
        $i = 0;
173
        
174
        while($i < $this->size) {
175
            if($current->data === $data) {
176
                return $i;
177
            }
178
179
            $current = $current->next;
180
            $i++;
181
        }
182
183
        return false;
184
    }
185
186
    /**
187
     * {@inheritDoc}
188
     */
189 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...
190
        if($this->head === null) {
191
            return false;
192
        }
193
        
194
        $current = $this->head;
195
        $i = 0;
196
        $pos = false;
197
        while($i < $this->size) {
198
            if($current->data === $data) {
199
                $pos = $i;
200
            }
201
202
            $current = $current->next;
203
            $i++;
204
        }
205
        
206
        return $pos;
207
    }
208
209
    /**
210
     * {@inheritDoc}
211
     */
212
    public function remove($data) {
213
        $current = $this->head;
214
        $prev = $this->tail;
215
        $i = 0;
216
        
217
        if($this->head === null) {
218
            throw new NotFoundException();
219
        }
220
221
        if($this->head->data === $data) {
222
            $this->head = &$this->head->next;
223
            $this->tail->next = &$this->head;
224
            $this->size--;
225
            return $current->data;
226
        }
227
228 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...
229
            if($prev->data === $data) {
230
                $prev->next = &$current->next;
231
                $this->size--;
232
233
                return $current->data;
234
            }
235
236
            $prev = $current;
237
            $current = $current->next;
238
        }
239
240
        throw new NotFoundException();
241
    }
242
243
    /**
244
     * Generator for retrieve all nodes stored.
245
     * 
246
     * @return null if the head is null (or list is empty)
247
     */
248 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...
249
        if($this->head === null) {
250
            return;
251
        }
252
        
253
        if($this->head->next === $this->tail) {
254
            yield $this->head->data;
255
        } else {
256
            $current = $this->head;
257
            $i = 0;
258
            while($i < $this->size) {
259
                yield $current->data;
260
                $current = $current->next;
261
                $i++;
262
            }
263
        }
264
    }
265
266
    /**
267
     * {@inheritDoc}
268
     */
269 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...
270
        // if only there is an element
271
        if($this->head->next === $this->head) {
272
            $temp = $this->head;
273
            $this->head = null;
274
            return $temp->data;
275
        }
276
        
277
        $temp = $this->head;
278
        $this->head = &$this->head->next;
279
        $this->tail->next = &$this->head;
280
281
        return $temp->data;
282
    }
283
284
    /**
285
     * {@inheritDoc}
286
     */
287
    protected function deleteAt($index) {
288
        $i = 0;
289
        $prev = $this->head;
290
        $current = $this->head;
291
        
292
        while($i < $index) {
293
            $prev = $current;
294
            $current = $current->next;
295
            $i++;
296
        }
297
298
        $prev->next = &$current->next;
299
300
        return $current->data;
301
    }
302
303
    /**
304
     * {@inheritDoc}
305
     */
306 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...
307
        $prev = $this->head;
308
        $current = $this->head;
309
        
310
        while($current !== $this->tail) {
311
            $prev = $current;
312
            $current = $current->next;
313
        }
314
        
315
        $temp = $current;
316
        $prev->next = &$this->head;
317
        $this->tail = &$prev;
318
        $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...
319
320
        return $temp->data;
321
    }
322
323
    public function clear() {
324
        while($this->head !== null) {
325
            $this->shift();
326
        }
327
    }
328
329
    /**
330
     * Reset the cursor position.
331
     */
332
    public function rewind() {
333
        $this->position = 0;
334
        $this->current = &$this->head;
335
    }
336
337
    /**
338
     * Returns the current node data.
339
     *
340
     * @return mixed
341
     */
342
    public function current() {
343
        return $this->current->data;
344
    }
345
346
    /**
347
     * Key or index that indicates the cursor position.
348
     *
349
     * @return integer The current position.
350
     */
351
    public function key() {
352
        return $this->position;
353
    }
354
355
    /**
356
     * Move the cursor to the next node and increments the
357
     * position counter.
358
     */
359
    public function next() {
360
        ++$this->position;
361
        $this->current = $this->current->next;
362
    }
363
364
    /**
365
     * Returns if the current pointer position is valid.
366
     *
367
     * @return boolean true if pointer is not last, else false.
368
     */
369
    public function valid() {
370
        return $this->position < $this->size;
371
    }
372
}