TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
trie_multiple_search.cpp
Go to the documentation of this file.
1
12
13
#include <algorithm>
14
#include <cassert>
15
#include <cctype>
16
#include <cstdint>
17
#include <cstring>
18
#include <iostream>
19
#include <queue>
20
25
namespace
operations_on_datastructures
{
32
namespace
trie_operations
{
37
class
Tnode {
38
private
:
39
static
constexpr
uint8_t ENGLISH_ALPHABET_SIZE = 26;
40
// pointers to alphabets
41
std::vector<Tnode *> english;
42
43
// To mark the end of word
44
bool
endOfWord;
45
46
// To store the frequency of searches for the word
47
uint32_t frequency;
48
49
public
:
50
Tnode() {
51
english.resize(ENGLISH_ALPHABET_SIZE,
nullptr
);
52
endOfWord =
false
;
53
frequency = 0;
54
}
55
// Copy Constructor
56
Tnode(
const
Tnode &
node
) {
57
english =
node
.english;
58
endOfWord =
node
.endOfWord;
59
frequency =
node
.frequency;
60
}
61
62
Tnode &operator=(
const
Tnode &
node
) =
default
;
63
64
Tnode(Tnode &&) =
default
;
65
66
Tnode &operator=(Tnode &&) =
default
;
72
inline
uint8_t
numberOfChildren
(Tnode *
node
) {
73
return
ENGLISH_ALPHABET_SIZE -
74
std::count(
node
->english.begin(),
node
->english.end(),
nullptr
);
75
}
76
77
// Functions to perform operations on trie
78
void
Insert(
const
std::string &entry);
79
void
Delete
(std::string entry);
80
void
DeleteFrom
(
Tnode
*delete_from, std::string delete_string,
81
int
remove_index);
82
bool
SearchPresence
(
const
std::string &key);
83
void
SuggestAutocomplete
(
Tnode
*new_root,
const
std::string &prefix);
84
void
SearchSuggestions
(
const
std::string &key);
85
void
SuggestFreqAutocomplete
(
86
Tnode
*new_root,
const
std::string &prefix,
87
std::priority_queue<std::pair<int, std::string> > *suggestions);
88
void
SearchFreqSuggestions
(
const
std::string &key);
89
void
SelectionTop_3
(
90
std::priority_queue<std::pair<int, std::string> > *suggestions);
91
92
// To free up the dynamically allocated objects
93
~Tnode
() {
94
int
i = 0;
95
for
(i = 0; i < ENGLISH_ALPHABET_SIZE; i++) {
96
if
(english[i]) {
97
delete
english[i];
98
}
99
}
100
}
101
};
102
107
void
Tnode::Insert
(
const
std::string &entry) {
108
Tnode *cur_pos =
this
;
109
int
letter_index = 0;
110
111
for
(
auto
&i : entry) {
112
// To ignore case
113
letter_index = tolower(i) - 97;
114
115
// Allocate a node for each character of entry if not present in the
116
// trie
117
if
(cur_pos->english[letter_index] ==
nullptr
) {
118
cur_pos->english[letter_index] =
new
Tnode();
119
}
120
121
cur_pos = cur_pos->english[letter_index];
122
}
123
// cur_pos points to the last char, mark it as end of word
124
cur_pos->endOfWord =
true
;
125
}
126
137
void
Tnode::DeleteFrom
(Tnode *delete_from, std::string delete_string,
138
int
remove_index) {
139
if
(delete_string.size() == remove_index) {
140
int
letter_index = tolower(delete_string[remove_index]) - 97;
141
142
DeleteFrom
(delete_from->english[letter_index], delete_string,
143
remove_index + 1);
144
145
delete
delete_from;
146
}
147
}
148
153
void
Tnode::Delete
(std::string entry) {
154
Tnode *cur_pos =
this
,
155
*delete_from =
this
;
// Current pointer pointing to root
156
int
letter_index = 0, delete_from_index = 0, i = 0, n = entry.size();
157
158
for
(i = 0; i < n; i++) {
159
// To ignore case
160
letter_index = tolower(entry[i]) - 97;
161
162
// Display error message when given entry is not present in the tree
163
if
(cur_pos->english[letter_index] ==
nullptr
) {
164
std::cout <<
"Entry not Found"
<< std::endl;
165
return
;
166
}
167
// If the current node is end of word for the current prefix or if it
168
// has 2 or more branches It cannot be deleted while deleting the
169
// required entry.
170
if
(
numberOfChildren
(cur_pos) > 1 || cur_pos->endOfWord) {
171
delete_from = cur_pos;
// denotes the beginning of the shortest
172
// suffix that is allowed to be deleted
173
delete_from_index = i - 1;
// Beginning index of the suffix
174
// corresponding to the 'entry'
175
}
176
177
// Traversing through the entry
178
cur_pos = cur_pos->english[letter_index];
179
}
180
181
// cur_pos now points to the last char of entry. Display message if that
182
// entry does not exist
183
if
(!cur_pos->endOfWord) {
184
std::cout <<
"Entry not Found"
<< std::endl;
185
return
;
186
}
187
188
// If cur_pos is not a leaf node, unmark end of word and assign 0 to it's
189
// frequency for deletion
190
if
(
numberOfChildren
(cur_pos)) {
191
cur_pos->endOfWord =
false
;
192
cur_pos->frequency = 0;
193
return
;
194
}
195
196
// The first character of the suffix to be deleted
197
letter_index = tolower(entry[delete_from_index + 1]) - 97;
198
// Point cur_pos to the next node
199
cur_pos = delete_from->english[letter_index];
200
// Sever the connection from the main trie
201
delete_from->english[letter_index] =
nullptr
;
202
203
// If number of characters in the suffix are more than 1, recursively delete
204
// each character starting from cur_pos using the helper function
205
if
(n > delete_from_index + 2) {
206
DeleteFrom
(cur_pos, entry, delete_from_index + 2);
207
}
208
// If the suffix is only 1 char in length
209
else
{
210
delete
cur_pos;
211
}
212
}
213
220
bool
Tnode::SearchPresence
(
const
std::string &key) {
221
Tnode *cur_pos =
this
;
222
int
letter_index = 0;
223
224
for
(
auto
&i : key) {
225
letter_index = tolower(i) - 97;
226
// If any character in the order of the key is absent, word not found!
227
if
(cur_pos->english[letter_index] ==
nullptr
) {
228
return
false
;
229
}
230
cur_pos = cur_pos->english[letter_index];
231
}
232
// Word is only present in the trie if the key is a valid complete entry and
233
// not just a prefix.
234
if
(cur_pos->endOfWord) {
235
(cur_pos->frequency)++;
236
return
true
;
237
}
else
{
238
return
false
;
239
}
240
}
241
249
void
Tnode::SuggestAutocomplete
(Tnode *new_root,
const
std::string &prefix) {
250
// Iterate through all 26 nodes as we have to print all strings with the
251
// given prefix
252
int
i = 0;
253
for
(i = 0; i < ENGLISH_ALPHABET_SIZE; i++) {
254
if
(new_root->english[i] !=
nullptr
) {
255
// Print the sugestion only if it's a valid complete entry and not
256
// just a prefix
257
if
(new_root->english[i]->endOfWord) {
258
std::cout << prefix + char(i + 97) << std::endl;
259
}
260
261
SuggestAutocomplete
(new_root->english[i], prefix +
char
(i + 97));
262
}
263
}
264
}
265
274
void
Tnode::SearchSuggestions
(
const
std::string &key) {
275
Tnode *cur_pos =
nullptr
, *prev_pos =
nullptr
;
276
cur_pos = prev_pos =
this
;
// maintaining 2 pointers, initialized to root
277
int
letter_index = 0;
278
std::string prefix =
279
""
;
// variable storing the updated value of longest common prefix
280
281
for
(
auto
&i : key) {
282
letter_index = tolower(i) - 97;
283
prev_pos = cur_pos;
// Previous pointer updated to point to the last
284
// char of the longest common prefix
285
286
// When the node for the character does not exist, longest prefix has
287
// been determined and SuggestAutocomplete is called
288
if
(cur_pos->english[letter_index] ==
nullptr
) {
289
SuggestAutocomplete
(prev_pos, prefix);
290
std::cout <<
"- - - - - - - - - - - - - - - - - - - - - - - - - - "
291
<< std::endl;
292
return
;
293
}
294
// Updating the longest common prefix
295
prefix += char(tolower(i));
296
cur_pos = cur_pos->english[letter_index];
297
}
298
// If the key is a valid entry of trie, display it @ top of the suggestions
299
if
(cur_pos->endOfWord) {
300
std::cout << key << std::endl;
301
(cur_pos->frequency)++;
302
}
303
304
(void)prev_pos;
// Idiom to ignore previous pointer
305
306
// Call for suggestions when the search key is present as an entry/a prefix
307
// in the trie
308
SuggestAutocomplete
(cur_pos, prefix);
309
std::cout <<
"- - - - - - - - - - - - - - - - - - - - - - - - - - "
310
<< std::endl;
311
return
;
312
}
313
320
void
Tnode::SelectionTop_3
(
321
std::priority_queue<std::pair<int, std::string> > *suggestions) {
322
// Display Either top 3 or total number of suggestions, whichever is smaller
323
int
n = suggestions->size(), Top = 0;
324
Top = n < 3 ? n : 3;
325
while
(Top--) {
326
std::cout << suggestions->top().second << std::endl;
327
suggestions->pop();
328
}
329
}
330
340
void
Tnode::SuggestFreqAutocomplete
(
341
Tnode *new_root,
const
std::string &prefix,
342
std::priority_queue<std::pair<int, std::string> > *suggestions) {
343
int
i = 0;
344
for
(i = 0; i < ENGLISH_ALPHABET_SIZE; i++) {
345
if
(new_root->english[i] !=
nullptr
) {
346
// Add to sugestions only if it's a valid complete entry and not
347
// just a prefix
348
if
(new_root->english[i]->endOfWord) {
349
suggestions->push(std::make_pair(
350
new_root->english[i]->frequency, prefix +
char
(i + 97)));
351
}
352
353
SuggestFreqAutocomplete
(new_root->english[i], prefix +
char
(i + 97),
354
suggestions);
355
}
356
}
357
}
358
368
void
Tnode::SearchFreqSuggestions
(
const
std::string &key) {
369
Tnode *cur_pos =
nullptr
, *prev_pos =
nullptr
;
370
cur_pos = prev_pos =
this
;
// maintaining 2 pointers, initialized to root
371
int
letter_index = 0;
372
std::string prefix =
373
""
;
// variable storing the updated value of longest common prefix
374
std::priority_queue<std::pair<int, std::string> >
375
suggestions;
// max heap to store (frequency, word) in descending order
376
// of freq
377
378
std::priority_queue<std::pair<int, std::string> > *Suggestions =
379
&suggestions;
380
381
for
(
auto
&i : key) {
382
letter_index = tolower(i) - 97;
383
prev_pos = cur_pos;
// Previous pointer updated to point to the last
384
// char of the longest common prefix
385
386
// When the node for the character does not exist, longest prefix has
387
// been determined and SuggestFreqAutocomplete is called
388
if
(cur_pos->english[letter_index] ==
nullptr
) {
389
SuggestFreqAutocomplete
(prev_pos, prefix, Suggestions);
390
// To display the top 3 results
391
SelectionTop_3
(Suggestions);
392
std::cout <<
"- - - - - - - - - - - - - - - - - - - - - - - - - - "
393
<< std::endl;
394
return
;
395
}
396
// Updating the longest common prefix
397
prefix += char(tolower(i));
398
cur_pos = cur_pos->english[letter_index];
399
}
400
// If the key is a valid entry of trie, display it @ top of the suggestions
401
if
(cur_pos->endOfWord) {
402
(cur_pos->frequency)++;
403
std::cout << key << std::endl;
404
}
405
406
(void)prev_pos;
// Idiom to ignore previous pointer
407
408
// Call for Suggestions when the search key is present as an entry/a prefix
409
// in the trie
410
SuggestFreqAutocomplete
(cur_pos, prefix, Suggestions);
411
// Display the top 3 results
412
SelectionTop_3
(Suggestions);
413
414
std::cout <<
"- - - - - - - - - - - - - - - - - - - - - - - - - - "
415
<< std::endl;
416
return
;
417
}
418
}
// namespace trie_operations
419
}
// namespace operations_on_datastructures
420
425
static
void
test
() {
426
auto
root =
new
operations_on_datastructures::trie_operations::Tnode
();
427
std::vector<std::string> inputs = {
428
"abcde"
,
"sss"
,
"ssss"
,
"ssst"
,
"sssu"
,
"sssv"
,
429
"sst"
,
"ssts"
,
"sstt"
,
"sstu"
,
"tutu"
,
"tutuv"
,
430
"tutuu"
,
"tutuvs"
,
"tutus"
,
"tvst"
,
"tvsu"
,
"vvvv"
};
431
432
for
(
auto
&i : inputs) {
433
root->Insert(i);
434
}
435
// Search an existing entry
436
assert(root->SearchPresence(
"vvvv"
));
437
std::cout << root->SearchPresence(
"vvvv"
) << std::endl;
438
// Delete it
439
root->Delete(
"vvvv"
);
440
// Search for the entry again
441
assert(!root->SearchPresence(
"vvvv"
));
442
std::cout << root->SearchPresence(
"vvvv"
) << std::endl;
443
444
std::cout << root->SearchPresence(
"tutu"
) << std::endl;
445
root->SearchSuggestions(
"tutu"
);
446
std::cout << root->SearchPresence(
"tutu"
) << std::endl;
447
448
root->SearchSuggestions(
"tutuv"
);
449
std::cout << root->SearchPresence(
"tutuv"
) << std::endl;
450
451
root->SearchSuggestions(
"tutuvs"
);
452
453
root->SearchFreqSuggestions(
454
"tu"
);
// The top 3 frequent entries with prefix tu are tutu, tutuv &
455
// tutuvs respectively
456
root->SearchSuggestions(
457
""
);
// Empty search to list all the entries in the trie
458
}
459
464
int
main
() {
465
test
();
// run self-test implementations
466
return
0;
467
}
test
void test()
Definition
caesar_cipher.cpp:100
operations_on_datastructures::trie_operations::Tnode
Class defining the structure of trie node and containing the methods to perform operations on them.
Definition
trie_multiple_search.cpp:37
operations_on_datastructures::trie_operations::Tnode::SuggestAutocomplete
void SuggestAutocomplete(Tnode *new_root, const std::string &prefix)
Recursive function to suggest all the entries of trie which have a given common prefix.
Definition
trie_multiple_search.cpp:249
operations_on_datastructures::trie_operations::Tnode::SearchSuggestions
void SearchSuggestions(const std::string &key)
Lists out all the words in trie with the longest prefix of the search key that is present in the trie...
Definition
trie_multiple_search.cpp:274
operations_on_datastructures::trie_operations::Tnode::SearchPresence
bool SearchPresence(const std::string &key)
Function to check a word's presence in the trie (Basic).
Definition
trie_multiple_search.cpp:220
operations_on_datastructures::trie_operations::Tnode::SearchFreqSuggestions
void SearchFreqSuggestions(const std::string &key)
Lists out the most frequent words in trie with the longest prefix of the search key that is present i...
Definition
trie_multiple_search.cpp:368
operations_on_datastructures::trie_operations::Tnode::Insert
void Insert(const std::string &entry)
Function to insert a word in the trie.
Definition
trie_multiple_search.cpp:107
operations_on_datastructures::trie_operations::Tnode::SuggestFreqAutocomplete
void SuggestFreqAutocomplete(Tnode *new_root, const std::string &prefix, std::priority_queue< std::pair< int, std::string > > *suggestions)
Recursive function to suggest most frequently searched entries of trie which have a given common pref...
Definition
trie_multiple_search.cpp:340
operations_on_datastructures::trie_operations::Tnode::SelectionTop_3
void SelectionTop_3(std::priority_queue< std::pair< int, std::string > > *suggestions)
Function to display the 3 suggestions with highest frequency of search hits.
Definition
trie_multiple_search.cpp:320
operations_on_datastructures::trie_operations::Tnode::DeleteFrom
void DeleteFrom(Tnode *delete_from, std::string delete_string, int remove_index)
Function recursively deletes the substring character by character iterating through the string to be ...
Definition
trie_multiple_search.cpp:137
operations_on_datastructures::trie_operations::Tnode::Delete
void Delete(std::string entry)
Function to verify presence and hence delete an entry from the trie.
Definition
trie_multiple_search.cpp:153
operations_on_datastructures::trie_operations::Tnode::numberOfChildren
uint8_t numberOfChildren(Tnode *node)
Function to count the number of children a node in the trie has.
Definition
trie_multiple_search.cpp:72
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
operations_on_datastructures
for std::vector
trie_operations
Functions for Trie datastructure implementation.
node
Definition
binary_search_tree.cpp:11
operations_on_datastructures
trie_multiple_search.cpp
Generated by
1.18.0