本文地址:http://blog.csdn.net/spch2008/article/details/9138557
使用字典树来存储数据,数据是一个键值对,即键值-数值。
字典树允许数据键值共享相同的前缀。本文采用的键值为字符串,数据如下:amy 56 ann 15 emma 30 rob 27 roger 52首先存入amy, level 0表示根,不持有数据。其余每个节点持有一个字符;叶子节点持有数据,且持有的字符为'\0'
. <- level 0 (root) | a <- level 1 | m <- level 2 | y <- level 3 | \0 56 <- level 4添加ann后,后缀树如下,二者共享前缀'a'
. | a / \ m n | | y n | | \0 56 \0 15下面加入emma,由于emma与之前添加的键值没有相同前缀,所以直接加入根节点下。
. / \ a e / \ | m n m | | | y n m | | | \0 56 \0 15 a | \0 30将rob与roger加入后,所得字典树如下:
. / | \ a e r / \ | | m n m o | | | / \ y n m b g | | | | | \0 56 \0 15 a \0 27 e | | \0 30 r | \0 52
| a --------- e ----- r | | | m --- n m o | | | | y n m b ----- g | | | | | \0 56 \0 15 a \0 27 e | | \0 30 r | \0 52
.h
class TrieTree { private: struct Node { char key; int val; Node *next, *child; Node(char k =' ', int v = 0) { key = k; val = v; next = child = NULL; } }; public: TrieTree(void); ~TrieTree(void); bool IsMember(char str[]); void Add(char str[], int val); void Remove(char str[]); int GetVal(char str[]); private: Node *root; Node* _Insert(Node* subtree, char *str, int val); Node* _CreateSubTree(char *str, int val); Node* _Delete(Node* subtree, char *str); Node* _Find(char *str); void _Destroy(Node* subtree); };
.cpp
TrieTree::TrieTree(void) { root = new Node; root->next = root->child = NULL; } TrieTree::~TrieTree(void) { _Destroy(root); } bool TrieTree::IsMember(char str[]) { Node *found = _Find(str); return found != NULL; } void TrieTree::Add(char str[], int val) { root->next = _Insert(root->next, str, val); } void TrieTree::Remove(char str[]) { root->next = _Delete(root->next, str); } int TrieTree::GetVal(char str[]) { Node *found = _Find(str); if(found == NULL) return -1; else return found->val; } TrieTree::Node* TrieTree::_Insert(Node* subtree, char *str, int val) { if(subtree == NULL) { subtree = _CreateSubTree(str, val); } else if(subtree->key != str[0]) { subtree->next = _Insert(subtree->next, str, val); } else { if(str[0] == '\0') //修改原值 subtree->val = val; else subtree->child = _Insert(subtree->child, &str[1], val); } return subtree; } void TrieTree::_Destroy(Node *subtree) { if(subtree != NULL) { _Destroy(subtree->child); _Destroy(subtree->next); delete subtree; } } TrieTree::Node* TrieTree::_Find(char *str) { int index = 0; Node *level = root->next; while(true) { Node *found = NULL; //当前层匹配 for(Node *curr = level; curr != NULL; curr = curr->next) { if(curr->key == str[index]) { found = curr; break; } } if(found == NULL) return NULL; //不能found->key == str[index] //str可以先匹配完成 if(str[index] == '\0') return found; //匹配上后,向下在孩子中匹配 level = found ->child; index += 1; } return NULL; } TrieTree::Node* TrieTree::_Delete(Node* subtree, char *str) { if(subtree == NULL) return NULL; if(subtree->key != str[0]) { subtree->next = _Delete(subtree->next, str); } else { if(subtree->key == '\0') { delete subtree; subtree = NULL; } else { subtree->child = _Delete(subtree->child, &str[1]); if(subtree->next == NULL && subtree->child == NULL) { delete subtree; subtree = NULL; } } } return subtree; } TrieTree::Node * TrieTree::_CreateSubTree(char *str, int val) { Node *subtree = new Node('\0', val); for(int i = strlen(str) - 1; i >= 0; i--) { Node *node = new Node(str[i]); node->child = subtree; subtree = node; } return subtree; }
来自:http://www.cs.bu.edu/teaching/c/tree/trie/