trie树(字典树)

来源:互联网 发布:腹部脂肪如何减 知乎 编辑:程序博客网 时间:2024/05/18 16:40

1. trie树,又名字典树,顾名思义,它是可以用来作字符串查找的数据结构,它的查找效率比散列表还要高。

trie树的建树:

比如有字符串”ab” ,“adb”,“adc”   可以建立字典树如图:





    树的根节点head不存储信息,它有26个next指针,分别对应着字符a,b,c等。插入字符串ab时,next[‘a’-‘a’]即next[0]为空,这是申请一个结点放在next[0]的位置,插入字符串db时,next[‘d’-‘a’]即next[3]为空,这时申请一个结点tmp放在next[3]的位置,接下来,tmp的后向结点tmp->next[‘a’-‘a’]即tmp->next[0]为空,在申请一个结点放在tmp->next[0]的位置。  插入字符串dc时,检查head->next[3]不为空,然后检查tmp->next[2]为空,这时申请一个结点放在tmp->next[2]的位置。

    字典树的建树过程就是字符串不断插入的过程。

    字典树的查找可以按照如下步骤进行:比如查找字符串”dc”,先检查head->next[3]是否为空,如果为空返回,若不为空,再检查下个结点的next[2]是否为空,如果为空返回

 2. 字典树的应用

(1)用于查字符串的字典树:

用于查找字符串的字典树,输的结点结构体可以定义为:

struct node{bool isword;node *next[26];};
其中isword用于判断从根节点到此结点是否构成一个单词,next数组用于指示26个结点指针,这里假定所有单词都使用小写英文字母来表示。

# include <iostream># include <cstdlib># include <cstring>using namespace std;struct node{bool isword;node *next[26];};node *head=NULL;void insert(char s[]){node *p=head;int len=strlen(s);int i=0;for(i=0;i<len;i++){if(p->next[s[i]-'a']==NULL){node *tmp=(node *)malloc(sizeof(node));tmp->isword=false;int j=0;for(j=0;j<26;j++)tmp->next[j]=NULL;p->next[s[i]-'a']=tmp;p=tmp;}elsep=p->next[s[i]-'a'];}p->isword=true;}int find(char *s){node *p=head;if(p==NULL)return 0;while(p!=NULL&&*s!='\0'){if(p->next[(*s)-'a']){p=p->next[(*s)-'a'];s++;}elsereturn 0;}return (p!=NULL&&(*s)=='\0'&&p->isword==true);}void destroy(node *head){if(head!=NULL){int i;for(i=0;i<26;i++){    if(head->next[i]!=NULL)destroy(head->next[i]);}free(head);}}int main(void){head=(node *)malloc(sizeof(node));head->isword=false;int i=0;for(;i<26;i++)head->next[i]=NULL;char s1[20]="hello";char s2[20]="world";char s3[20]="hell";insert(s2);insert(s1);cout<<find(s1)<<endl;destroy(head);system("pause");return 0;}

(2)用于统计前缀出现次数的字典树

用于统计前缀出现次数的字典树,其树的结点结构体可以定义如下:

struct node{int num;node *next[26];};
其中num为这个本前缀出现的次数,next数组表示的含义与上面类似。

# include <iostream># include <string># include <cstdlib>using namespace std;struct node{int num;node *next[26];};node *head=0;int main(){char s[20];void insert(char a[]);int find(char a[]);void destroy(node *head);int i;head=new node;for(i=0;i<26;i++)head->next[i]=NULL;cout<<"input words and terminate by '#'"<<endl;while(cin>>s&&s[0]!='#'){insert(s);}cout<<"input the prefix"<<endl;cin>>s;cout<<"the number is"<<endl;cout<<find(s)<<endl;destroy(head);system("pause");return 0;}void insert(char a[]){node *s=head;int i;int len=strlen(a);for(i=0;i<len;i++){int k=a[i]-'a';if(s->next[k]==NULL){node *tmp=new node;tmp->num=1;int j=0;for(j=0;j<26;j++)tmp->next[j]=NULL;s->next[k]=tmp;s=s->next[k];}else{s=s->next[k];s->num++;}}}int  find(char a[]){int i;int len=strlen(a);int count=0;node *s=head;for(i=0;i<len;i++){int k=a[i]-'a';if(s->next[k]==NULL){count=0;return count;}else{s=s->next[k];count=s->num;}}return count;}void destroy(node *head){if(head!=NULL){int i;for(i=0;i<26;i++){    if(head->next[i]!=NULL)destroy(head->next[i]);}free(head);}}

(3)用于字符串排序的字典树

用于字符串排序的字典树,树的结点结构体可以定义如下:

struct node{int count;char *s;node *next[26];};
其中count用于保存某个字符串出现的次数,s用于保存到本节点为止的字符串,next数组含义与前面的类似。

# include <iostream># include <cstdlib># include <cstring>using namespace std;int cnt=0;struct node{int count;char *s;node *next[26];};node *head=NULL;void insert(char str[]){node *p=head;int len=strlen(str);int i=0;for(;i<len;i++){if(p->next[str[i]-'a']==NULL){node *tmp=(node *)malloc(sizeof(node));tmp->count=0;tmp->s=(char *)malloc(50*sizeof(char));int j;for(j=0;j<26;j++)tmp->next[j]=NULL;strcpy(tmp->s,p->s);//strcat(tmp->s,p->s);//strcat(tmp->s,str[i]);//strcat(tmp->s,'\0');char ctmp[2]={str[i],'\0'};strcat(tmp->s,ctmp);p->next[str[i]-'a']=tmp;p=tmp;}elsep=p->next[str[i]-'a'];}p->count++;}void sort(node *head,char **str){if(head!=NULL){if(head->count>0){for(int i=0;i<head->count;i++)str[cnt++]=head->s;}for(int j=0;j<26;j++)sort(head->next[j],str);}}void destroy(node *head){if(head!=NULL){int i;for(i=0;i<26;i++){    if(head->next[i]!=NULL)destroy(head->next[i]);}free(head);}}int main(void){head=(node *)malloc(sizeof(node));int i=0;for(i=0;i<26;i++)head->next[i]=NULL;head->count=0;head->s=(char *)malloc(50*sizeof(char));head->s[0]='\0';char s1[20]="hello";char s2[20]="world";char s3[20]="helloa";char *str[3]={s1,s2,s3};insert(str[0]);insert(str[1]);insert(str[2]);sort(head,str);cout<<str[0]<<endl;cout<<str[1]<<endl;cout<<str[2]<<endl;destroy(head);system("pause");return 0;}

0 0
原创粉丝点击