Trie树

原创 2015年07月07日 09:40:04

在Trie树中主要有3个操作,插入、查找和删除。一般情况下Trie树中很少存在删除单独某个结点的情况,因此只考虑删除整棵树。

1.插入

  假设存在字符串str,Trie树的根结点为root。i=0,p=root。

  1)取str[i],判断p->next[str[i]-97]是否为空,若为空,则建立结点temp,并将p->next[str[i]-97]指向temp,然后p指向temp;

   若不为空,则p=p->next[str[i]-97];

  2)i++,继续取str[i],循环1)中的操作,直到遇到结束符'\0',此时将当前结点p中的isStr置为true。

2.查找

  假设要查找的字符串为str,Trie树的根结点为root,i=0,p=root

  1)取str[i],判断判断p->next[str[i]-97]是否为空,若为空,则返回false;若不为空,则p=p->next[str[i]-97],继续取字符。

  2)重复1)中的操作直到遇到结束符'\0',若当前结点p不为空并且isStr为true,则返回true,否则返回false。

3.删除

  删除可以以递归的形式进行删除。

#include <iostream>
#include<cstdlib>
#define MAX 26
using namespace std;
 
typedef struct TrieNode                     //Trie结点声明 
{
    bool isStr;                            //标记该结点处是否构成单词 
    struct TrieNode *next[MAX];            //儿子分支 
}Trie;
 
void insert(Trie *root,const char *s)     //将单词s插入到字典树中 
{
    if(root==NULL||*s=='\0')
        return;
    int i;
    Trie *p=root;
    while(*s!='\0')
    {
        if(p->next[*s-'a']==NULL)        //如果不存在,则建立结点 
        {
            Trie *temp=(Trie *)malloc(sizeof(Trie));
            for(i=0;i<MAX;i++)
            {
                temp->next[i]=NULL;
            }
            temp->isStr=false;
            p->next[*s-'a']=temp;
            p=p->next[*s-'a'];   
        }   
        else
        {
            p=p->next[*s-'a'];
        }
        s++;
    }
    p->isStr=true;                       //单词结束的地方标记此处可以构成一个单词 
}
 
int search(Trie *root,const char *s)  //查找某个单词是否已经存在 
{
    Trie *p=root;
    while(p!=NULL&&*s!='\0')
    {
        p=p->next[*s-'a'];
        s++;
    }
    return (p!=NULL&&p->isStr==true);      //在单词结束处的标记为true时,单词才存在 
}
 
void del(Trie *root)                      //释放整个字典树占的堆区空间 
{
    int i;
    for(i=0;i<MAX;i++)
    {
        if(root->next[i]!=NULL)
        {
            del(root->next[i]);
        }
    }
    free(root);
}
 
int main(int argc, char *argv[])
{
    int i;
    int n,m;                              //n为建立Trie树输入的单词数,m为要查找的单词数 
    char s[100];
    Trie *root= (Trie *)malloc(sizeof(Trie));
    for(i=0;i<MAX;i++)
    {
        root->next[i]=NULL;
    }
    root->isStr=false;
    scanf("%d",&n);
    getchar();
    for(i=0;i<n;i++)                 //先建立字典树 
    {
        scanf("%s",s);
        insert(root,s);
    }
    while(scanf("%d",&m)!=EOF)
    {
        for(i=0;i<m;i++)                 //查找 
        {
            scanf("%s",s);
            if(search(root,s)==1)
                printf("YES\n");
            else
                printf("NO\n");
        }
        printf("\n");   
    }
    del(root);                         //释放空间很重要 
    return 0;
}


Hdu 1075

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MAX 30
typedef struct Trie   
{   
    Trie *next[MAX];   
    int v;   //根据需要变化
};   
 
Trie root;
char str[35000];
char len[35000];
void createTrie(char *str,int wei)
{
    int len = strlen(str);
    Trie *p = &root, *q;
    for(int i=0; i<len; ++i)
    {
        int id = str[i]-'a';
        if(p->next[id] == NULL)
        {
            q = (Trie *)malloc(sizeof(Trie));
            q->v = -1;    //把不是字符串最后一个的v 都初始化为-1
            for(int j=0; j<MAX; ++j)
                q->next[j] = NULL;
            p->next[id] = q;
            p = p->next[id];
        }
        else
        {
            p = p->next[id];
        }
    }
    p->v = wei;   //若为结尾,则将v改成wei表示这串字符串对应的字符串在arr中的下标
}

int findTrie(char *str)
{
    int len = strlen(str);
    Trie *p = &root;
    for(int i=0; i<len; ++i)
    {
        int id = str[i]-'a';
        p = p->next[id];
        if(p == NULL)   //已经找不到第i+1个字母了,所以不存在这个字符串
            return -1;
        if(p->v != -1&&i==len-1)   
            return p->v;
    }
    return -1;   //此串是字符集中某串的前缀
}
char arr[500000][15];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("output.txt","w",stdout);
#endif
    int n;
    scanf("%s",str);
    for(int i=0;;i++)
    {
        scanf("%s",arr[i]);
        if(strcmp(arr[i],"END")==0)
        {
            scanf("%s",arr[i]);
            break;
        }
        scanf("%s",str);
        createTrie(str,i);
    }
    getchar();
    char c;
    int p=0;
    while(1)
    { 
        gets(len);
        if(strcmp(len,"END")==0)
            break;
        int nn=strlen(len);
        len[nn]=10;//因为是gets输入没有回车,所以添加一个回车
        len[nn+1]=0;
        for(int i=0;len[i];i++)
        {
            c=len[i];
            if((c<='z'&&c>='a'))
                str[p++]=c;
            else
            {
                str[p]=0;
                int tem=findTrie(str);
                if(tem!=-1)
                    printf("%s%c",arr[tem],c);
                else 
                    printf("%s%c",str,c);
                p=0;
            }
        }
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

DoubleArrayTrie(双数组Trie树)

  • 2015年10月22日 09:57
  • 2.13MB
  • 下载

trie树模板,acm竞赛

  • 2010年03月12日 08:14
  • 2KB
  • 下载

java实现的Trie树数据结构

最近在学习的时候,经常看到使用Trie树数据结构来解决问题,比如“ 有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。” 该如何解决...
  • abcd_d_
  • abcd_d_
  • 2014年10月15日 20:37
  • 5398

trie树实现英语词典

  • 2008年09月15日 15:38
  • 200KB
  • 下载

数据结构之双数组trie树

双数组Tire树定义: 双数组Trie(Double-ArrayTrie)是trie树的一个简单而有效的实现,由两个整数数组构成,一个是base[],另一个是check[]。 base:数组中的每一个...

Trie树 linux32 SDK V3.0

  • 2010年04月18日 17:25
  • 238KB
  • 下载

敏感词过滤与DFA算法Trie树

关键字过滤 trie树

Acm Trie树

  • 2014年04月06日 10:28
  • 45KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Trie树
举报原因:
原因补充:

(最多只允许输入30个字)