summary refs log tree commit diff stats
path: root/prefix_search.h
diff options
context:
space:
mode:
Diffstat (limited to 'prefix_search.h')
-rw-r--r--prefix_search.h85
1 files changed, 85 insertions, 0 deletions
diff --git a/prefix_search.h b/prefix_search.h new file mode 100644 index 0000000..fe69ef7 --- /dev/null +++ b/prefix_search.h
@@ -0,0 +1,85 @@
1#ifndef PREFIX_SEARCH_H_A6672A1D
2#define PREFIX_SEARCH_H_A6672A1D
3
4#include <unordered_map>
5#include <vector>
6#include <stdexcept>
7
8template <typename T>
9class prefix_search {
10public:
11
12 prefix_search(size_t depth = 0) : depth_(depth), count_(0)
13 {
14 }
15
16 size_t getDepth() const
17 {
18 return depth_;
19 }
20
21 size_t getCount() const
22 {
23 return count_;
24 }
25
26 void add(std::string& key, T val, size_t i = 0)
27 {
28 count_++;
29
30 if (i == key.length())
31 {
32 elements_.push_back(val);
33 } else {
34 char next = key.at(i);
35
36 if (!children_.count(next))
37 {
38 children_.emplace(next, prefix_search<T> { depth_ + 1 } );
39 }
40
41 children_.at(next).add(key, val, i + 1);
42 }
43 }
44
45 T at(size_t i) const
46 {
47 if (i < elements_.size())
48 {
49 return elements_.at(i);
50 } else {
51 i -= elements_.size();
52
53 for (const auto& mapping : children_)
54 {
55 if (mapping.second.count_ > i)
56 {
57 return mapping.second.at(i);
58 } else {
59 i -= mapping.second.count_;
60 }
61 }
62 }
63
64 throw std::out_of_range("Index out of range");
65 }
66
67 const prefix_search<T>& find(const std::string& val, size_t i) const
68 {
69 if (i == val.length() || !children_.count(val.at(i)))
70 {
71 return *this;
72 }
73
74 return children_.at(val.at(i)).find(val, i+1);
75 }
76
77private:
78
79 size_t depth_;
80 size_t count_;
81 std::unordered_map<char, prefix_search<T>> children_;
82 std::vector<T> elements_;
83};
84
85#endif /* end of include guard: PREFIX_SEARCH_H_A6672A1D */