Skip to content

Commit 6b7d3ad

Browse files
authored
Merge pull request rachitiitr#47 from rachitiitr/trie
Added Trie implementation using pointers
2 parents ac4d499 + d609686 commit 6b7d3ad

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

Library/Tree/trie.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#include<iostream>
2+
#include<vector>
3+
#include<map>
4+
#include<assert.h>
5+
#include<algorithm>
6+
using namespace std;
7+
8+
class Trie {
9+
map<char, Trie*> m_keys = {}; // what are the next avail chars in trie node
10+
int m_traversed = 0; // how many words in trie are proper prefix
11+
bool m_isLeaf = 0; // is this trie node a leaf node i.e a word ends here
12+
int m_depth = 0; // depth of trie node
13+
14+
public:
15+
Trie() = default;
16+
Trie(int depth): m_depth(depth) {}
17+
int getDepth() { return m_depth; }
18+
bool isKeyPresent(const char &c) { return m_keys.find(c) != m_keys.end(); }
19+
bool isLeaf() { return m_isLeaf; }
20+
void setLeaf() { m_isLeaf = 1; }
21+
void add(const string &word);
22+
int matchLength(const string &prefix); // returns the length of max prefix that exists in trie
23+
vector<string> getAllWords();
24+
vector<string> autoComplete(const string &prefix);
25+
bool isPresent(const string &word);
26+
void addKey(const char &c);
27+
Trie *to(const char &c);
28+
};
29+
30+
template <typename T>
31+
void assertVectors(const vector<T>& lhs, const vector<T>& rhs) {
32+
// for(auto e: lhs)
33+
// cout << e << " ";
34+
// cout << endl;
35+
// for(auto e: rhs)
36+
// cout << e << " ";
37+
// cout << endl;
38+
assert(lhs.size() == rhs.size());
39+
for (int i = 0; i < lhs.size(); i++)
40+
{
41+
assert(lhs[i] == rhs[i]);
42+
}
43+
}
44+
45+
int main() {
46+
47+
Trie t;
48+
49+
vector<string> words = {"Rachit", "Ramesh", "Ankit", "Ankita", "Rachit1"};
50+
sort(words.begin(), words.end());
51+
for (auto w : words)
52+
{
53+
t.add(w);
54+
}
55+
56+
assertVectors(t.autoComplete(""), words);
57+
assertVectors(t.autoComplete("Ra"), {"Rachit", "Rachit1", "Ramesh"});
58+
assertVectors(t.autoComplete("Rachit"), {"Rachit", "Rachit1"});
59+
assertVectors(t.autoComplete("Rachit1"), {"Rachit1"});
60+
assertVectors(t.autoComplete("Rachit12"), {});
61+
62+
assert(t.isPresent(""));
63+
assert(!t.isPresent("Racht"));
64+
assert(t.isPresent("Rachit"));
65+
assert(t.isPresent("Rachit1"));
66+
assert(!t.isPresent("Rachit12"));
67+
68+
assert(t.matchLength("Ract") == 3);
69+
assert(t.matchLength("") == 0);
70+
71+
return 0;
72+
}
73+
74+
// add the given char to current Trie node
75+
void Trie::addKey(const char& c) {
76+
if(!isKeyPresent(c)) {
77+
m_keys[c] = new Trie(m_depth + 1);
78+
}
79+
m_traversed++;
80+
}
81+
82+
Trie* Trie::to(const char& c) {
83+
if(!isKeyPresent(c)) {
84+
return NULL;
85+
}
86+
return m_keys[c];
87+
}
88+
89+
// add the word to trie, duplicates are ignored
90+
void Trie::add(const string &word) {
91+
Trie *cur = this;
92+
for (char c: word)
93+
{
94+
cur->addKey(c);
95+
cur = cur->to(c);
96+
}
97+
cur->setLeaf();
98+
}
99+
100+
// returns the length of max prefix that exists in trie
101+
int Trie::matchLength(const string &prefix) {
102+
Trie *cur = this;
103+
int match = 0;
104+
for (char c: prefix) {
105+
if (cur->isKeyPresent(c)) {
106+
match++;
107+
cur = cur->to(c);
108+
}
109+
else {
110+
return match;
111+
}
112+
}
113+
return match;
114+
}
115+
116+
vector<string> Trie::getAllWords() {
117+
vector<string> ans = {};
118+
for (auto it: m_keys) {
119+
char c = it.first;
120+
Trie *t = it.second;
121+
if (t->isLeaf()) {
122+
ans.push_back(string("") + c);
123+
}
124+
for (auto word: t->getAllWords()) {
125+
ans.push_back(c + word);
126+
}
127+
}
128+
129+
return ans;
130+
}
131+
132+
vector<string> Trie::autoComplete(const string &prefix) {
133+
if (!isPresent(prefix)) {
134+
return {};
135+
}
136+
vector<string> ans = {};
137+
138+
Trie *cur = this;
139+
for (char c: prefix) {
140+
if (cur->isKeyPresent(c)) {
141+
cur = cur->to(c);
142+
}
143+
else {
144+
break;
145+
}
146+
}
147+
148+
if (cur->isLeaf()) {
149+
ans.push_back(prefix);
150+
}
151+
152+
for (auto restWord: cur->getAllWords()) {
153+
ans.push_back(prefix + restWord);
154+
}
155+
return ans;
156+
}
157+
158+
bool Trie::isPresent(const string &word) {
159+
return matchLength(word) == word.size();
160+
}

0 commit comments

Comments
 (0)