Completed
Push — master ( bca99a...ce603c )
by Siro Díaz
01:43
created

SimpleLinkedList::contains()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.2
c 0
b 0
f 0
cc 4
eloc 9
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 CountTrait, 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
     * Insert a node in the specified list position.
139
     *
140
     * @param integer $index position
141
     * @param mixed $data data to be saved
142
     */
143
    public function insert($index, $data) {
144
        if($this->head === null) {
145
            return $this->push($data);
146
        }
147
148
        $newNode = new Node($data);
149
        if($index === 0) {
150
            $aux = $this->head;
151
            $this->head = &$newNode;
152
            $newNode->next = &$aux;
153
            $this->current = &$this->head;
154
        } else {
155
            $i = 0;
156
            $current = $this->head;
157
            $prev = $current;
158 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...
159
                $prev = $current;
160
                $current = $current->next;
161
                $i++;
162
            }
163
164
            $prev->next = &$newNode;
165
            $newNode->next = &$current;
166
        }
167
168
        $this->size++;
169
    }
170
171
    /**
172
     * Delete a node in the given position and returns it back.
173
     *
174
     * @param integer $index the position.
175
     * @throws OutOfBoundsException if index is negative
176
     *  or is greater than the size of the list.
177
     */
178
    public function delete($index) {
179
        if($index < 0) {
180
            throw new OutOfBoundsException();
181
        }
182
        if($this->head === null) {
183
            return null;
184
        }
185
186
        if($index >= $this->size) {
187
            return null;    // It should return an exception
188
        }
189
190
        if($index === 0) {
191
            $node = $this->head;
192
            $this->head = $this->head->next;
193
            $this->current = &$this->head;
194
            $this->size--;
195
            return $node->data;
196
        }
197
        
198
        $i = 0;
199
        $current = $this->head;
200
        $prev = $current;
201 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...
202
            $prev = $current;
203
            $current = $current->next;
204
        }
205
        $prev->next = $current->next;
206
        $this->size--;
207
208
        return $prev->data;
209
    }
210
211
    /**
212
     * Removes and returns the last node in the list.
213
     *
214
     * @return mixed data in node.
215
     */
216
    public function pop() {
217
        return $this->delete($this->size - 1);
218
    }
219
220
    /**
221
     * Remove all nodes of the list using shift.
222
     */
223
    public function clear() {
224
        while($this->head !== null) {
225
            $this->shift();
226
        }
227
    }
228
229
    /**
230
     * Converts/exports the list content into array type.
231
     *
232
     * @return array data stored in all nodes.
233
     */
234
    public function toArray() : array {
235
        $arr = [];
236
        foreach($this->getAll() as $node) {
237
            $arr[] = $node;
238
        }
239
240
        return $arr;
241
    }
242
243
    /**
244
     * Adds at the beginning a node in the list.
245
     *
246
     * @param mixed $data
247
     * @return mixed the data stored.
248
     */
249
    public function unshift($data) {
250
        $this->insert(0, $data);
251
    }
252
253
    /**
254
     * Deletes the first node of the list and returns it.
255
     *
256
     * @return mixed the data.
257
     */
258
    public function shift() {
259
        return $this->delete(0);
260
    }
261
262
    /**
263
     * Reset the cursor position.
264
     */
265
    public function rewind() {
266
        $this->position = 0;
267
        $this->current = $this->head;
268
    }
269
270
    /**
271
     * Returns the current node data.
272
     *
273
     * @return mixed
274
     */
275
    public function current() {
276
        return $this->current->data;
277
    }
278
279
    /**
280
     * Key or index that indicates the cursor position.
281
     *
282
     * @return integer The current position.
283
     */
284
    public function key() {
285
        return $this->position;
286
    }
287
288
    /**
289
     * Move the cursor to the next node and increments the
290
     * position counter.
291
     */
292
    public function next() {
293
        ++$this->position;
294
        $this->current = $this->current->next;
295
    }
296
297
    /**
298
     * Returns if the current pointer position is valid.
299
     *
300
     * @return boolean true if pointer is not last, else false.
301
     */
302
    public function valid() {
303
        return $this->current !== null;
304
    }
305
}