zoukankan      html  css  js  c++  java
  • trie树(字典树)

    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;
    	}
    	else
    		p=p->next[s[i]-'a'];
    }
    p->isword=true;
    }
    
    int find(char *s)
    {
    node *p=head;
    if(p==NULL)
    	return 0;
    while(p!=NULL&&*s!='')
    {
    	if(p->next[(*s)-'a']){
    		p=p->next[(*s)-'a'];
    		s++;
    	}
    	else
    		return 0;
    }
    return (p!=NULL&&(*s)==''&&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,'');
    	char ctmp[2]={str[i],''};
    	strcat(tmp->s,ctmp);
    	p->next[str[i]-'a']=tmp;
    	p=tmp;
    	}
    	else
    		p=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]='';
    	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;
    }

  • 相关阅读:
    Mysql系列【解决mysql连接数太多】
    并发编程系列【线程池七大核心参数】
    C信号处理的基础
    设计模式之Command
    Ext文件系统
    内存管理
    设计模式之Decorator Pattern
    设计模式之singleton
    Quicklz压缩算法
    设计模式之Factory
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6964176.html
Copyright © 2011-2022 走看看