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

DoublyLinkedList::next()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
eloc 3
nc 1
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\DoublyLinkedListNode;
13
use DataStructures\Lists\ListAbstract;
14
use OutOfBoundsException;
15
16
/**
17
 * DoublyLinkedList
18
 *
19
 * DoublyLinkedList is a double linked list that has
20
 * a pointer to the next and the previous node.
21
 *
22
 * @author Siro Diaz Palazon <[email protected]>
23
 */
24
class DoublyLinkedList extends ListAbstract {
25
    use ArrayAccessTrait;
26
27
    protected $head;
28
    private $tail;
29
    private $position;
30
    private $current;
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
     * Gets the node stored in the position especified.
42
     * If index is 0 or (size - 1) the method is O(1) else O(n).
43
     *
44
     * @param integer $index the position.
45
     * @throws OutOfBoundsException if it is out of limits (< 0 or > size - 1)
46
     * @return DataStructures\Lists\Nodes\DoublyLinkedListNode|null the node stored in $index.
47
     */
48
    protected function search($index) {
49
        if($index < 0 || $index > $this->size - 1) {
50
            throw new OutOfBoundsException();
51
        }
52
53
        if($index === 0) {
54
            return $this->head;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->head; of type null|DataStructures\List...es\DoublyLinkedListNode adds the type DataStructures\Lists\Nodes\DoublyLinkedListNode to the return on line 54 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...
55
        }
56
57
        if($index === $this->size - 1) {
58
            return $this->tail;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->tail; of type null|DataStructures\List...es\DoublyLinkedListNode adds the type DataStructures\Lists\Nodes\DoublyLinkedListNode to the return on line 58 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...
59
        }
60
61
        $current = &$this->head;
62
        if($index < (int) ceil($this->size / 2)) {
63
            $i = 0;
64
            while($i < $index) {
65
                $current = &$current->next;
66
                $i++;
67
            }    
68
        } else {
69
            $i = $this->size;
70
            while($i > $index) {
71
                $current = &$current->prev;
72
                $i--;
73
            }
74
        }
75
76
        return $current;
77
    }
78
79
    /**
80
     * Returns the last node with O(1).
81
     *
82
     * @return DataStructures\Lists\Nodes\DoublyLinkedListNode|null if the list is empty.
83
     */
84
    public function searchLast() {
85
        if($this->head === null) {
86
            return null;
87
        }
88
        return $this->tail;
89
    }
90
91
    /**
92
     * {@inheritDoc}
93
     */
94
    public function contains($data) : bool {
95
        if($this->empty()) {
96
            return false;
97
        }
98
99
        $current = $this->head->next;
100
        $prev = $this->head;
101
        while($current !== $this->head) {
102
            if($prev->data === $data) {
103
                return true;
104
            }
105
            $prev = $current;
106
            $current = $current->next;
107
        }
108
109
        return $prev->data === $data;
110
    }
111
112
    /**
113
     * {@inheritDoc}
114
     */
115 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...
116
        if($this->head === null) {
117
            return false;
118
        }
119
        
120
        $current = $this->head;
121
        $i = 0;
122
        
123
        while($i < $this->size) {
124
            if($current->data === $data) {
125
                return $i;
126
            }
127
128
            $current = $current->next;
129
            $i++;
130
        }
131
132
        return false;
133
    }
134
135
    /**
136
     * {@inheritDoc}
137
     */
138 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...
139
        if($this->head === null) {
140
            return false;
141
        }
142
        
143
        $current = $this->head;
144
        $i = 0;
145
        $pos = false;
146
        while($i < $this->size) {
147
            if($current->data == $data) {
148
                $pos = $i;
149
            }
150
151
            $current = $current->next;
152
            $i++;
153
        }
154
155
        return $pos;
156
    }
157
158
    /**
159
     * {@inheritDoc}
160
     */
161
    public function remove($data) {
162
        $current = &$this->head;
163
        $i = 0;
164
        
165
        if($this->head === null) {
166
            return null;
167
        }
168
169
        if($this->head->data === $data) {
170
            $this->head = &$this->head->next;
171
            $this->head->prev = &$this->tail;
172
            $this->size--;
173
            
174
            return $data;
175
        }
176
177 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...
178
            if($current->data === $data) {
179
                $current->prev = &$current->next;
180
                $current = null;
181
                $this->size--;
182
                return $data;
183
            }
184
185
            $current = $current->next;
186
        }
187
188
        return null;
189
    }
190
    
191
    /**
192
     * Generator for retrieve all nodes stored.
193
     * 
194
     * @return null if the head is null (or list is empty)
195
     */
