转自:http://blog.csdn.net/insistgogo/article/details/7828851
作者: insistGoGo
一、定义:
Trie,又称字典树,是一种用于快速检索的二十六叉树结构。典型的空间换时间
二、结构图:
三、原理:
Trie把要查找的关键词看作一个字符序列,并根据构成关键词字符的先后顺序检索树结构;
特别地:和二叉查找树不同,在Trie树中,每个结点上并非存储一个元素。
四、性质:
0、利用串的公共前缀,节约内存
1、在trie树上进行检索总是始于根结点
2、根节点不包含字符,除根节点外的每一个节点都只代表一个字母,这里不是包含。
3、从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
4、每个节点的所有子节点包含的字符都不相同。
五、效率分析
0、当存储大量字符串时,Trie耗费的空间较少。因为键值并非显式存储的,而是与其他键值共享子串。
1、查询快。在trie树中查找一个关键字的时间和树中包含的结点数无关,而取决于组成关键字的字符数。对于长度为m的键值,最坏情况下只需花费O(m)的时间(对比:二叉查找树的查找时间和树中的结点数有关O(log2n)。)
2、如果要查找的关键字可以分解成字符序列且不是很长,利用trie树查找速度优于二叉查找树。
3、若关键字长度最大是5,则利用trie树,利用5次比较可以从265=11881376个可能的关键字中检索出指定的关键字。而利用二叉查找树至少要进行log2265=23.5次比较。
六、应用:用于字符串的统计与排序,经常被搜索引擎系统用于文本词频统计。
1、字典树在串的快速检索中的应用。
给出N个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。在这道题中,我们可以用字典树,先把熟词建一棵树,然后读入文章进行比较,这种方法效率是比较高的。
2、字典树在“串”排序方面的应用
给定N个互不相同的仅由一个单词构成的英文名,让你将他们按字典序从小到大输出用字典树进行排序,采用数组的方式创建字典树,这棵树的每个结点的所有儿子很显然地按照其字母大小排序。对这棵树进行先序遍历即可。
3.、字典树在最长公共前缀问题的应用
对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数,于是,问题就转化为最近公共祖先问题。
代码
- #ifndef _TRIE_
- #define _TRIE_
-
- #include <iostream>
- #include <fstream>
- #include <string>
- #include <algorithm>
- #include <assert.h>
- using namespace std;
- const int MaxBranchNum = 26;
-
-
- class TrieNode
- {
- public:
- char* word;
- int count;
- TrieNode* nextBranch[MaxBranchNum];
- public:
- TrieNode() : word(NULL),count(0)
- {
- memset(nextBranch,NULL,sizeof(TrieNode*) * MaxBranchNum);
- }
- };
-
-
- class Trie
- {
- public:
- Trie();
- ~Trie();
- void Insert(const char* str);
- bool Search(const char* str,int& count);
- bool Remove(const char* str);
- void PrintALL();
- void PrintPre(const char* str);
- private:
- TrieNode* pRoot;
- private:
- void Destory(TrieNode* pRoot);
- void Print(TrieNode* pRoot);
- };
-
- #endif //_TRIE_
-
- Trie::Trie()
- {
- pRoot = new TrieNode();
- }
-
- Trie::~Trie()
- {
- Destory(pRoot);
- }
-
-
- void Trie::Insert(const char* str)
- {
- assert(NULL != str);
- int index;
- TrieNode* pLoc = pRoot;
- for (int i = 0;str[i];i++)
- {
- index = str[i] - 'a';
-
- if(index < 0 || index > MaxBranchNum)
- {
- return;
- }
-
- if (NULL == pLoc->nextBranch[index])
- {
- pLoc->nextBranch[index] = new TrieNode();
- }
- pLoc = pLoc->nextBranch[index];
- }
- if (NULL != pLoc->word)
- {
- pLoc->count++;
- return;
- }
- else
- {
- pLoc->count++;
- pLoc->word = new char[strlen(str) + 1];
- assert(NULL != pLoc->word);
- strcpy(pLoc->word,str);
- }
- }
-
-
- bool Trie::Search(const char* str,int& count)
- {
- assert(str != NULL);
- int i = 0;
- int index = -1;;
- TrieNode* pLoc = pRoot;
- while(pLoc && *str)
- {
- index = *str - 'a';
-
- if(index < 0 || index > MaxBranchNum)
- {
- return false;
- }
-
- pLoc = pLoc->nextBranch[index];
- str++;
- }
- if (pLoc && pLoc->word)
- {
- count = pLoc->count;
- return true;
- }
- return false;
- }
-
- bool Trie::Remove(const char* str)
- {
- assert(NULL != str);
- int index = -1;;
- TrieNode* pLoc = pRoot;
- while(pLoc && *str)
- {
- index = *str - 'a';
-
- if(index < 0 || index > MaxBranchNum)
- {
- return false;
- }
-
- pLoc = pLoc->nextBranch[index];
- str++;
- }
- if (pLoc && pLoc-> word)
- {
- delete[] pLoc->word;
- pLoc->word = NULL;
- return true;
- }
- return false;
- }
-
- void Trie::PrintALL()
- {
- Print(pRoot);
- }
-
- void Trie::PrintPre(const char* str)
- {
- assert(str != NULL);
- int i = 0;
- int index = -1;;
- TrieNode* pLoc = pRoot;
- while(pLoc && *str)
- {
- index = *str - 'a';
-
- if(index < 0 || index > MaxBranchNum)
- {
- return;
- }
-
- pLoc = pLoc->nextBranch[index];
- str++;
- }
- if (pLoc)
- {
- Print(pLoc);
- }
- }
-
-
- void Trie::Print(TrieNode* pRoot)
- {
- if (NULL == pRoot)
- {
- return;
- }
-
- if (NULL != pRoot->word)
- {
- cout<<pRoot->word<<" "<<pRoot->count<<endl;
- }
-
- for (int i = 0;i < MaxBranchNum;i++)
- {
- Print(pRoot->nextBranch[i]);
- }
- }
-
-
- void Trie::Destory(TrieNode* pRoot)
- {
- if (NULL == pRoot)
- {
- return;
- }
- for (int i = 0;i < MaxBranchNum;i++)
- {
- Destory(pRoot->nextBranch[i]);
- }
-
- if (NULL != pRoot->word)
- {
- delete []pRoot->word;
- pRoot->word = NULL;
- }
- delete pRoot;
- pRoot = NULL;
- }
-
- int main()
- {
- Trie t;
- string str;
- int count = -1;
- ifstream in("word.txt");
-
- while(in >> str)
- {
- transform(str.begin(),str.end(),str.begin(),tolower);
- t.Insert(str.c_str());
- }
-
- bool isFind = t.Search("the",count);
- if (isFind)
- {
- cout<<"存在the,出现次数:"<<count<<endl;
- }
- else
- {
- cout<<"不存在the!"<<endl;
- }
-
- t.PrintALL();
-
- bool isDel = t.Remove("the");
- if (isDel)
- {
- cout<<"删除成功!"<<endl;
- }
- else
- {
- cout<<"删除失败!"<<endl;
- }
-
- t.PrintPre("w");
- cout<<endl;
- system("pause");
- }