Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef _TRIE_H
00024 #define _TRIE_H
00025
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029
00030 #include "List.h"
00031
00032
00033
00034 template<typename T>
00035 class Trie
00036 {
00037 public:
00038 Trie()
00039 {
00040 m_root.Clear();
00041 }
00042
00043
00044
00045 bool Insert(const char *key, T *value, int rank, int key_len = -1);
00046
00047
00048 T* Search(const char *key, int key_len = -1) const;
00049 void Clear();
00050 void Print();
00051
00052 bool Empty() const { return m_value_list.empty(); }
00053
00054 virtual ~Trie() { Clear(); }
00055
00056 private:
00057 static const int N_NODE_CHILDREN = 256;
00058
00059 class Node
00060 {
00061 public:
00062 T* value;
00063 bool occupied;
00064 int rank;
00065
00066 void Clear() {
00067 value = NULL;
00068 occupied = false;
00069 rank = 0;
00070 ink_zero(children);
00071 }
00072
00073 void Print(const char *debug_tag) const;
00074 inline Node* GetChild(char index) const { return children[static_cast<unsigned char>(index)]; }
00075 inline Node* AllocateChild(char index) {
00076 Node * &child = children[static_cast<unsigned char>(index)];
00077 ink_assert(child == NULL);
00078 child = static_cast<Node*>(ats_malloc(sizeof(Node)));
00079 child->Clear();
00080 return child;
00081 }
00082
00083 private:
00084 Node *children[N_NODE_CHILDREN];
00085 };
00086
00087 Node m_root;
00088 Queue<T> m_value_list;
00089
00090 void _CheckArgs(const char *key, int &key_len) const;
00091 void _Clear(Node *node);
00092
00093
00094
00095 Trie(const Trie<T> &rhs) { };
00096 Trie &operator =(const Trie<T> &rhs) { return *this; }
00097 };
00098
00099 template<typename T>
00100 void
00101 Trie<T>::_CheckArgs(const char *key, int &key_len) const
00102 {
00103 if (!key) {
00104 key_len = 0;
00105 }
00106 else if (key_len == -1) {
00107 key_len = strlen(key);
00108 }
00109 }
00110
00111 template<typename T>
00112 bool
00113 Trie<T>::Insert(const char *key, T* value, int rank, int key_len )
00114 {
00115 _CheckArgs(key, key_len);
00116
00117 Node *next_node;
00118 Node *curr_node = &m_root;
00119 int i = 0;
00120
00121 while (true) {
00122 if (is_debug_tag_set("Trie::Insert")) {
00123 Debug("Trie::Insert", "Visiting Node...");
00124 curr_node->Print("Trie::Insert");
00125 }
00126
00127 if (i == key_len) {
00128 break;
00129 }
00130
00131 next_node = curr_node->GetChild(key[i]);
00132 if (!next_node) {
00133 while (i < key_len) {
00134 Debug("Trie::Insert", "Creating child node for char %c (%d)", key[i], key[i]);
00135 curr_node = curr_node->AllocateChild(key[i]);
00136 ++i;
00137 }
00138 break;
00139 }
00140 curr_node = next_node;
00141 ++i;
00142 }
00143
00144 if (curr_node->occupied) {
00145 Debug("Trie::Insert", "Cannot insert duplicate!");
00146 return false;
00147 }
00148
00149 curr_node->occupied = true;
00150 curr_node->value = value;
00151 curr_node->rank = rank;
00152 m_value_list.enqueue(curr_node->value);
00153 Debug("Trie::Insert", "inserted new element!");
00154 return true;
00155 }
00156
00157 template<typename T>
00158 T*
00159 Trie<T>::Search(const char *key, int key_len ) const
00160 {
00161 _CheckArgs(key, key_len);
00162
00163 const Node *found_node = 0;
00164 const Node *curr_node = &m_root;
00165 int i = 0;
00166
00167 while (curr_node) {
00168 if (is_debug_tag_set("Trie::Search")) {
00169 Debug("Trie::Search", "Visiting node...");
00170 curr_node->Print("Trie::Search");
00171 }
00172 if (curr_node->occupied) {
00173 if (!found_node || curr_node->rank <= found_node->rank) {
00174 found_node = curr_node;
00175 }
00176 }
00177 if (i == key_len) {
00178 break;
00179 }
00180 curr_node = curr_node->GetChild(key[i]);
00181 ++i;
00182 }
00183
00184 if (found_node) {
00185 Debug("Trie::Search", "Returning element with rank %d", found_node->rank);
00186 return found_node->value;
00187 }
00188
00189 return NULL;
00190 }
00191
00192
00193 template<typename T>
00194 void
00195 Trie<T>::_Clear(Node *node)
00196 {
00197 Node *child;
00198
00199 for (int i = 0; i < N_NODE_CHILDREN; ++i) {
00200 child = node->GetChild(i);
00201 if (child) {
00202 _Clear(child);
00203 ats_free(child);
00204 }
00205 }
00206 }
00207
00208 template<typename T>
00209 void
00210 Trie<T>::Clear()
00211 {
00212 T* iter;
00213 while (NULL != (iter = m_value_list.pop()))
00214 delete iter;
00215
00216 _Clear(&m_root);
00217 m_root.Clear();
00218 }
00219
00220 template<typename T>
00221 void
00222 Trie<T>::Print() {
00223
00224 forl_LL(T, iter, m_value_list)
00225 iter->Print();
00226 }
00227
00228 template<typename T>
00229 void
00230 Trie<T>::Node::Print(const char *debug_tag) const
00231 {
00232 if (occupied) {
00233 Debug(debug_tag, "Node is occupied");
00234 Debug(debug_tag, "Node has rank %d", rank);
00235 } else {
00236 Debug(debug_tag, "Node is not occupied");
00237 }
00238
00239 for (int i = 0; i < N_NODE_CHILDREN; ++i) {
00240 if (GetChild(i)) {
00241 Debug(debug_tag, "Node has child for char %c", static_cast<char>(i));
00242 }
00243 }
00244 }
00245
00246 #endif // _TRIE_H