Completed
Push — master ( 9126fc...46289f )
by Siro Díaz
01:30
created

SimpleLinkedList::size()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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