Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
trie_example.C
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
217#include <iostream>
218#include <iomanip>
219#include <string>
220#include <vector>
221#include <chrono>
222#include <prefix-tree.H>
223#include <tclap/CmdLine.h>
224
225using namespace std;
226using namespace Aleph;
227
232{
233 cout << "\n" << string(60, '=') << endl;
234 cout << "Trie: Basic Operations" << endl;
235 cout << string(60, '=') << endl;
236
238
239 cout << "\n--- Insertion ---" << endl;
240
241 vector<string> words = {"cat", "car", "card", "care", "careful", "cart"};
242
243 cout << "Inserting words with common prefix 'ca':" << endl;
244 for (const auto &word : words)
245 {
246 const bool inserted = trie.insert_word(word);
247 cout << " " << word << " -> " << (inserted ? "inserted" : "exists") << endl;
248 }
249
250 // Try inserting duplicates
251 cout << "\nTrying to insert duplicate:" << endl;
252 cout << " cat -> " << (trie.insert_word("cat") ? "inserted" : "already exists") << endl;
253
254 cout << "\n--- Search ---" << endl;
255
256 vector<string> to_find = {"cat", "car", "care", "cap", "dog"};
257 cout << "Searching for words:" << endl;
258 for (const auto &word : to_find)
259 {
260 bool found = trie.contains(word);
261 cout << " " << word << " -> " << (found ? "FOUND" : "not found") << endl;
262 }
263
264 cout << "\n--- Statistics ---" << endl;
265 cout << "Total words stored: " << trie.count() << endl;
266
267 cout << "\n--- All Words ---" << endl;
268 cout << "Words in lexicographic order:" << endl;
269 auto all_words = trie.words();
270 for (size_t i = 0; i < all_words.size(); ++i)
271 {
272 string word = all_words[i];
273 cout << " " << (i + 1) << ". " << word << endl;
274 }
275}
276
281{
282 cout << "\n" << string(60, '=') << endl;
283 cout << "Prefix Search: Autocomplete Feature" << endl;
284 cout << string(60, '=') << endl;
285
287
288 // Build a dictionary
289 vector<string> dictionary = {"apple", "application", "apply", "approach", "apt",
290 "aptitude", "banana", "band", "bandana", "bank",
291 "banner", "car", "card", "care", "careful",
292 "careless", "career", "cart", "cartoon", "carton"};
293
294 cout << "\nBuilding dictionary with " << dictionary.size() << " words..." << endl;
295 for (const auto &word : dictionary)
296 trie.insert_word(word);
297
298 cout << "\n--- Prefix Search Demo ---" << endl;
299
300 vector<string> prefixes = {"app", "ban", "car", "cart", "xyz"};
301
302 for (const auto &prefix : prefixes)
303 {
304 cout << "\nPrefix '" << prefix << "' matches:" << endl;
305
306 auto matches = trie.words_with_prefix(prefix);
307
308 if (matches.size() == 0)
309 cout << " (no matches)" << endl;
310 else
311 {
312 for (size_t i = 0; i < matches.size(); ++i)
313 {
314 string match = matches[i];
315 cout << " - " << match << endl;
316 }
317 }
318 }
319
320 cout << "\n--- Simulating Autocomplete ---" << endl;
321
322 string input = "c";
323 cout << "\nTyping simulation (showing suggestions):" << endl;
324
325 while (input.length() <= 4)
326 {
327 auto suggestions = trie.words_with_prefix(input);
328 cout << " User types: '" << input << "'" << endl;
329 cout << " Suggestions (" << suggestions.size() << " matches): ";
330
331 size_t shown = 0;
332 for (size_t i = 0; i < suggestions.size() and shown < 5; ++i, ++shown)
333 {
334 if (i > 0)
335 cout << ", ";
336 string s = suggestions[i];
337 cout << s;
338 }
339 if (suggestions.size() > 5)
340 cout << " ...(" << (suggestions.size() - 5) << " more)";
341 cout << endl;
342
343 // Simulate user typing more
344 if (input == "c")
345 input = "ca";
346 else if (input == "ca")
347 input = "car";
348 else if (input == "car")
349 input = "care";
350 else
351 break;
352 }
353}
354
359{
360 cout << "\n" << string(60, '=') << endl;
361 cout << "Practical Example: Simple Spell Checker" << endl;
362 cout << string(60, '=') << endl;
363
365
366 // Build dictionary
368 "program", "programming", "programmer", "progress", "project", "computer", "compute",
369 "computing", "computation", "algorithm", "algorithms", "algorithmic", "data", "database",
370 "datum", "structure", "structures", "structural", "the", "they", "them",
371 "there", "their", "these", "hello", "help", "helper", "helpful"};
372
373 cout << "Loading dictionary with " << dictionary.size() << " words..." << endl;
374 for (const auto &word : dictionary)
375 trie.insert_word(word);
376
377 cout << "\n--- Spell Check Demo ---" << endl;
378
379 vector<string> to_check = {"program", "progam", "algoritm", "helllo", "data", "computer"};
380
381 for (const auto &word : to_check)
382 {
383 cout << "\nChecking: '" << word << "'" << endl;
384
385 if (trie.contains(word))
386 {
387 cout << " Status: Correct!" << endl;
388 }
389 else
390 {
391 cout << " Status: Not found - might be misspelled" << endl;
392
393 // Simple suggestion: words with same prefix
394 for (size_t prefixLen = word.length() - 1; prefixLen >= 2; --prefixLen)
395 {
396 string prefix = word.substr(0, prefixLen);
397 auto suggestions = trie.words_with_prefix(prefix);
398
399 if (suggestions.size() > 0)
400 {
401 cout << " Did you mean: ";
402 size_t shown = 0;
403 for (size_t i = 0; i < suggestions.size() and shown < 3; ++i, ++shown)
404 {
405 if (i > 0)
406 cout << ", ";
407 string s = suggestions[i];
408 cout << s;
409 }
410 cout << "?" << endl;
411 break;
412 }
413 }
414 }
415 }
416}
417
422{
423 cout << "\n" << string(60, '=') << endl;
424 cout << "Practical Example: Shell Command Autocomplete" << endl;
425 cout << string(60, '=') << endl;
426
428
429 // Common shell commands
431 "cd", "ls", "pwd", "mkdir", "rmdir", "rm", "cp", "mv", "cat",
432 "less", "more", "head", "tail", "grep", "find", "locate", "which", "whereis",
433 "chmod", "chown", "chgrp", "ps", "top", "htop", "kill", "killall", "ssh",
434 "scp", "sftp", "git", "gitk", "github", "make", "cmake", "gcc", "g++",
435 "gdb", "python", "python3", "pip", "pip3", "apt", "apt-get", "apt-cache"};
436
437 cout << "Loading " << commands.size() << " shell commands..." << endl;
438 for (const auto &cmd : commands)
439 trie.insert_word(cmd);
440
441 cout << "\n--- Tab Completion Simulation ---" << endl;
442
443 vector<string> partial_inputs = {"g", "gi", "apt", "ch", "py"};
444
445 for (const auto &input : partial_inputs)
446 {
447 cout << "\n$ " << input << "<TAB>" << endl;
448
449 auto completions = trie.words_with_prefix(input);
450
451 if (completions.size() == 0)
452 cout << " (no completions)" << endl;
453 else if (completions.size() == 1)
454 {
455 string c = completions[0];
456 cout << " -> " << c << " (unique match)" << endl;
457 }
458 else
459 {
460 cout << " Possible completions: ";
461 for (size_t i = 0; i < completions.size(); ++i)
462 {
463 if (i > 0)
464 cout << " ";
465 string c = completions[i];
466 cout << c;
467 }
468 cout << endl;
469 }
470 }
471}
472
477{
478 cout << "\n" << string(60, '=') << endl;
479 cout << "Trie Structure Visualization" << endl;
480 cout << string(60, '=') << endl;
481
483
484 vector<string> words = {"cat", "car", "card"};
485
486 cout << "\nInserting: ";
487 for (size_t i = 0; i < words.size(); ++i)
488 {
489 if (i > 0)
490 cout << ", ";
491 cout << words[i];
492 trie.insert_word(words[i]);
493 }
494 cout << endl;
495
496 cout << "\nTrie structure:" << endl;
497 cout << " root" << endl;
498 cout << " |" << endl;
499 cout << " c" << endl;
500 cout << " |" << endl;
501 cout << " a" << endl;
502 cout << " / \\" << endl;
503 cout << " r* t*" << endl;
504 cout << " |" << endl;
505 cout << " d*" << endl;
506 cout << endl;
507 cout << "Words: cat, car, card" << endl;
508 cout << "Notice how 'c', 'a' are shared!" << endl;
509 cout << "The '*' marks word endings stored as node state, not child nodes." << endl;
510
511 string structure = trie.root()->to_str();
512 if (not structure.empty() and structure.front() == '\0')
513 structure.replace(0, 1, "<root>");
514 cout << "\nTree string representation: " << structure << endl;
515}
516
521{
522 cout << "\n" << string(60, '=') << endl;
523 cout << "Performance Analysis (n = " << n << " words)" << endl;
524 cout << string(60, '=') << endl;
525
527
528 // Generate random-ish words
529 vector<string> words;
530 words.reserve(n);
531
532 vector<string> prefixes = {"pre", "post", "un", "re", "in", "ex", "sub", "super", "anti", "auto"};
533 vector<string> roots = {"act", "form", "port", "ject", "duct",
534 "spect", "scrib", "struct", "mit", "vers"};
535 vector<string> suffixes = {"ion", "ment", "ness", "able", "ible",
536 "ful", "less", "ive", "ous", "al"};
537
538 for (int i = 0; i < n; ++i)
539 {
540 string word = prefixes[i % prefixes.size()] + roots[(i / prefixes.size()) % roots.size()] +
541 suffixes[(i / (prefixes.size() * roots.size())) % suffixes.size()];
542 // Add some variation
543 if (i % 3 == 0)
544 word += "ed";
545 if (i % 5 == 0)
546 word += "ly";
547 if (i % 7 == 0)
548 word += "ing";
549 words.push_back(word);
550 }
551
552 cout << "\nGenerated " << words.size() << " words for testing" << endl;
553
554 // Insertion benchmark
555 auto start = chrono::high_resolution_clock::now();
556
557 for (const auto &word : words)
558 trie.insert_word(word);
559
560 auto mid = chrono::high_resolution_clock::now();
561
562 // Search benchmark
563 int found = 0;
564 for (const auto &word : words)
565 if (trie.contains(word))
566 ++found;
567
568 auto end = chrono::high_resolution_clock::now();
569
570 auto insert_us = chrono::duration_cast<chrono::microseconds>(mid - start).count();
571 auto search_us = chrono::duration_cast<chrono::microseconds>(end - mid).count();
572
573 cout << "\nResults:" << endl;
574 cout << " Words in trie: " << trie.count() << endl;
575 cout << " Insert time: " << insert_us << " us" << endl;
576 cout << " Search time: " << search_us << " us" << endl;
577 cout << " Found: " << found << "/" << words.size() << endl;
578
579 // Prefix search benchmark
580 start = chrono::high_resolution_clock::now();
581
582 size_t total_matches = 0;
583 for (const auto &prefix : prefixes)
584 {
585 auto matches = trie.words_with_prefix(prefix);
586 total_matches += matches.size();
587 }
588
589 end = chrono::high_resolution_clock::now();
590
591 auto prefix_us = chrono::duration_cast<chrono::microseconds>(end - start).count();
592
593 cout << "\nPrefix search (10 prefixes):" << endl;
594 cout << " Time: " << prefix_us << " us" << endl;
595 cout << " Total matches: " << total_matches << endl;
596}
597
598int main(int argc, char *argv[])
599{
600 try
601 {
602 TCLAP::CmdLine cmd("Trie (Prefix Tree) Example", ' ', "1.0");
603
604 TCLAP::ValueArg<int> nArg("n", "count", "Number of words for performance test", false, 1000,
605 "int");
606 TCLAP::SwitchArg basicArg("b", "basic", "Show basic operations", false);
607 TCLAP::SwitchArg prefixArg("p", "prefix", "Show prefix search / autocomplete", false);
608 TCLAP::SwitchArg spellArg("s", "spell", "Show spell checker example", false);
609 TCLAP::SwitchArg cmdArg("c", "commands", "Show command autocomplete example", false);
610 TCLAP::SwitchArg structArg("t", "structure", "Show trie structure visualization", false);
611 TCLAP::SwitchArg perfArg("f", "performance", "Run performance analysis", false);
612 TCLAP::SwitchArg allArg("a", "all", "Run all demos", false);
613
614 cmd.add(nArg);
615 cmd.add(basicArg);
616 cmd.add(prefixArg);
617 cmd.add(spellArg);
618 cmd.add(cmdArg);
619 cmd.add(structArg);
620 cmd.add(perfArg);
621 cmd.add(allArg);
622
623 cmd.parse(argc, argv);
624
625 int n = nArg.getValue();
626 bool runBasic = basicArg.getValue();
627 bool runPrefix = prefixArg.getValue();
628 bool runSpell = spellArg.getValue();
629 bool runCmd = cmdArg.getValue();
630 bool runStruct = structArg.getValue();
631 bool runPerf = perfArg.getValue();
632 bool runAll = allArg.getValue();
633
635 not runPerf)
636 runAll = true;
637
638 cout << "=== Trie (Prefix Tree): Efficient String Storage ===" << endl;
639
640 if (runAll or runBasic)
642
643 if (runAll or runStruct)
645
646 if (runAll or runPrefix)
648
649 if (runAll or runSpell)
651
652 if (runAll or runCmd)
654
655 if (runAll or runPerf)
657
658 cout << "\n=== Summary ===" << endl;
659 cout << "Tries excel at:" << endl;
660 cout << " - Fast prefix searches (autocomplete)" << endl;
661 cout << " - Memory-efficient storage of strings with shared prefixes" << endl;
662 cout << " - O(k) operations where k = word length" << endl;
663 cout << "Use cases: autocomplete, spell checkers, IP routing, dictionaries" << endl;
664
665 return 0;
666 }
667 catch (TCLAP::ArgException &e)
668 {
669 cerr << "Error: " << e.error() << " for arg " << e.argId() << endl;
670 return 1;
671 }
672}
int main()
void demo_performance()
Owning prefix tree wrapper.
bool insert_word(const std::string &word)
Insert a word into the tree.
size_t size() const noexcept
Return the number of words stored in the tree.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
static void prefix(Node *root, DynList< Node * > &acc)
STL namespace.
Trie (prefix tree) implementation.
CmdLine cmd
Definition testHash.C:48
void demo_basic_operations()
Demonstrate basic trie operations.
void demo_prefix_search()
Demonstrate prefix search - the trie's killer feature.
void demo_trie_structure()
Show trie structure visualization.
void demo_command_autocomplete()
Practical example: Command-line autocomplete.
void demo_spell_checker()
Practical example: Spell checker suggestions.