DoublyLinkedList::deleteBeginning()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 13
Ratio 100 %

Importance

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