【第22期】观点:IT 行业加班,到底有没有价值?

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;
}


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

相关文章推荐

BZOJ 3261 浅谈可持久化TRIE树最大连续异或和

世界真的很大 trie树贪心求最大异或和大概也就是那么回事了 但是对于区间的查询就不是那么容易的了 考虑主席树的思想,怎么得到区间的值域的 这就是可持久化的trie树 说来容易 指针教做人...

┎结构之美┒之Trie树

博主今天新开一系列写“结构”,简单的单链表,普通队列,普通栈,普通二叉树就不写了,今天从Trie树写起。 Trie树(又叫字典树,前缀树,单词查找树,键树)是一种树形数据结构,直接来看图: 我们来看看Trie树的特点:根节点为空值,剩下每一个节点保存一个字母。知道这些就够了! 我们再来看看...

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

异或(今日头条2017秋招真题)Trie树

Trie树

trie tree 字典树

摘自:http://blog.sina.com.cn/s/blog_4d3a41f40100f4z7.html 今天AC了两题trie tree的题目,感觉trie的性质真的是相当的好,而且实现比较简单。它使在字符串集合中查找某个字符串的操作的复杂度降到最大只需O(n),其中n为字符串的长...

双数组Trie树(DoubleArrayTrie)Java实现

双数组Trie树(DoubleArrayTrie)是一种空间复杂度低的Trie树,应用于字符区间大的语言(如中文、日文等)分词领域。 双数组Trie (Double-Array Trie)结构由日...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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