Completed
Push — master ( 71e8d2...303a8a )
by Siro Díaz
01:32
created

SimpleLinkedList::search()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 4
Ratio 28.57 %

Importance

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