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
32
213#include <iostream>
214#include <iomanip>
215#include <string>
216#include <vector>
217#include <chrono>
218#include <prefix-tree.H>
219#include <tclap/CmdLine.h>
220
221using namespace std;
222using namespace Aleph;
223
228{
229 cout << "\n" << string(60, '=') << endl;
230 cout << "Trie: Basic Operations" << endl;
231 cout << string(60, '=') << endl;
232
233 Cnode root('\0'); // Root with sentinel character
234
235 cout << "\n--- Insertion ---" << endl;
236
237 vector<string> words = {"cat", "car", "card", "care", "careful", "cart"};
238
239 cout << "Inserting words with common prefix 'ca':" << endl;
240 for (const auto& word : words)
241 {
242 bool inserted = root.insert_word(word);
243 cout << " " << word << " -> " << (inserted ? "inserted" : "exists") << endl;
244 }
245
246 // Try inserting duplicates
247 cout << "\nTrying to insert duplicate:" << endl;
248 cout << " cat -> " << (root.insert_word("cat") ? "inserted" : "already exists") << endl;
249
250 cout << "\n--- Search ---" << endl;
251
252 vector<string> to_find = {"cat", "car", "care", "cap", "dog"};
253 cout << "Searching for words:" << endl;
254 for (const auto& word : to_find)
255 {
256 bool found = root.contains(word);
257 cout << " " << word << " -> " << (found ? "FOUND" : "not found") << endl;
258 }
259
260 cout << "\n--- Statistics ---" << endl;
261 cout << "Total words stored: " << root.count() << endl;
262
263 cout << "\n--- All Words ---" << endl;
264 cout << "Words in lexicographic order:" << endl;
265 auto all_words = root.words();
266 for (size_t i = 0; i < all_words.size(); ++i)
267 {
268 string word = all_words[i];
269 cout << " " << (i + 1) << ". " << word << endl;
270 }
271
272 root.destroy();
273}
274
279{
280 cout << "\n" << string(60, '=') << endl;
281 cout << "Prefix Search: Autocomplete Feature" << endl;
282 cout << string(60, '=') << endl;
283
284 Cnode root('\0');
285
286 // Build a dictionary
288 "apple", "application", "apply", "approach",
289 "apt", "aptitude",
290 "banana", "band", "bandana", "bank", "banner",
291 "car", "card", "care", "careful", "careless", "career",
292 "cart", "cartoon", "carton"
293 };
294
295 cout << "\nBuilding dictionary with " << dictionary.size() << " words..." << endl;
296 for (const auto& word : dictionary)
297 root.insert_word(word);
298
299 cout << "\n--- Prefix Search Demo ---" << endl;
300
301 vector<string> prefixes = {"app", "ban", "car", "cart", "xyz"};
302
303 for (const auto& prefix : prefixes)
304 {
305 cout << "\nPrefix '" << prefix << "' matches:" << endl;
306
307 auto matches = root.words_with_prefix(prefix);
308
309 if (matches.size() == 0)
310 cout << " (no matches)" << endl;
311 else
312 {
313 for (size_t i = 0; i < matches.size(); ++i)
314 {
315 string match = matches[i];
316 cout << " - " << match << endl;
317 }
318 }
319 }
320
321 cout << "\n--- Simulating Autocomplete ---" << endl;
322
323 string input = "c";
324 cout << "\nTyping simulation (showing suggestions):" << endl;
325
326 while (input.length() <= 4)
327 {
328 auto suggestions = root.words_with_prefix(input);
329 cout << " User types: '" << input << "'" << endl;
330 cout << " Suggestions (" << suggestions.size() << " matches): ";
331
332 size_t shown = 0;
333 for (size_t i = 0; i < suggestions.size() and shown < 5; ++i, ++shown)
334 {
335 if (i > 0) 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") input = "ca";
345 else if (input == "ca") input = "car";
346 else if (input == "car") input = "care";
347 else break;
348 }
349
350 root.destroy();
351}
352
357{
358 cout << "\n" << string(60, '=') << endl;
359 cout << "Practical Example: Simple Spell Checker" << endl;
360 cout << string(60, '=') << endl;
361
362 Cnode root('\0');
363
364 // Build dictionary
366 "program", "programming", "programmer", "progress", "project",
367 "computer", "compute", "computing", "computation",
368 "algorithm", "algorithms", "algorithmic",
369 "data", "database", "datum",
370 "structure", "structures", "structural",
371 "the", "they", "them", "there", "their", "these",
372 "hello", "help", "helper", "helpful"
373 };
374
375 cout << "Loading dictionary with " << dictionary.size() << " words..." << endl;
376 for (const auto& word : dictionary)
377 root.insert_word(word);
378
379 cout << "\n--- Spell Check Demo ---" << endl;
380
381 vector<string> to_check = {"program", "progam", "algoritm", "helllo", "data", "computer"};
382
383 for (const auto& word : to_check)
384 {
385 cout << "\nChecking: '" << word << "'" << endl;
386
387 if (root.contains(word))
388 {
389 cout << " Status: Correct!" << endl;
390 }
391 else
392 {
393 cout << " Status: Not found - might be misspelled" << endl;
394
395 // Simple suggestion: words with same prefix
396 for (size_t prefixLen = word.length() - 1; prefixLen >= 2; --prefixLen)
397 {
398 string prefix = word.substr(0, prefixLen);
399 auto suggestions = root.words_with_prefix(prefix);
400
401 if (suggestions.size() > 0)
402 {
403 cout << " Did you mean: ";
404 size_t shown = 0;
405 for (size_t i = 0; i < suggestions.size() and shown < 3; ++i, ++shown)
406 {
407 if (i > 0) cout << ", ";
408 string s = suggestions[i];
409 cout << s;
410 }
411 cout << "?" << endl;
412 break;
413 }
414 }
415 }
416 }
417
418 root.destroy();
419}
420
425{
426 cout << "\n" << string(60, '=') << endl;
427 cout << "Practical Example: Shell Command Autocomplete" << endl;
428 cout << string(60, '=') << endl;
429
430 Cnode root('\0');
431
432 // Common shell commands
434 "cd", "ls", "pwd", "mkdir", "rmdir", "rm", "cp", "mv",
435 "cat", "less", "more", "head", "tail",
436 "grep", "find", "locate", "which", "whereis",
437 "chmod", "chown", "chgrp",
438 "ps", "top", "htop", "kill", "killall",
439 "ssh", "scp", "sftp",
440 "git", "gitk", "github",
441 "make", "cmake", "gcc", "g++", "gdb",
442 "python", "python3", "pip", "pip3",
443 "apt", "apt-get", "apt-cache"
444 };
445
446 cout << "Loading " << commands.size() << " shell commands..." << endl;
447 for (const auto& cmd : commands)
448 root.insert_word(cmd);
449
450 cout << "\n--- Tab Completion Simulation ---" << endl;
451
452 vector<string> partial_inputs = {"g", "gi", "apt", "ch", "py"};
453
454 for (const auto& input : partial_inputs)
455 {
456 cout << "\n$ " << input << "<TAB>" << endl;
457
458 auto completions = root.words_with_prefix(input);
459
460 if (completions.size() == 0)
461 cout << " (no completions)" << endl;
462 else if (completions.size() == 1)
463 {
464 string c = completions[0];
465 cout << " -> " << c << " (unique match)" << endl;
466 }
467 else
468 {
469 cout << " Possible completions: ";
470 for (size_t i = 0; i < completions.size(); ++i)
471 {
472 if (i > 0) cout << " ";
473 string c = completions[i];
474 cout << c;
475 }
476 cout << endl;
477 }
478 }
479
480 root.destroy();
481}
482
487{
488 cout << "\n" << string(60, '=') << endl;
489 cout << "Trie Structure Visualization" << endl;
490 cout << string(60, '=') << endl;
491
492 Cnode root('\0');
493
494 vector<string> words = {"cat", "car", "card"};
495
496 cout << "\nInserting: ";
497 for (size_t i = 0; i < words.size(); ++i)
498 {
499 if (i > 0) cout << ", ";
500 cout << words[i];
501 root.insert_word(words[i]);
502 }
503 cout << endl;
504
505 cout << "\nTrie structure:" << endl;
506 cout << " root" << endl;
507 cout << " |" << endl;
508 cout << " c" << endl;
509 cout << " |" << endl;
510 cout << " a" << endl;
511 cout << " /|" << endl;
512 cout << " t r ($=end)" << endl;
513 cout << " | |" << endl;
514 cout << " $ ($) d" << endl;
515 cout << " |" << endl;
516 cout << " $" << endl;
517 cout << endl;
518 cout << "Words: cat, car, card" << endl;
519 cout << "Notice how 'c', 'a' are shared!" << endl;
520
521 cout << "\nTree string representation: " << root.to_str() << endl;
522
523 root.destroy();
524}
525
530{
531 cout << "\n" << string(60, '=') << endl;
532 cout << "Performance Analysis (n = " << n << " words)" << endl;
533 cout << string(60, '=') << endl;
534
535 Cnode root('\0');
536
537 // Generate random-ish words
538 vector<string> words;
539 words.reserve(n);
540
541 vector<string> prefixes = {"pre", "post", "un", "re", "in", "ex", "sub", "super", "anti", "auto"};
542 vector<string> roots = {"act", "form", "port", "ject", "duct", "spect", "scrib", "struct", "mit", "vers"};
543 vector<string> suffixes = {"ion", "ment", "ness", "able", "ible", "ful", "less", "ive", "ous", "al"};
544
545 for (int i = 0; i < n; ++i)
546 {
547 string word = prefixes[i % prefixes.size()] +
548 roots[(i / prefixes.size()) % roots.size()] +
549 suffixes[(i / (prefixes.size() * roots.size())) % suffixes.size()];
550 // Add some variation
551 if (i % 3 == 0) word += "ed";
552 if (i % 5 == 0) word += "ly";
553 if (i % 7 == 0) word += "ing";
554 words.push_back(word);
555 }
556
557 cout << "\nGenerated " << words.size() << " words for testing" << endl;
558
559 // Insertion benchmark
560 auto start = chrono::high_resolution_clock::now();
561
562 for (const auto& word : words)
563 root.insert_word(word);
564
565 auto mid = chrono::high_resolution_clock::now();
566
567 // Search benchmark
568 int found = 0;
569 for (const auto& word : words)
570 if (root.contains(word)) ++found;
571
572 auto end = chrono::high_resolution_clock::now();
573
574 auto insert_us = chrono::duration_cast<chrono::microseconds>(mid - start).count();
575 auto search_us = chrono::duration_cast<chrono::microseconds>(end - mid).count();
576
577 cout << "\nResults:" << endl;
578 cout << " Words in trie: " << root.count() << endl;
579 cout << " Insert time: " << insert_us << " us" << endl;
580 cout << " Search time: " << search_us << " us" << endl;
581 cout << " Found: " << found << "/" << words.size() << endl;
582
583 // Prefix search benchmark
584 start = chrono::high_resolution_clock::now();
585
586 size_t total_matches = 0;
587 for (const auto& prefix : prefixes)
588 {
589 auto matches = root.words_with_prefix(prefix);
591 }
592
593 end = chrono::high_resolution_clock::now();
594
595 auto prefix_us = chrono::duration_cast<chrono::microseconds>(end - start).count();
596
597 cout << "\nPrefix search (10 prefixes):" << endl;
598 cout << " Time: " << prefix_us << " us" << endl;
599 cout << " Total matches: " << total_matches << endl;
600
601 root.destroy();
602}
603
604int main(int argc, char* argv[])
605{
606 try
607 {
608 TCLAP::CmdLine cmd("Trie (Prefix Tree) Example", ' ', "1.0");
609
610 TCLAP::ValueArg<int> nArg("n", "count",
611 "Number of words for performance test", false, 1000, "int");
612 TCLAP::SwitchArg basicArg("b", "basic",
613 "Show basic operations", false);
614 TCLAP::SwitchArg prefixArg("p", "prefix",
615 "Show prefix search / autocomplete", false);
616 TCLAP::SwitchArg spellArg("s", "spell",
617 "Show spell checker example", false);
618 TCLAP::SwitchArg cmdArg("c", "commands",
619 "Show command autocomplete example", false);
620 TCLAP::SwitchArg structArg("t", "structure",
621 "Show trie structure visualization", false);
622 TCLAP::SwitchArg perfArg("f", "performance",
623 "Run performance analysis", false);
624 TCLAP::SwitchArg allArg("a", "all",
625 "Run all demos", false);
626
627 cmd.add(nArg);
628 cmd.add(basicArg);
629 cmd.add(prefixArg);
630 cmd.add(spellArg);
631 cmd.add(cmdArg);
632 cmd.add(structArg);
633 cmd.add(perfArg);
634 cmd.add(allArg);
635
636 cmd.parse(argc, argv);
637
638 int n = nArg.getValue();
639 bool runBasic = basicArg.getValue();
640 bool runPrefix = prefixArg.getValue();
641 bool runSpell = spellArg.getValue();
642 bool runCmd = cmdArg.getValue();
643 bool runStruct = structArg.getValue();
644 bool runPerf = perfArg.getValue();
645 bool runAll = allArg.getValue();
646
649 runAll = true;
650
651 cout << "=== Trie (Prefix Tree): Efficient String Storage ===" << endl;
652
653 if (runAll or runBasic)
655
656 if (runAll or runStruct)
658
659 if (runAll or runPrefix)
661
662 if (runAll or runSpell)
664
665 if (runAll or runCmd)
667
668 if (runAll or runPerf)
670
671 cout << "\n=== Summary ===" << endl;
672 cout << "Tries excel at:" << endl;
673 cout << " - Fast prefix searches (autocomplete)" << endl;
674 cout << " - Memory-efficient storage of strings with shared prefixes" << endl;
675 cout << " - O(k) operations where k = word length" << endl;
676 cout << "Use cases: autocomplete, spell checkers, IP routing, dictionaries" << endl;
677
678 return 0;
679 }
680 catch (TCLAP::ArgException& e)
681 {
682 cerr << "Error: " << e.error() << " for arg " << e.argId() << endl;
683 return 1;
684 }
685}
686
int main()
void demo_performance()
Prefix tree (Trie) node for storing character sequences.
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
size_t length() const noexcept
Count the number of elements of a container.
Definition ah-dry.H:1385
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
Definition gmpfrxx.h:4060
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
static void prefix(Node *root, DynList< Node * > &acc)
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Trie (prefix tree) implementation.
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.