Skip to content

Commit 6b84685

Browse files
authored
Merge pull request #107 from kirilcvetkov/SinglyLinkedLists
Added Singly Linked Lists
2 parents 79f5d22 + 4597595 commit 6b84685

File tree

2 files changed

+182
-0
lines changed

2 files changed

+182
-0
lines changed

DataStructures/SinglyLinkedList.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
/**
3+
* Singly Linked List
4+
*/
5+
6+
class SinglyLinkedList
7+
{
8+
public ?SinglyLinkedList $next = null;
9+
public $data;
10+
11+
public function __construct($data)
12+
{
13+
$this->data = $data;
14+
}
15+
16+
public function append($data): void
17+
{
18+
$current = $this;
19+
20+
while ($current instanceof SinglyLinkedList && isset($current->next)) {
21+
$current = $current->next;
22+
}
23+
24+
$current->next = new SinglyLinkedList($data);
25+
}
26+
27+
public function delete($data): SinglyLinkedList
28+
{
29+
$current = $this;
30+
31+
if ($current->data == $data) {
32+
return $current->next;
33+
}
34+
35+
while ($current instanceof SinglyLinkedList && isset($current->next)) {
36+
if ($current->next->data === $data) {
37+
$current->next = $current->next->next;
38+
39+
return $this;
40+
}
41+
42+
$current = $current->next;
43+
}
44+
45+
return $this;
46+
}
47+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php
2+
3+
use PHPUnit\Framework\TestCase;
4+
5+
require_once __DIR__ . '/../../vendor/autoload.php';
6+
require_once __DIR__ . '/../../DataStructures/SinglyLinkedList.php';
7+
8+
/**
9+
* Tests for the Singly Linked Lists class
10+
*/
11+
class SinglyLinkedListTest extends TestCase
12+
{
13+
/**
14+
* Create a SinglyLinkedList node
15+
*/
16+
private function createNode(string $string): SinglyLinkedList
17+
{
18+
$node = new SinglyLinkedList($string[0]);
19+
20+
for ($i = 1; $i < strlen($string); $i++) {
21+
$node->append($string[$i]);
22+
}
23+
24+
return $node;
25+
}
26+
27+
/**
28+
* Provider of SinglyLinkedList nodes
29+
*/
30+
public function provideNodes()
31+
{
32+
return [
33+
'IsPalindrome' => [
34+
'node' => $this->createNode('hannah'),
35+
'expected' => true
36+
],
37+
'IsPalindrome2' => [
38+
'node' => $this->createNode('hanah'),
39+
'expected' => true
40+
],
41+
'IsNotPalindrome' => [
42+
'node' => $this->createNode('hanbah'),
43+
'expected' => false
44+
],
45+
'IsNotPalindrome2' => [
46+
'node' => $this->createNode('han1h'),
47+
'expected' => false
48+
],
49+
];
50+
}
51+
52+
/**
53+
* Test the if a SinglyLinkedList is a palindrome
54+
*
55+
* @dataProvider provideNodes
56+
*/
57+
public function testIsPalindrome($node, $expected): void
58+
{
59+
$this->assertEquals($expected, $this->isPalindrome($node));
60+
}
61+
62+
/**
63+
* Supporting method for testing if a linked list is palindrome
64+
*/
65+
private function isPalindrome(SinglyLinkedList $node): bool
66+
{
67+
$length = $this->length($node);
68+
$pairs = 0;
69+
$curr = $node;
70+
71+
while ($curr instanceof SinglyLinkedList) {
72+
if ($this->hasPair($curr->next, $curr->data)) {
73+
$pairs++;
74+
}
75+
76+
$curr = $curr->next;
77+
}
78+
79+
return $pairs == floor($length / 2);
80+
}
81+
82+
/**
83+
* Supporting method for testing if a linked list is palindrome
84+
*/
85+
private function hasPair($node, string $data): bool
86+
{
87+
if (! $node instanceof SinglyLinkedList) {
88+
return false;
89+
}
90+
91+
$curr = $node;
92+
93+
while ($curr instanceof SinglyLinkedList) {
94+
if ($curr->data == $data) {
95+
return true;
96+
}
97+
98+
$curr = $curr->next;
99+
}
100+
101+
return false;
102+
}
103+
104+
/**
105+
* Supporting method for testing if a linked list is palindrome
106+
*/
107+
private function length(SinglyLinkedList $node): int
108+
{
109+
$curr = $node;
110+
$counter = 0;
111+
112+
while ($curr instanceof SinglyLinkedList) {
113+
$counter++;
114+
$curr = $curr->next;
115+
}
116+
117+
return $counter;
118+
}
119+
120+
/**
121+
* Test SinglyLinkedList's delete functionality
122+
*/
123+
public function testDelete(): void
124+
{
125+
$this->assertEquals(
126+
$this->createNode('hanah'), // expected node
127+
$this->createNode('hannah')->delete('n'), // actual node
128+
);
129+
130+
$this->assertNotEquals(
131+
$this->createNode('hanah'), // expected node
132+
$this->createNode('hannah')->delete('h'), // actual node
133+
);
134+
}
135+
}

0 commit comments

Comments
 (0)