llvm.org GIT mirror llvm / 765d8e5
Remove Trie::Edge class. Now edge labels are stored into nodes itself. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44880 91177308-0d34-0410-b5e6-96231b3b80d8 Anton Korobeynikov 12 years ago
1 changed file(s) with 89 addition(s) and 95 deletion(s). Raw diff Collapse all Expand all
2323 // - Labels are usually small, maybe it's better to use SmallString
2424 // - Something efficient for child storage
2525 // - Should we use char* during construction?
26 // - Should we templatize Empty with traits-like interface?
2627 // - GraphTraits interface
27 // - Eliminate Edge class, which is ok for debugging, but not for end code
2828
2929 template
3030 class Trie {
31 class Edge;
32 class Node;
33
34 class Edge {
35 std::string Label;
36 Node *Parent, *Child;
37
38 public:
31 class Node {
32 friend class Trie;
33
3934 typedef enum {
4035 Same = -3,
4136 StringIsPrefix = -2,
4439 HaveCommonPart
4540 } QueryResult;
4641
47 inline explicit Edge(std::string label = "",
48 Node* parent = NULL, Node* child = NULL):
49 Label(label), Parent(parent), Child(child) { }
50
51 inline void setParent(Node* parent) { Parent = parent; }
52 inline Node* getParent() const { return Parent; }
53 inline void setChild(Node* child) { Child = child; }
54 inline Node* getChild() const { return Child; }
42 std::string Label;
43 Payload Data;
44 std::map Children;
45 public:
46 inline explicit Node(const Payload& data, const std::string& label = ""):
47 Label(label), Data(data) { }
48
49 inline Node(const Node& n) {
50 Data = n.Data;
51 Children = n.Children;
52 Label = n.Label;
53 }
54 inline Node& operator=(const Node& n) {
55 if (&n != this) {
56 Data = n.Data;
57 Children = n.Children;
58 Label = n.Label;
59 }
60
61 return *this;
62 }
63
64 inline bool isLeaf() const { return Children.empty(); }
65
66 inline const Payload& getData() const { return Data; }
67 inline void setData(const Payload& data) { Data = data; }
68
5569 inline void setLabel(const std::string& label) { Label = label; }
5670 inline const std::string& getLabel() const { return Label; }
5771
58 QueryResult query(const std::string& string) const {
72 inline bool addEdge(Node* N) {
73 const std::string& Label = N->getLabel();
74 return Children.insert(std::make_pair(Label[0], N)).second;
75 }
76
77 QueryResult query(const std::string& s) const {
5978 unsigned i, l;
60 unsigned l1 = string.length();
79 unsigned l1 = s.length();
6180 unsigned l2 = Label.length();
6281
6382 // Find the length of common part
6483 l = std::min(l1, l2);
6584 i = 0;
66 while ((i < l) && (string[i] == Label[i]))
85 while ((i < l) && (s[i] == Label[i]))
6786 ++i;
6887
6988 if (i == l) { // One is prefix of another, find who is who
7392 return StringIsPrefix;
7493 else
7594 return LabelIsPrefix;
76 } else // String and Label just have common part, return its length
95 } else // s and Label have common (possible empty) part, return its length
7796 return (QueryResult)i;
78 }
79 };
80
81 class Node {
82 friend class Trie;
83
84 std::map Edges;
85 Payload Data;
86 public:
87 inline explicit Node(const Payload& data):Data(data) { }
88 inline Node(const Node& n) {
89 Data = n.Data;
90 Edges = n.Edges;
91 }
92 inline Node& operator=(const Node& n) {
93 if (&n != this) {
94 Data = n.Data;
95 Edges = n.Edges;
96 }
97
98 return *this;
99 }
100
101 inline bool isLeaf() const { return Edges.empty(); }
102
103 inline const Payload& getData() const { return Data; }
104 inline void setData(const Payload& data) { Data = data; }
105
106 inline Edge* addEdge(const std::string& Label) {
107 if (!Edges.insert(std::make_pair(Label[0],
108 Edge(Label, this))).second) {
109 assert(0 && "Edge already exists!");
110 return NULL;
111 } else
112 return &Edges[Label[0]];
11397 }
11498 };
11599
116100 std::vector Nodes;
117101 Payload Empty;
118102
119 inline Node* addNode(const Payload& data) {
120 Node* N = new Node(data);
103 inline Node* addNode(const Payload& data, const std::string label = "") {
104 Node* N = new Node(data, label);
121105 Nodes.push_back(N);
122106 return N;
123107 }
124108
125 inline Node* splitEdge(Edge& cEdge, size_t index) {
126 const std::string& l = cEdge.getLabel();
127 assert(index < l.length() && "Trying to split too far!");
128
109 inline Node* splitEdge(Node* N, char Id, size_t index) {
110 assert(N->Children.count(Id) && "Node doesn't exist");
111
112 Node* eNode = N->Children[Id];
113
114 const std::string &l = eNode->Label;
115 assert(index > 0 && index < l.length() && "Trying to split too far!");
129116 std::string l1 = l.substr(0, index);
130117 std::string l2 = l.substr(index);
131118
132 Node* nNode = addNode(Empty);
133 Edge* nEdge = nNode->addEdge(l2);
134 nEdge->setChild(cEdge.getChild());
135 cEdge.setChild(nNode);
136 cEdge.setLabel(l1);
119 eNode->Label = l2;
120
121 Node* nNode = addNode(Empty, l1);
122 nNode->addEdge(eNode);
123
124 N->Children[Id] = nNode;
137125
138126 return nNode;
139127 }
151139
152140 bool addString(const std::string& s, const Payload& data) {
153141 Node* cNode = getRoot();
154 Edge* nEdge = NULL;
142 Node* tNode = NULL;
155143 std::string s1(s);
156144
157 while (nEdge == NULL) {
158 if (cNode->Edges.count(s1[0])) {
159 Edge& cEdge = cNode->Edges[s1[0]];
160 typename Edge::QueryResult r = cEdge.query(s1);
145 while (tNode == NULL) {
146 char Id = s1[0];
147 if (cNode->Children.count(Id)) {
148 Node* nNode = cNode->Children[Id];
149 typename Node::QueryResult r = nNode->query(s1);
161150
162151 switch (r) {
163 case Edge::Same:
164 case Edge::StringIsPrefix:
165 case Edge::DontMatch:
152 case Node::Same:
153 case Node::StringIsPrefix:
154 // Currently we don't allow to have two strings in the trie one
155 // being a prefix of another. This should be fixed.
156 assert(0 && "FIXME!");
157 return false;
158 case Node::DontMatch:
166159 assert(0 && "Impossible!");
167160 return false;
168 case Edge::LabelIsPrefix:
169 s1 = s1.substr(cEdge.getLabel().length());
170 cNode = cEdge.getChild();
161 case Node::LabelIsPrefix:
162 s1 = s1.substr(nNode->getLabel().length());
163 cNode = nNode;
171164 break;
172165 default:
173 nEdge = splitEdge(cEdge, r)->addEdge(s1.substr(r));
166 nNode = splitEdge(cNode, Id, r);
167 tNode = addNode(data, s1.substr(r));
168 nNode->addEdge(tNode);
174169 }
175 } else
176 nEdge = cNode->addEdge(s1);
177 }
178
179 Node* tNode = addNode(data);
180 nEdge->setChild(tNode);
170 } else {
171 tNode = addNode(data, s1);
172 cNode->addEdge(tNode);
173 }
174 }
181175
182176 return true;
183177 }
188182 std::string s1(s);
189183
190184 while (tNode == NULL) {
191 if (cNode->Edges.count(s1[0])) {
192 Edge& cEdge = cNode->Edges[s1[0]];
193 typename Edge::QueryResult r = cEdge.query(s1);
185 if (cNode->Children.count(s1[0])) {
186 Node* nNode = cNode->Children[s1[0]];
187 typename Node::QueryResult r = nNode->query(s1);
194188
195189 switch (r) {
196 case Edge::Same:
197 tNode = cEdge.getChild();
190 case Node::Same:
191 tNode = nNode;
198192 break;
199 case Edge::StringIsPrefix:
193 case Node::StringIsPrefix:
200194 return Empty;
201 case Edge::DontMatch:
195 case Node::DontMatch:
202196 assert(0 && "Impossible!");
203197 return Empty;
204 case Edge::LabelIsPrefix:
205 s1 = s1.substr(cEdge.getLabel().length());
206 cNode = cEdge.getChild();
198 case Node::LabelIsPrefix:
199 s1 = s1.substr(nNode->getLabel().length());
200 cNode = nNode;
207201 break;
208202 default:
209203 return Empty;