• 字典树


    字典树

    又称单词查找树Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高,缺点是内存开销大。 

    字典树与字典很相似,当你要查一个单词是不是在字典树中,首先看单词的第一个字母是不是在字典的第一层,如果不在,说明字典树里没有该单词,如果在就在该字母的孩子节点里找是不是有单词的第二个字母,没有说明没有该单词,有的话用同样的方法继续查找.字典树不仅可以用来储存字母,也可以储存数字等其它数据。

     c语言实现

    #include <stdio.h>
    #include <string.h>
        
    
    #define NodeSize 100 //100000
    #define CHARSIZE 26  //26
    int flag[NodeSize]={0};//是否以该节点结尾,大小为节点数量
    int tree[NodeSize][CHARSIZE];//每一个节点都有26个子节点,如果有大写字母则为52,加上数字就是62
    int cnt=0;//记录已经存储字母的节点数量
    
    void Insert(char s[])
    {
        int root=0;
        int i;
        //遍历
        for(i=0;s[i];i++)
        {    
            //得到0-25范围的整数,代表a-z
            int id=s[i]-'a';
            //判断该节点是否被赋值
            //如果为-1,说明该节点还未存储字母,就需要创建新节点
            if(tree[root][id]==-1) 
            {    
                //创建一个新节点
                tree[root][id]=++cnt;
            }
            //如果存在直接指向这个节点,如果不存在,指向创建的新节点
            //指向的是下标
            root=tree[root][id];
        }
        //设置该节点的结束标志
        flag[root]= 1;
    }
    int Search(char s[])
    {
        int root=0;
        int i;
        for(i=0;s[i];i++)
        {
            int id=s[i]-'a';
            if(tree[root][id]==-1) return 0;
            root=tree[root][id];
        }
        //判断该节点是否为结束标志位
        if(flag[root]){
            return 1;
        }else{
            return 0;
        }
    }
    
    void Init(){
        int i;
        int j;
        for(i=0;i<NodeSize;i++){
            for(j=0;j<CHARSIZE;j++){
                tree[i][j] = -1;
            }
        }
    }
        
        
    int main()
    {
        Init();
        char s1[5] = "fggf";
        char s2[4] = "fbs";
        char s3[6] = "fb";
        //插入字符串
        Insert(s1);
        //插入字符串
        Insert(s2);
        //查找字符串
        int flag = Search(s3);
        if(flag){
            printf("字符串存在");
        }else{
            printf("字符串不存在");
        }
        return 0;
    }

    基本操作

    插入:在字典树中插入单词

    1.每次插入从根节点开始

    int root=0;

    2.遍历单词

     for(i=0;s[i];i++)
        {    
           。。。
        }

    3.得到当前字母在此节点下的位置,每个节点有26个子节点。

    int id=s[i]-'a';

    4.判断该节点是否已经存储字母,如果存储,直接指向该节点,如果没有,新增节点,并指向新增节点。

         //判断该节点是否被赋值
            //如果为-1,说明该节点还未存储字母,就需要创建新节点
            if(tree[root][id]==-1) 
            {    
                //创建一个新节点
                tree[root][id]=++cnt;
            }
            //如果存在直接指向这个节点,如果不存在,指向创建的新节点
            //指向的是下标
            root=tree[root][id];

    5.结束插入后,在此节点的位置标记单词结束标志。

       //设置该节点的结束标志
        flag[root]= 1;
    void Insert(char s[])
    {
        int root=0;
        int i;
        //遍历
        for(i=0;s[i];i++)
        {    
            //得到0-25范围的整数,代表a-z
            int id=s[i]-'a';
            //判断该节点是否被赋值
            //如果为-1,说明该节点还未存储字母,就需要创建新节点
            if(tree[root][id]==-1) 
            {    
                //创建一个新节点
                tree[root][id]=++cnt;
            }
            //如果存在直接指向这个节点,如果不存在,指向创建的新节点
            //指向的是下标
            root=tree[root][id];
        }
        //设置该节点的结束标志
        flag[root]= 1;
    }

    查找:在字典树中查找单词是否存在

    int Search(char s[])
    {
        int root=0;
        int i;
        for(i=0;s[i];i++)
        {
            int id=s[i]-'a';
            if(tree[root][id]==-1) return 0;
            root=tree[root][id];;
        }
        //判断该节点是否为结束标志位
        if(flag[root]){
            return 1;
        }else{
            return 0;
        }
    }

    最重要的功能:已知前缀,查所有出现的单词。

    void iter(int root){
        int j;
        for(j=0;j<26;j++){
            //tree[root][j]存储的是节点位置
            if(tree[root][j] != -1){
                printf("%d:%c
    ",root,j+'a');
                //迭代:
                iter(tree[root][j]);    
                printf("
    ");
            }
        }
    }
    
    int locate(char s[])
    {
        int root=0;
        int i;
        for(i=0;s[i];i++)
        {
            int id=s[i]-'a';
            if(tree[root][id]==-1) return 0;
            root=tree[root][id];
        }
        //判断该节点是否为结束标志位
        if(flag[root]){
               return 0;
        }
        iter(root);
        return 1;
    }
    #include <stdio.h>
    #include <string.h>
        
    
    #define NodeSize 100 //100000
    #define CHARSIZE 26  //26
    int flag[NodeSize]={0};//是否以该节点结尾,大小为节点数量
    int tree[NodeSize][CHARSIZE];//每一个节点都有26个子节点,如果有大写字母则为52,加上数字就是62
    int cnt=0;//记录已经存储字母的节点数量
    
    void Insert(char s[])
    {
        int root=0;
        int i;
        //遍历
        for(i=0;s[i];i++)
        {    
            //得到0-25范围的整数,代表a-z
            int id=s[i]-'a';
            //判断该节点是否被赋值
            //如果为-1,说明该节点还未存储字母,就需要创建新节点
            if(tree[root][id]==-1) 
            {    
                //创建一个新节点
                tree[root][id]=++cnt;
            }
            //如果存在直接指向这个节点,如果不存在,指向创建的新节点
            //指向的是下标
            root=tree[root][id];
        }
        //设置该节点的结束标志
        flag[root]= 1;
    }
    int Search(char s[])
    {
        int root=0;
        int i;
        for(i=0;s[i];i++)
        {
            int id=s[i]-'a';
            if(tree[root][id]==-1) return 0;
            root=tree[root][id];
        }
        //判断该节点是否为结束标志位
        if(flag[root]){
            return 1;
        }else{
            return 0;
        }
    }
    
    void iter(int root){
        int j;
        for(j=0;j<26;j++){
            //tree[root][j]存储的是节点位置
            if(tree[root][j] != -1){
                printf("%d:%c
    ",root,j+'a');
                //迭代:
                iter(tree[root][j]);    
                printf("
    ");
            }
        }
    }
    
    int locate(char s[])
    {
        int root=0;
        int i;
        for(i=0;s[i];i++)
        {
            int id=s[i]-'a';
            if(tree[root][id]==-1) return 0;
            root=tree[root][id];
        }
        //判断该节点是否为结束标志位
        if(flag[root]){
               return 0;
        }
        iter(root);
        return 1;
    }
    
    
    void Init(){
        int i;
        int j;
        for(i=0;i<NodeSize;i++){
            for(j=0;j<CHARSIZE;j++){
                tree[i][j] = -1;
            }
        }
    }
        
        
    int main()
    {
        Init();
        char s1[5] = "fggf";
        char s2[4] = "fbs";
        char s3[6] = "f";
        //插入字符串
        Insert(s1);
        //插入字符串
        Insert(s2);
        //查找字符串
        locate(s3);
       
        return 0;
    }
    源码

    更多阅读:

    python实现版本

  • 相关阅读:
    HDU 1013 Digital Roots
    HDU 1290 献给杭电五十周年校庆的礼物
    几何分割问题
    HDU 1222 Wolf and Rabbit
    HDU 1997 汉诺塔VII
    HDU 1443 Joseph
    HTML的标题样式
    HDU 1568 Fibonacci
    Hope
    HDU 1071 The area
  • 原文地址:https://www.cnblogs.com/-wenli/p/12442678.html
Copyright © 2020-2023  润新知