Skip to content

Commit 3360474

Browse files
Enhanced Trie Data Structure with Case-Insensitive Feature and additional Test Cases (#172)
* Added Disjoint Sets Data structure * Moved DisjointSetTest.php to tests/DataStructures * Update DataStructures/DisjointSets/DisjointSet.php Co-authored-by: Brandon Johnson <[email protected]> * Update DataStructures/DisjointSets/DisjointSetNode.php Co-authored-by: Brandon Johnson <[email protected]> * Update DataStructures/DisjointSets/DisjointSetNode.php Co-authored-by: Brandon Johnson <[email protected]> * Update tests/DataStructures/DisjointSetTest.php Co-authored-by: Brandon Johnson <[email protected]> * Update tests/DataStructures/DisjointSetTest.php Co-authored-by: Brandon Johnson <[email protected]> * Update tests/DataStructures/DisjointSetTest.php Co-authored-by: Brandon Johnson <[email protected]> * Considered PHPCS remarks. Unit Testing is now working. * Remove data type mixed. Considered annotations for php7.4. * Remove data type mixed. Considered annotations for php7.4. * updating DIRECTORY.md * Implemented Trie DataStructure * Added Trie to DIRECTORY.md * updating DIRECTORY.md * Implemented AVLTree DataStructure * updating DIRECTORY.md * Implemented AVLTree DataStructure * Implemented SegmentTreeNode.php * Implementing SegmentTree * Implementing SegmentTree with updateTree * Implementing SegmentTree with rangeUpdateTree * Implementing SegmentTree with query and queryTree * Added serializing and deserializing of the SegmentTree * Adding unit tests SegmentTree implementation * Added unit tests for SegmentTree updates and range updates * considering PHPCS for Added unit tests for SegmentTree updates and range updates * Added unit tests for SegmentTree serialization/deserialization and array updates reflections * Added unit tests for SegmentTree Edge Cases * Added unit tests for SegmentTree Exceptions (OutOfBoundsException, InvalidArgumentException) * Added SegmentTree to DIRECTORY.md * Implemented Segment Tree Data Structure * updating DIRECTORY.md * Added some comments to my files in: #160, #162, #163, #166. Implemented Segment Tree Data Structure. * Added some comments to my files in: #160, #162, #163, #166. Implemented Segment Tree Data Structure. * Added comments time complexity for query(), update() and buildTree() * Implemented Splay Tree Data Structure * Update tests/DataStructures/SplayTreeTest.php Co-authored-by: Brandon Johnson <[email protected]> * Implemented Trie Data Structure. Added case-insensitive feature to the Trie implementation. Added corresponding unit testing. --------- Co-authored-by: Brandon Johnson <[email protected]> Co-authored-by: Ramy-Badr-Ahmed <[email protected]>
1 parent ea4d3b0 commit 3360474

File tree

3 files changed

+175
-4
lines changed

3 files changed

+175
-4
lines changed

DataStructures/Trie/Trie.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<?php
22

33
/*
4-
* Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) in Pull Request: #162
4+
* Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) in Pull Request #162 and #172
55
* https://github.com/TheAlgorithms/PHP/pull/162
6+
* https://github.com/TheAlgorithms/PHP/pull/172
67
*
78
* Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request addressing bugs/corrections to this file.
89
* Thank you!
@@ -61,6 +62,7 @@ public function search(string $word): bool
6162
*/
6263
public function startsWith(string $prefix): array
6364
{
65+
$prefix = strtolower($prefix); // Normalize the prefix to lowercase
6466
$node = $this->root;
6567
for ($i = 0; $i < strlen($prefix); $i++) {
6668
$char = $prefix[$i];

DataStructures/Trie/TrieNode.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<?php
22

33
/*
4-
* Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) in Pull Request: #162
4+
* Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) in Pull Request #162 and #172
55
* https://github.com/TheAlgorithms/PHP/pull/162
6+
* https://github.com/TheAlgorithms/PHP/pull/172
67
*
78
* Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request addressing bugs/corrections to this file.
89
* Thank you!
@@ -27,6 +28,7 @@ public function __construct()
2728
*/
2829
public function addChild(string $char): TrieNode
2930
{
31+
$char = $this->normalizeChar($char);
3032
if (!isset($this->children[$char])) {
3133
$this->children[$char] = new TrieNode();
3234
}
@@ -38,6 +40,7 @@ public function addChild(string $char): TrieNode
3840
*/
3941
public function hasChild(string $char): bool
4042
{
43+
$char = $this->normalizeChar($char);
4144
return isset($this->children[$char]);
4245
}
4346

@@ -46,6 +49,15 @@ public function hasChild(string $char): bool
4649
*/
4750
public function getChild(string $char): ?TrieNode
4851
{
52+
$char = $this->normalizeChar($char);
4953
return $this->children[$char] ?? null;
5054
}
55+
56+
/**
57+
* Normalize the character to lowercase.
58+
*/
59+
private function normalizeChar(string $char): string
60+
{
61+
return strtolower($char);
62+
}
5163
}

tests/DataStructures/TrieTest.php

Lines changed: 159 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<?php
22

33
/*
4-
* Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) in Pull Request: #162
4+
* Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) in Pull Request #162 and #172
55
* https://github.com/TheAlgorithms/PHP/pull/162
6+
* https://github.com/TheAlgorithms/PHP/pull/172
67
*
78
* Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request addressing bugs/corrections to this file.
89
* Thank you!
@@ -14,6 +15,7 @@
1415
require_once __DIR__ . '/../../DataStructures/Trie/TrieNode.php';
1516

1617
use DataStructures\Trie\Trie;
18+
use DataStructures\Trie\TrieNode;
1719
use PHPUnit\Framework\TestCase;
1820

1921
class TrieTest extends TestCase
@@ -25,6 +27,9 @@ protected function setUp(): void
2527
$this->trie = new Trie();
2628
}
2729

30+
/**
31+
* Test insertion and search functionality of the Trie.
32+
*/
2833
public function testInsertAndSearch()
2934
{
3035
$this->trie->insert('the');
@@ -42,6 +47,48 @@ public function testInsertAndSearch()
4247
);
4348
}
4449

50+
/**
51+
* Test insertion and search functionality with mixed case words.
52+
*/
53+
public function testInsertAndSearchMixedCase()
54+
{
55+
$this->trie->insert('Apple');
56+
$this->trie->insert('aPPle');
57+
$this->assertTrue($this->trie->search('apple'), 'Expected "apple" to be found in the Trie.');
58+
$this->assertTrue($this->trie->search('APPLE'), 'Expected "APPLE" to be found in the Trie.');
59+
}
60+
61+
/**
62+
* Test insertion and search functionality with special characters.
63+
*/
64+
public function testInsertAndSearchWithSpecialCharacters()
65+
{
66+
$this->trie->insert('hello123');
67+
$this->trie->insert('[email protected]');
68+
$this->assertTrue($this->trie->search('hello123'), 'Expected "hello123" to be found in the Trie.');
69+
$this->assertTrue(
70+
$this->trie->search('[email protected]'),
71+
'Expected "[email protected]" to be found in the Trie.'
72+
);
73+
$this->assertTrue(
74+
$this->trie->search('HELLO123'),
75+
'Expected "HELLO123" not to be found in the Trie (case-sensitive).'
76+
);
77+
}
78+
79+
/**
80+
* Test insertion and search functionality with long strings.
81+
*/
82+
public function testInsertAndSearchLongStrings()
83+
{
84+
$longString = str_repeat('a', 1000);
85+
$this->trie->insert($longString);
86+
$this->assertTrue($this->trie->search($longString), 'Expected the long string to be found in the Trie.');
87+
}
88+
89+
/**
90+
* Test the startsWith functionality of the Trie.
91+
*/
4592
public function testStartsWith()
4693
{
4794
$this->trie->insert('hello');
@@ -58,9 +105,31 @@ public function testStartsWith()
58105
);
59106
}
60107

108+
/**
109+
* Test startsWith functionality with mixed case prefixes.
110+
*/
111+
public function testStartsWithMixedCase()
112+
{
113+
$this->trie->insert('PrefixMatch');
114+
$this->trie->insert('PreFixTesting');
115+
$this->assertEquals(
116+
['prefixmatch', 'prefixtesting'],
117+
$this->trie->startsWith('prefix'),
118+
'Expected words starting with "prefix" to be found in the Trie (case-insensitive).'
119+
);
120+
121+
$this->assertEquals(
122+
['prefixmatch', 'prefixtesting'],
123+
$this->trie->startsWith('PREFIX'),
124+
'Expected words starting with "PREFIX" to be found in the Trie (case-insensitive).'
125+
);
126+
}
127+
128+
/**
129+
* Test deletion of existing words from the Trie.
130+
*/
61131
public function testDelete()
62132
{
63-
// Insert words into the Trie
64133
$this->trie->insert('the');
65134
$this->trie->insert('universe');
66135
$this->trie->insert('is');
@@ -80,12 +149,51 @@ public function testDelete()
80149
$this->assertTrue($this->trie->search('rather'), 'Expected "rather" to be found.');
81150
}
82151

152+
/**
153+
* Test deletion of mixed case words from the Trie.
154+
*/
155+
public function testDeleteMixedCase()
156+
{
157+
$this->trie->insert('MixedCase');
158+
$this->assertTrue($this->trie->search('mixedcase'), 'Expected "mixedcase" to be found before deletion.');
159+
160+
$this->trie->delete('MIXEDCASE');
161+
$this->assertFalse(
162+
$this->trie->search('MixedCase'),
163+
'Expected "MixedCase" not to be found after deletion (case-insensitive).'
164+
);
165+
}
166+
167+
/**
168+
* Test deletion of words with special characters.
169+
*/
170+
public function testDeleteWithSpecialCharacters()
171+
{
172+
$this->trie->insert('spec!@l#chars');
173+
$this->assertTrue(
174+
$this->trie->search('spec!@l#chars'),
175+
'Expected "spec!@l#chars" to be found before deletion.'
176+
);
177+
178+
$this->trie->delete('SPEC!@L#CHARS');
179+
$this->assertFalse(
180+
$this->trie->search('spec!@l#chars'),
181+
'Expected "spec!@l#chars" not to be found after deletion.'
182+
);
183+
}
184+
185+
/**
186+
* Test deletion of a non-existent word from the Trie.
187+
*/
83188
public function testDeleteNonExistentWord()
84189
{
85190
$this->trie->delete('nonexistent');
86191
$this->assertFalse($this->trie->search('nonexistent'), 'Expected "nonexistent" to not be found.');
87192
}
88193

194+
/**
195+
* Test traversal of the Trie and retrieval of words.
196+
*/
89197
public function testTraverseTrieNode()
90198
{
91199
$this->trie->insert('hello');
@@ -99,11 +207,17 @@ public function testTraverseTrieNode()
99207
$this->assertCount(3, $words, 'Expected 3 words in the Trie.');
100208
}
101209

210+
/**
211+
* Test behavior of an empty Trie.
212+
*/
102213
public function testEmptyTrie()
103214
{
104215
$this->assertEquals([], $this->trie->getWords(), 'Expected an empty Trie to return an empty array.');
105216
}
106217

218+
/**
219+
* Test retrieval of words from the Trie.
220+
*/
107221
public function testGetWords()
108222
{
109223
$this->trie->insert('apple');
@@ -117,19 +231,28 @@ public function testGetWords()
117231
$this->assertCount(3, $words, 'Expected 3 words in the Trie.');
118232
}
119233

234+
/**
235+
* Test insertion of an empty string into the Trie.
236+
*/
120237
public function testInsertEmptyString()
121238
{
122239
$this->trie->insert('');
123240
$this->assertTrue($this->trie->search(''), 'Expected empty string to be found in the Trie.');
124241
}
125242

243+
/**
244+
* Test deletion of an empty string from the Trie.
245+
*/
126246
public function testDeleteEmptyString()
127247
{
128248
$this->trie->insert('');
129249
$this->trie->delete('');
130250
$this->assertFalse($this->trie->search(''), 'Expected empty string not to be found after deletion.');
131251
}
132252

253+
/**
254+
* Test the startsWith functionality with a common prefix.
255+
*/
133256
public function testStartsWithWithCommonPrefix()
134257
{
135258
$this->trie->insert('trie');
@@ -142,4 +265,38 @@ public function testStartsWithWithCommonPrefix()
142265
$this->assertContains('trier', $words, 'Expected "trier" to be found with prefix "tri".');
143266
$this->assertCount(3, $words, 'Expected 3 words with prefix "tri".');
144267
}
268+
269+
/**
270+
* Test retrieval of the root node of the Trie.
271+
*/
272+
public function testGetRoot()
273+
{
274+
$root = $this->trie->getRoot();
275+
$this->assertInstanceOf(TrieNode::class, $root, 'Expected root to be an instance of TrieNode.');
276+
$this->assertFalse($root->isEndOfWord, 'Expected the root node not to be the end of a word.');
277+
$this->assertCount(0, $root->children, 'Expected the root node to have no children initially.');
278+
}
279+
280+
/**
281+
* Test retrieval of the root node after populating the Trie with words.
282+
*/
283+
public function testGetRootAfterPopulation()
284+
{
285+
$this->trie->insert('TheAlgorithms');
286+
$this->trie->insert('PHP');
287+
$this->trie->insert('DSA');
288+
289+
$root = $this->trie->getRoot();
290+
291+
$this->assertInstanceOf(TrieNode::class, $root, 'Expected root to be an instance of TrieNode.');
292+
293+
// Assert that the root node is not marked as the end of a word
294+
$this->assertFalse($root->isEndOfWord, 'Expected the root node not to be the end of a word.');
295+
296+
// Assert that the root node has children corresponding to the inserted words
297+
$this->assertCount(3, $root->children, 'Expected the root node to have 3 children after inserting words.');
298+
$this->assertTrue($root->hasChild('t'), 'Expected root to have a child for "t".');
299+
$this->assertTrue($root->hasChild('p'), 'Expected root to have a child for "p".');
300+
$this->assertTrue($root->hasChild('D'), 'Expected root to have a child for "D".');
301+
}
145302
}

0 commit comments

Comments
 (0)