29
29
use doganoo \PHPAlgorithms \Common \Interfaces \IComparable ;
30
30
use doganoo \PHPAlgorithms \Common \Interfaces \INode ;
31
31
use doganoo \PHPAlgorithms \Common \Interfaces \IUnaryNode ;
32
+ use doganoo \PHPAlgorithms \Common \Iterator \LinkedListIterator ;
32
33
use doganoo \PHPAlgorithms \Common \Util \Comparator ;
33
34
use doganoo \PHPAlgorithms \Datastructure \Lists \Node ;
35
+ use IteratorAggregate ;
34
36
use JsonSerializable ;
35
37
36
-
37
38
/**
38
39
* Class LinkedList
39
40
*
46
47
* Linked lists are a necessary data structure, since they give you dynamic memory allocation with less danger of buffer overruns. Which means you had to write linked lists by hand. Which means you had to manipulate the pointers in linked lists by hand.
47
48
*
48
49
*/
49
- abstract class AbstractLinkedList implements IComparable, JsonSerializable {
50
+ abstract class AbstractLinkedList
51
+ implements
52
+ IComparable
53
+ , JsonSerializable
54
+ , IteratorAggregate {
50
55
51
56
/** @var Node */
52
57
private $ head = null ;
@@ -75,17 +80,18 @@ abstract class AbstractLinkedList implements IComparable, JsonSerializable {
75
80
* ================================
76
81
* 5 -> 4 -> 3 -> 2 -> 1 -> NULL
77
82
*/
78
- public function reverse () {
83
+ public function reverse (): void {
84
+ $ current = $ this ->getHead ();
79
85
$ prev = null ;
80
86
$ next = null ;
81
- $ current = $ this ->getHead ();
82
87
83
88
while ($ current !== null ) {
84
89
$ next = $ current ->getNext ();
85
90
$ current ->setNext ($ prev );
86
91
$ prev = $ current ;
87
92
$ current = $ next ;
88
93
}
94
+
89
95
$ this ->setHead ($ prev );
90
96
}
91
97
@@ -103,7 +109,7 @@ public function getHead(): ?Node {
103
109
*
104
110
* @param Node|null $node
105
111
*/
106
- public function setHead (?Node $ node ) {
112
+ public function setHead (?Node $ node ): void {
107
113
$ this ->head = $ node ;
108
114
}
109
115
@@ -148,12 +154,12 @@ public function deleteNode($data): bool {
148
154
* head twice. If the list contains duplicates, the next-next is set
149
155
* as the next node of the current node.
150
156
*/
151
- public function removeDuplicates () {
157
+ public function removeDuplicates (): void {
152
158
$ tortoise = $ this ->head ;
153
159
154
- while ($ tortoise !== null ) {
160
+ while (null !== $ tortoise ) {
155
161
$ hare = $ tortoise ;
156
- while ($ hare ->getNext () !== null ) {
162
+ while (null !== $ hare ->getNext ()) {
157
163
if (Comparator::equals ($ hare ->getNext ()->getValue (), $ tortoise ->getValue ())) {
158
164
$ hare ->setNext ($ hare ->getNext ()->getNext ());
159
165
} else {
@@ -162,6 +168,7 @@ public function removeDuplicates() {
162
168
}
163
169
$ tortoise = $ tortoise ->getNext ();
164
170
}
171
+
165
172
}
166
173
167
174
/**
@@ -183,11 +190,11 @@ public function removeDuplicates() {
183
190
* @return AbstractLinkedList|null
184
191
*
185
192
*/
186
- public function getLastElements (int $ number ): AbstractLinkedList {
193
+ public function getLastElements (int $ number ): ? AbstractLinkedList {
187
194
$ p1 = $ this ->getHead ();
188
195
$ p2 = $ this ->getHead ();
189
196
$ number = $ number > $ this ->head ->size () ? $ this ->head ->size () : $ number ;
190
- $ list = $ this -> getEmptyInstance ();
197
+ $ list = new static ();
191
198
192
199
for ($ i = 0 ; $ i < $ number ; $ i ++) {
193
200
if ($ p1 == null ) {
@@ -208,22 +215,6 @@ public function getLastElements(int $number): AbstractLinkedList {
208
215
return $ list ;
209
216
}
210
217
211
- /**
212
- * abstract method that requires inheritors to return their type
213
- *
214
- * @return AbstractLinkedList
215
- */
216
- protected abstract function getEmptyInstance (): AbstractLinkedList ;
217
-
218
- /**
219
- * abstract method that requires inheritors to implement the way how
220
- * values are prepended to the list
221
- *
222
- * @param Node|null $node
223
- * @return bool
224
- */
225
- public abstract function append (?Node $ node ): bool ;
226
-
227
218
////This problem cannot be solved if the node to be deleted is
228
219
////the last node in the linked list
229
220
////node could be marked as dummy
@@ -254,7 +245,7 @@ public function getFirstElements(int $number): AbstractLinkedList {
254
245
$ head = $ this ->getHead ();
255
246
//if there are more elements requested than the list provides
256
247
$ number = $ number > $ head ->size () ? $ head ->size () : $ number ;
257
- $ list = $ this -> getEmptyInstance ();
248
+ $ list = new static ();
258
249
$ i = 0 ;
259
250
while ($ i < $ number ) {
260
251
//TODO append or prepend?
@@ -265,6 +256,15 @@ public function getFirstElements(int $number): AbstractLinkedList {
265
256
return $ list ;
266
257
}
267
258
259
+ /**
260
+ * abstract method that requires inheritors to implement the way how
261
+ * values are prepended to the list
262
+ *
263
+ * @param Node|null $node
264
+ * @return bool
265
+ */
266
+ public abstract function append (?Node $ node ): bool ;
267
+
268
268
/**
269
269
* abstract method that requires inheritors to implement the way how
270
270
* values are prepended to the list
@@ -423,7 +423,7 @@ public function remove($key): bool {
423
423
* The while loop iterates over all nodes until the
424
424
* value is found.
425
425
*/
426
- while ($ head !== null && Comparator::notEquals ($ head ->getKey (), $ key )) {
426
+ while (null !== $ head && Comparator::notEquals ($ head ->getKey (), $ key )) {
427
427
/*
428
428
* since a node is going to be removed from the
429
429
* node chain, the previous element has to be
@@ -467,7 +467,7 @@ public function remove($key): bool {
467
467
public function replaceValue ($ key , $ value ): bool {
468
468
$ replaced = false ;
469
469
$ node = $ this ->getHead ();
470
- while ($ node !== null ) {
470
+ while (null !== $ node ) {
471
471
if (Comparator::equals ($ node ->getKey (), $ key )) {
472
472
$ node ->setValue ($ value );
473
473
$ replaced = true ;
@@ -483,11 +483,11 @@ public function replaceValue($key, $value): bool {
483
483
*/
484
484
public function compareTo ($ object ): int {
485
485
if ($ object instanceof AbstractLinkedList) {
486
- if (Comparator::equals ($ this ->getHead (), $ object ->getHead ())) return 0 ;
487
- if (Comparator::lessThan ($ this ->getHead (), $ object ->getHead ())) return - 1 ;
488
- if (Comparator::greaterThan ($ this ->getHead (), $ object ->getHead ())) return 1 ;
486
+ if (Comparator::equals ($ this ->getHead (), $ object ->getHead ())) return IComparable:: EQUAL ;
487
+ if (Comparator::lessThan ($ this ->getHead (), $ object ->getHead ())) return IComparable:: IS_LESS ;
488
+ if (Comparator::greaterThan ($ this ->getHead (), $ object ->getHead ())) return IComparable:: IS_GREATER ;
489
489
}
490
- return - 1 ;
490
+ return IComparable:: IS_LESS ;
491
491
}
492
492
493
493
/**
@@ -573,6 +573,9 @@ public function getIntersectionNode(AbstractLinkedList $list): ?INode {
573
573
574
574
575
575
while (null !== $ l1 && null !== $ l2 ) {
576
+ // we can not use the identity operator here
577
+ // since it requires to be the exact same
578
+ // instance!
576
579
if ($ l1 == $ l2 ) {
577
580
return $ l1 ;
578
581
}
@@ -589,7 +592,7 @@ public function getIntersectionNode(AbstractLinkedList $list): ?INode {
589
592
* @return int
590
593
*/
591
594
public function size () {
592
- if ($ this ->isEmpty ()) {
595
+ if (true === $ this ->isEmpty ()) {
593
596
return 0 ;
594
597
}
595
598
return $ this ->head ->size ();
@@ -604,6 +607,13 @@ public function isEmpty() {
604
607
return $ this ->head == null ;
605
608
}
606
609
610
+ /**
611
+ * @inheritDoc
612
+ */
613
+ public function getIterator () {
614
+ return new LinkedListIterator ($ this );
615
+ }
616
+
607
617
/**
608
618
* Specify data which should be serialized to JSON
609
619
*
@@ -614,24 +624,8 @@ public function isEmpty() {
614
624
*/
615
625
public function jsonSerialize () {
616
626
return [
617
- "head " => $ this ->head ,
627
+ "head " => $ this ->getHead () ,
618
628
];
619
629
}
620
630
621
- //TODO implement
622
- //protected function removeDuplicates() {
623
- // $node = $this->head;
624
- // $previous = $this->head;
625
- // $visited = [];
626
- //
627
- // while ($node !== null) {
628
- // if (in_array($node->getValue(), $visited)) {
629
- // $previous->setNext($node->getNext());
630
- // } else {
631
- // $visited[] = $node->getValue();
632
- // $previous = $node;
633
- // }
634
- // $node = $node->getNext();
635
- // }
636
- //}
637
631
}
0 commit comments