Completed
Push — master ( 8863d6...f6a034 )
by Siro Díaz
01:40
created

SimpleLinkedList::indexOf()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 11

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 11
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
     * Insert a node in the specified list position.
162
     *
163
     * @param integer $index position
164
     * @param mixed $data data to be saved
165
     */
166
    public function insert($index, $data) {
167
        if($this->head === null) {
168
            return $this->push($data);
169
        }
170
171
        $newNode = new Node($data);
172
        if($index === 0) {
173
            $aux = $this->head;
174
            $this->head = &$newNode;
175
            $newNode->next = &$aux;
176
            $this->current = $this->head;
177
        } else {
178
            $i = 0;
179
            $current = $this->head;
180
            $prev = $current;
181 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...
182
                $prev = $current;
183
                $current = $current->next;
184
                $i++;
185
            }
186
187
            $prev->next = &$newNode;
188
            $newNode->next = &$current;
189
        }
190
191
        $this->size++;
192
    }
193
194
    /**
195
     * Delete a node in the given position and returns it back.
196
     *
197
     * @param integer $index the position.
198
     * @throws OutOfBoundsException if index is negative
199
     *  or is greater than the size of the list.
200
     */
201
    public function delete($index) {
202
        if($index < 0) {
203
            throw new OutOfBoundsException();
204
        }
205
        if($this->head === null) {
206
            return null;
207
        }
208
209
        if($index >= $this->size) {
210
            return null;    // It should return an exception
211
        }
212
213
        if($index === 0) {
214
            $node = $this->head;
215
            $this->head = $this->head->next;
216
            $this->current = &$this->head;
217
            $this->size--;
218
            return $node->data;
219
        }
220
        
221
        $i = 0;
222
        $current = $this->head;
223
        $prev = $current;
224 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...
225
            $prev = $current;
226
            $current = $current->next;
227
        }
228
229
        if($index === $this->size - 1) {
230
            $prev->next = null;
231
            $this->size--;
232
            return $current->data;
233
        } else {
234
            $prev->next = $current->next;
235
        }
236
        $this->size--;
237
238
        return $prev->data;
239
    }
240
241
    /**
242
     * Removes and returns the last node in the list.
243
     *
244
     * @return mixed data in node.
245
     */
246
    public function pop() {
247
        return $this->delete($this->size - 1);
248
    }
249
250
    /**
251
     * Remove all nodes of the list using shift.
252
     */
253
    public function clear() {
254
        while($this->head !== null) {
255
            $this->shift();
256
        }
257
    }
258
259
    /**
260
     * Converts/exports the list content into array type.
261
     *
262
     * @return array data stored in all nodes.
263
     */
264
    public function toArray() : array {
265
        $arr = [];
266
        foreach($this->getAll() as $node) {
267
            $arr[] = $node;
268
        }
269
270
        return $arr;
271
    }
272
273
    /**
274
     * Adds at the beginning a node in the list.
275
     *
276
     * @param mixed $data
277
     * @return mixed the data stored.
278
     */
279
    public function unshift($data) {
280
        $this->insert(0, $data);
281
    }
282
283
    /**
284
     * Deletes the first node of the list and returns it.
285
     *
286
     * @return mixed the data.
287
     */
288
    public function shift() {
289
        return $this->delete(0);
290
    }
291
292
    /**
293
     * Reset the cursor position.
294
     */
295
    public function rewind() {
296
        $this->position = 0;
297
        $this->current = $this->head;
298
    }
299
300
    /**
301
     * Returns the current node data.
302
     *
303
     * @return mixed
304
     */
305
    public function current() {
306
        return $this->current->data;
307
    }
308
309
    /**
310
     * Key or index that indicates the cursor position.
311
     *
312
     * @return integer The current position.
313
     */
314
    public function key() {
315
        return $this->position;
316
    }
317
318
    /**
319
     * Move the cursor to the next node and increments the
320
     * position counter.
321
     */
322
    public function next() {
323
        ++$this->position;
324
        $this->current = $this->current->next;
325
    }
326
327
    /**
328
     * Returns if the current pointer position is valid.
329
     *
330
     * @return boolean true if pointer is not last, else false.
331
     */
332
    public function valid() {
333
        return $this->current !== null;
334
    }
335
336
    /**
337
     * Binds to count() method. This is equal to make $this->tree->size().
338
     *
339
     * @return integer the tree size. 0 if it is empty.
340
     */
341
    public function count() {
342
        return $this->size;
343
    }
344
345
    /**
346
     * Returns the array size.
347
     *
348
     * @return int the length
349
     */
350
    public function size() : int {
351
        return $this->size;
352
    }
353
354
    /**
355
     * Checks if the list is empty.
356
     *
357
     * @return boolean true if is empty, else false.
358
     */
359
    public function empty() : bool {
360
        return $this->size === 0;
361
    }
362
}