Completed
Push — master ( f6a034...2cb83b )
by Siro Díaz
01:26
created

SimpleLinkedList::lastIndexOf()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 12

Duplication

Lines 19
Ratio 100 %

Importance

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