196 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...
197
        if($this->head === null) {
198
            return;
199
        }
200
201
        if($this->head === $this->tail) {
202
            yield $this->head->data;
203
        } else {
204
            $current = $this->head;
205
            $i = 0;
206
            while($i < $this->size) {
207
                yield $current->data;
208
                $current = $current->next;
209
                $i++;
210
            }
211
        }
212
    }
213
214
    /**
215
     * {@inheritDoc}
216
     */
217
    protected function insertBeginning($data) {
218
        $newNode = new DoublyLinkedListNode($data);
219
        if($this->head === null) {
220
            $newNode->next = &$this->head;
221
            $newNode->prev = &$this->head;
222
            $this->head = &$newNode;
223
            $this->tail = &$newNode;
224
        } else {
225
            $this->tail->next = &$newNode;
226
            $newNode->next = &$this->head;
227
            $newNode->prev = &$this->tail;
228
            $this->head = &$newNode;
229
        }
230
    }
231
232
    protected function insertEnd($data) {
233
        $newNode = new DoublyLinkedListNode($data);
234
        $this->tail->next = &$newNode;
235
        $newNode->next = &$this->head;
236
        $newNode->prev = &$this->tail;
237
        $this->tail = &$newNode;
238
        $this->head->prev = &$newNode;
239
    }
240
241
    /**
242
     * Add a new node in the specified index.
243
     *
244
     * @param integer $index the position.
245
     * @param mixed $data the data to be stored.
246
     */
247
    protected function insertAt($index, $data) {
248
        $newNode = new DoublyLinkedListNode($data);
249
        $current = $this->head;
250
        $prev = null;
251
        $i = 0;
252
        while($i < $index) {
253
            $prev = $current;
254
            $current = $current->next;
255
            $i++;
256
        }
257
        
258
        $prev->next = &$newNode;
259
        $newNode->prev = &$prev;
260
        $newNode->next = &$current;
261
        $current->prev = &$newNode;
262
    }
263
264
    /**
265
     * Deletes at the beginnig of the list and returns the data stored.
266
     *
267
     * @return mixed the data stored in the node.
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
        } else {
275
            $temp = $this->head;
276
            $this->head = &$this->head->next;
277
            $this->tail->next = &$this->head;
278
            
279
        }
280
        return $temp->data;
281
    }
282
283
    /**
284
     * Deletes at the specified position and returns the data stored.
285
     *
286
     * @param integer $index the position.
287
     * @return mixed the data stored in the node.
288
     */
289
    protected function deleteAt($index) {
290
        $i = 0;
291
        $prev = $this->head;
292
        $current = $this->head;
293
        
294
        while($i < $index) {
295
            $prev = $current;
296
            $current = $current->next;
297
            $i++;
298
        }
299
300
        $temp = $current;
301
        $prev->next = &$current->next;
302
        $current->next->prev = &$pre;
0 ignored issues
show
Bug introduced by
The variable $pre does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
303
        $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...
304
305
        return $temp->data;
306
    }
307
308
    /**
309
     * Deletes at the end of the list and returns the data stored.
310
     *
311
     * @return mixed the data stored in the node.
312
     */
313 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...
314
        $prev = $this->head;
315
        $current = $this->head;
316
        
317
        while($current !== $this->tail) {
318
            $prev = $current;
319
            $current = $current->next;
320
        }
321
        
322
        $temp = $current;
323
        $prev->next = &$this->head;
324
        $this->head->prev = &$prev;
325
        $this->tail = &$prev;
326
        $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...
327
328
        return $temp->data;
329
    }
330
331
    /**
332
     * Reset the cursor position.
333
     */
334
    public function rewind() {
335
        $this->position = 0;
336
        $this->current = &$this->head;
337
    }
338
339
    /**
340
     * Returns the current node data.
341
     *
342
     * @return mixed
343
     */
344
    public function current() {
345
        return $this->current->data;
346
    }
347
348
    /**
349
     * Key or index that indicates the cursor position.
350
     *
351
     * @return integer The current position.
352
     */
353
    public function key() {
354
        return $this->position;
355
    }
356
357
    /**
358
     * Move the cursor to the next node and increments the
359
     * position counter.
360
     */
361
    public function next() {
362
        ++$this->position;
363
        $this->current = $this->current->next;
364
    }
365
366
    /**
367
     * Returns if the current pointer position is valid.
368
     *
369
     * @return boolean true if pointer is not last, else false.
370
     */
371
    public function valid() {
372
        return $this->position < $this->size;
373
    }
374
}