c++ 字典树
实现插入和查询
#include <iostream> #include <string> #include <vector> #include <algorithm> #include <stdexcept> using namespace std; struct Node { bool isWord;//判断当前字母是否为单词的最后一个字母标识 Node *next[26];//26叉 Node() { isWord = false; for (int i = 0; i != 26; ++i) { next[i] = NULL;//清空26叉 } } }; class DicTree { public: Node *root;//根节点 DicTree() { root = NULL;//在构造函数中初始化 } void Insert(string str) { if (!root) { root = new Node;//如果root现在不空,需要重新开辟一个根节点 } Node *head = root;//根节点不能变,找一个新的指针指向根节点方便操作 for (long int i = 0; i != str.length(); ++i) { int num = str[i] - 'a';//获取当前字母应该存储的位置 if (head->next[num] == NULL) { head->next[num] = new Node; } head = head->next[num]; } head->isWord = true; } bool Search(string str) { Node *head = root; for (long int i = 0; i != str.length(); ++i) { int num = str[i] - 'a'; if (head->next[num] == NULL) { return false; } else { head = head->next[num]; } } return head->isWord; } }; int main(int argc, const char * argv[]) { string inp1; DicTree A; while (cin >> inp1, inp1 != "quit") { A.Insert(inp1); } cout << "-----------------------------" << endl; cout << "input end" << endl; cout << "-----------------------------" << endl; string inp2; while (cin >> inp2, inp2 != "quit") { bool res = A.Search(inp2); cout << res << endl; } system("pause"); return 0; }
完整版实现
#include <queue> #include <iostream> using namespace std; const int maxs = 26; struct TrieTreeNode { char val; bool isEnd; int childCnt; int prefixCnt; TrieTreeNode *child[maxs]; TrieTreeNode(char _val) :val(_val), isEnd(false), childCnt(0), prefixCnt(0) { memset(child, NULL, sizeof(child));//not 26!! } }; void Insert(TrieTreeNode * root, const char *word) { TrieTreeNode * p = root; for (int i = 0; i < strlen(word); i++) { if (p->child[word[i] - 'a'] == NULL) { p->child[word[i] - 'a'] = new TrieTreeNode(word[i]); p->childCnt++; } p->child[word[i] - 'a']->prefixCnt++; p = p->child[word[i] - 'a']; } p->isEnd = true; } bool find(TrieTreeNode * root, const char * word) { TrieTreeNode * p = root; int len = strlen(word); for (int i = 0; i < len; i++) { int c = word[i] - 'a'; if (p->child[c] == NULL) { return false; } p = p->child[c]; } return p->isEnd; } void levelOrderTraverse(TrieTreeNode * root) { if (root == NULL) return; queue<TrieTreeNode *> q; q.push(root); while (!q.empty()) { TrieTreeNode *p = q.front(); cout << p->val << "(" << p->childCnt << ")"; for (int i = 0; i < maxs; i++) { if (p->child[i] != NULL) { q.push(p->child[i]); } } q.pop(); } cout << endl; } void preOrderTraverse(TrieTreeNode * treeNode) { if (treeNode != NULL) { cout << treeNode->val << "(" << treeNode->childCnt << ")"; for (int i = 0; i < maxs; i++) { preOrderTraverse(treeNode->child[i]); } } } void PostOrderTraverse(TrieTreeNode * treeNode) { if (treeNode != NULL) { for (int i = 0; i < maxs; i++) { PostOrderTraverse(treeNode->child[i]); } cout << treeNode->val << "(" << treeNode->childCnt << ")"; } } void makeEmpty(TrieTreeNode * root) { if (root != NULL) { for (int i = 0; i < 26; i++) { makeEmpty(root->child[i]); } delete root; } root = NULL; } void buildTrieTree(TrieTreeNode * root, const char* words[], int n) { for (int i = 0; i < n; i++) { Insert(root, words[i]); } } bool Remove(TrieTreeNode * root, const char *word, int pos, int n) { if (pos == n) { root->isEnd = false; return root->childCnt; } if (root->child[word[pos] - 'a'] == NULL) return false; if (Remove(root->child[word[pos] - 'a'], word, pos + 1, n)) { delete root->child[word[pos] - 'a']; root->child[word[pos] - 'a'] = NULL; root->prefixCnt--; if (--root->childCnt == 0 && root->isEnd == false) { return true; } } return false; } int countWordsWithPrefix(TrieTreeNode * root, const char *prefix) { TrieTreeNode *p = root; for (int i = 0; i < strlen(prefix); i++) { if (p->child[prefix[i] - 'a'] == NULL) { return 0; } p = p->child[prefix[i] - 'a']; } return p->prefixCnt; } int main() { TrieTreeNode *root = new TrieTreeNode('\0'); const char *words[] = { "abc", "ad", "ef" }; buildTrieTree(root, words, sizeof(words) / sizeof(words[0])); levelOrderTraverse(root); cout << '\n'; preOrderTraverse(root); cout << '\n'; PostOrderTraverse(root); cout << "\n"; if (find(root, "ef")) cout << "ef found" << endl; else cout << "ef not found" << endl; Insert(root, "e"); levelOrderTraverse(root); Remove(root, "ef", 0, strlen("ef")); levelOrderTraverse(root); Remove(root, "e", 0, strlen("e")); levelOrderTraverse(root); cout << countWordsWithPrefix(root, "a") << endl; Remove(root, "ad", 0, strlen("ad")); cout << countWordsWithPrefix(root, "a") << endl; makeEmpty(root); system("pause"); return 0; }