字典树萌新总结
具体参考:http://www.cnblogs.com/tanky_woo/archive/2010/09/24/1833717.html
字典树(Trie树):
利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。
引入一张图片:
利用公共前缀;
Trie树的定义:
struct Trie{ Trie* next[LENGTH]; //每层有多少种类,例如:数字(10种),字母(26种); int num; //表示字典树到此有多少种前缀的数量, //可以根据不同的需求增加; };
Trie树的基本操作:
(1): 创建(插入);
(2): 查找;
Trie树的创建:先讲动态;
创建:
void Creat(char *str,Trie *root) { int len=strlen(str); Trie *p,*q; p=root; for(int i=0;i<len;i++) { int id=str[i]-'a';//默认存的是字母 if(p->next[id]==NULL) //如果这个字母所在的这一层没有; { q=(Trie *)malloc(sizeof(Tire));//那么就创一个点,并初始化 q->num=1; for(int j=0;j<26;j++) q->next[j]=NULL; p->next[id]=q; p=p->next[id]; } } q->num=-1;//用于标记,表示一个单词的结束 }
bool Find(char *str,Trie *root) { int len=strlen(str); Trie *q; q=root; for(int i=0;i<len;i++) { int id=str[i]-'a'; q=q->next[id]; if(q==NULL) //表明不存在 return false; if(q->num==-1) //表明查询到了终点,该字符串就是字典序中的某串; return true; } return true; //表明字典树的某串是该字符串的前缀 }
ACM竞赛中,考虑到效率问题,常用静态。
其实我们知道动态和静态的区边就是
静态就是提前一下子把要用的给全部申请了,然后用到的时候再直接拿,不用申请了,效率高;
我们可以很方便的改变一点就行了,就是存的地方嘛
定义:
<span style="font-size:18px;">struct Trie{ Trie* next[LENGTH]; //每层有多少种类,例如:数字(10种),字母(26种); int num; //表示字典树到此有多少种前缀的数量, //可以根据不同的需求增加; }; Trie q[N];<span style="white-space:pre"> </span>//用数组存储; int tol;<span style="white-space:pre"> </span>//节点数;</span>创建:
只要返回一个结点就好了;
Trie* Creat() { Trie *p; p=&q[tol];<span style="white-space:pre"> </span>//直接调用就好了; tol++;<span style="white-space:pre"> </span>//节点数++ p->num=1; for(int i=0;i<26;i++) p->next[i]=NULL; return p; }这种静态的写法和动态差不多,感觉也是比较方便可懂;
最后,拿几题基础题练练手吧;
最后:
balabalabalabalabalabalabalabalabalabalabalabalabalabalabalabalabalabalabalabalabalabala~~~~~萌新系列下次见~~~~balabalabalabalabalabalabalabalabalabalabalabalabalabalabalabala~~~