-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTrie.h
445 lines (394 loc) · 10.7 KB
/
Trie.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
//============================================================================
// Name : Trie.h
// Author : Alexander M. Westphal / Paul Schroeder / Klaus Riedl
// Version : Version 1.0
// Copyright :
// Description : Trie.h Template
// Compiler and C++ Version: GNU GCC / C++14 Standard
//============================================================================
#ifndef TRIE_H_INCLUDED
#define TRIE_H_INCLUDED
#include <typeinfo>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <stdlib.h>
template<class T, class E = char> class Trie {
public:
class _node;
class InternalNode;
class Leaf;
class TrieIterator;
typedef std::basic_string<E> key_type;
typedef std::pair<const key_type, T> value_type;
typedef T mapped_type;
typedef TrieIterator iterator;
typedef std::map<E, _node*> mappy;
InternalNode* root;
Trie(){
root = new InternalNode();
};
~Trie() = default;
/**
* Abstract Class Node
*/
class _node {
public:
virtual bool insert(key_type, mapped_type , key_type) = 0;
virtual bool erase(key_type& value) = 0;
virtual void clear() = 0;
};
/**
* Class Leaf extends abstract Class node.
* Leaf implements all methods of the Class node.
* Leaf represents a the last element of a branch containing the Translation of a word
*/
class Leaf: public _node {
public:
key_type mPath;
T mMeaning;
~Leaf()=default;
Leaf(key_type path, mapped_type meaning) {
mPath = path;
mMeaning = meaning;
}
bool insert(key_type, mapped_type , key_type) {return false;}
bool erase(key_type& value) {return false;}
void clear() {}
};
/**
* Class InternalNode implements Class node.
* Internal Node reprecents a single Charactar.
*/
class InternalNode: public _node {
public:
mappy mappyTheLittleMap;
~InternalNode()=default;
InternalNode() = default;
key_type viewTrie = "";
/**
* Insert will insert a Word into the Tree.
* This method will create Nodes with charactars until the very end is reach reprecented by the '#' Charactar.
* At the end a Leaf will be attached.
*/
bool insert(key_type key, mapped_type value, key_type leafWord) {
using namespace std;
try {
using namespace std;
E currentChar = key[0];
InternalNode* next;
using namespace std;
if (currentChar == '#') {
if (!mappyTheLittleMap.count(currentChar)) {
Leaf* last = new Leaf(leafWord, value);
mappyTheLittleMap.insert(pair<E,_node*>(currentChar, static_cast<_node*>(last)));
return true;
}
} else {
if (mappyTheLittleMap.find(currentChar) == mappyTheLittleMap.end()) {
next = new InternalNode();
mappyTheLittleMap.insert(pair<E,_node*>(currentChar, static_cast<_node*>(next)));
} else {
next = static_cast<InternalNode*>(mappyTheLittleMap.find(currentChar)->second);
}
next->insert(key.erase(0, 1), value, leafWord);
}
} catch (...) {
using namespace std;
cout << "An error occurred" << endl;
return false;
}
}
/**
* Erase will erase a word form the tree.
* It will erase the branch, the leaf and the terminate charactar.
*
*/
bool erase(key_type &value) {
E curChar = value[0];
auto mappyIt=mappyTheLittleMap.find(curChar);
if (curChar != '#') { //Not a leaf
if (!mappyTheLittleMap.empty() && mappyTheLittleMap.find(curChar) != mappyTheLittleMap.end()) {
mappyTheLittleMap.erase(curChar);
mappyIt.operator*().second->erase(value.erase(0, 1));
}
} else {
if (mappyTheLittleMap.erase(curChar) == 1) {
return true;
}
}
return false;
}
/**
* Clear will clear a branch.
*
*/
void clear() {
if (!mappyTheLittleMap.empty()) {
for (typename mappy::iterator clearIt=mappyTheLittleMap.begin(); clearIt!=mappyTheLittleMap.end(); clearIt++) {
clearIt -> second -> clear();
delete clearIt -> second;
}
mappyTheLittleMap.clear();
}
}
/**
* Method to check whether the map is empty or not.
*/
bool empty() {
return mappyTheLittleMap.empty();
}
};
/**
* Class TrieIterator will represent a Iterator-Class for the Trie.
*/
class TrieIterator {
public:
TrieIterator()=default;
std::stack<std::pair<typename mappy::iterator,typename mappy::iterator>> stackyTheLittleStack;
key_type viewTrie = "";
/**
* Constructor for the TrieIterator.
*/
TrieIterator(std::stack<std::pair<typename mappy::iterator, typename mappy::iterator>> stacky) {
stackyTheLittleStack = stacky;
}
/**
* operator* will represent the meaning of a leaf in case it is called.
*/
T& operator*() {
try {
Leaf* last = static_cast<Leaf*>(stackyTheLittleStack.top().first->second);
return last->mMeaning;
} catch (...){
std::cerr << "* kann nur auf ein Leaf angewendet werden" << std::endl;
}
};
/**
* Method to return mPath of this leaf.
*/
T& show() {
try {
Leaf* last = static_cast<Leaf*>(stackyTheLittleStack.top().first->second);
return last->mPath;
} catch (...){
std::cerr << "* kann nur auf ein Leaf angewendet werden" << std::endl;
}
};
/**
* Is-Not-Equal for to TrieIterator.
* Will return true in case the iterators are not equal.
*/
bool operator !=(const TrieIterator& rhs) {
return !operator ==(rhs);
};
/**
* Is-Equal for to TrieIterator.
* Will return true in case the iterators are equal.
*/
bool operator ==(const iterator& rhs) const {
return (stackyTheLittleStack.size() == rhs.stackyTheLittleStack.size() && stackyTheLittleStack.top().second == rhs.stackyTheLittleStack.top().second && stackyTheLittleStack.top().first == rhs.stackyTheLittleStack.top().first);
}
bool opCheck=false;
/**
* Increment operator.
*/
TrieIterator& operator ++() {
popStack();
if(opCheck){
std::cout<< stackyTheLittleStack.top().first->first<<std::endl;
slideLeft(static_cast<InternalNode*>(stackyTheLittleStack.top().first->second));
}
return *this;
};
/**
* Method to pop the top of the Stack.
* Method works recrusive.
*/
void popStack() {
opCheck=false;
typename mappy::iterator topIter = ++(stackyTheLittleStack.top().first);
typename mappy::iterator topEnd = (stackyTheLittleStack.top().second);
if (topIter == topEnd &&stackyTheLittleStack.size()>1 ) {
stackyTheLittleStack.pop();
popStack();
}else if(topIter != topEnd){
opCheck=true;
}else{
opCheck=false;
}
}
/**
* Method to go straigth down leaf.
*/
void slideLeft(InternalNode* node){
int leer =0;
int tmp;
InternalNode* current = node;
while(!current->mappyTheLittleMap.empty() && current->mappyTheLittleMap.begin()->first != '#'){
tmp=leer;
while(leer!=0){
leer--;
std::cout<<"_";
}
leer=tmp;
std::cout<<current->mappyTheLittleMap.begin()->first<<std::endl;
typename mappy::iterator ki = current->mappyTheLittleMap.begin();
stackyTheLittleStack.push(std::pair<typename mappy::iterator,typename mappy::iterator> (ki,current->mappyTheLittleMap.end()));
current = static_cast<InternalNode*>(current->mappyTheLittleMap.begin()->second);
leer++;
}
if (!current->mappyTheLittleMap.empty()){
if(current->mappyTheLittleMap.begin()->first=='#'){
tmp=leer;
while(leer!=0){
leer--;
std::cout<<"_";
}
leer=tmp;
}else{
std::cout << current->mappyTheLittleMap.begin()->first<<std::endl;
}
typename mappy::iterator ki = current->mappyTheLittleMap.begin();
stackyTheLittleStack.push(std::pair<typename mappy::iterator,typename mappy::iterator>(ki,current->mappyTheLittleMap.end()));
Leaf* lastL = static_cast<Leaf*>(current->mappyTheLittleMap.begin()->second);
tmp=leer;
while(leer!=0){
leer--;
std::cout<<"_";
}
leer=tmp;
std::cout<< " : " <<lastL->mMeaning<<std::endl;
}
}
};
/**
* Method to return whether the Map isEmpty or not
*/
bool empty() {
return root->empty();
}
/**
* Insert a single InternalNode or Leaf.
*/
iterator insert(const value_type& value) {
key_type word = value.first + '#';
key_type leafWord = value.first + '#';
key_type findLeafWithWord = value.first;
mapped_type meaning = value.second;
root->insert(word,meaning,leafWord);
return find(findLeafWithWord);
}
/**
* Delete a single InternalNode or a Leaf.
*/
void showTrie(){
if(!empty()){
std::cout <<"\n"<< "---ShowTrie---"<<std::endl;
iterator showTrieIt=begin();
while(showTrieIt!=end()){
++showTrieIt;
}
std::cout <<"\n"<< "----------"<<std::endl;
}else{
std::cout <<"\n"<< "ein leerer baum wird nicht geprintet"<<std::endl;
}
}
/**
* Method to clear the Tree.
* Except for the root.
*/
void clear() {
try {
root->clear();
} catch(...) {
std::cout << "Root has no children yet! \n";
}
}
/**
* LowerBound of the trie.
*/
iterator lower_bound(const key_type& testElement) {
iterator lowerBoundIt = begin();
while(lowerBoundIt != end()){
Leaf* last = static_cast<Leaf*>(lowerBoundIt.stackyTheLittleStack.top().first->second);
key_type leafWord = last->mPath;
if (leafWord.find(testElement) != std::string::npos){
return lowerBoundIt;
}
++lowerBoundIt;
}
return end();
}
/**
* UpperBound of the trie.
*/
iterator upper_bound(const key_type& testElement) {
try {
iterator upperBoundIt = begin();
TrieIterator ab();
while(upperBoundIt){
Leaf* last = static_cast<Leaf*>(upperBoundIt.stackyTheLittleStack.top().first->second);
key_type leafWord = last->mPath;
if (leafWord.find(testElement) != std::string::npos){
ab = upperBoundIt;
}
++upperBoundIt;
}
return ++ab();
} catch (...){
return end();
}
}
/**
* Method to find a word in the trie.
*
*/
iterator find(key_type& word) {
iterator findIt = begin();
if(!empty()){
while(findIt != end()){
Leaf* last = static_cast<Leaf*>(findIt.stackyTheLittleStack.top().first->second);
key_type leafWord = last->mPath;
key_type wordToCheck = word + '#';
if (leafWord == wordToCheck){
return findIt;
}
++findIt;
}
}
return end();
}
/**
* Begin-Element for the Trie-Iterator.
*/
iterator begin() {
try {
iterator beginIt;
beginIt.slideLeft(root);
return beginIt;
} catch(...) {
return end();
}
}
/**
* End-Element of the Trie-Iterator.
*/
iterator end() {
std::stack<std::pair<typename mappy::iterator,typename mappy::iterator>> endStack;
endStack.push(std::pair<typename mappy::iterator,typename mappy::iterator>(root->mappyTheLittleMap.end(),root->mappyTheLittleMap.end()));
TrieIterator endIt(endStack);
return endIt;
}
/**
* Erase a word of the trie.
* will return true in case the word could be erased.
*/
bool erase(const key_type& value) {
key_type tmp = value + "#";
root->erase(tmp);
}
};
#endif // TRIE_H_INCLUDED