美文网首页
【一】 字典树

【一】 字典树

作者: Michael_abc | 来源:发表于2019-10-09 14:52 被阅读0次

前言

一个超过1GB的文件,每一行都是一个单词,且每行长度不超过16,请找出出现次数排名前100的单词,内存使用不能超过2MB。这是我遇到过的一道题目,以此为引子。

定义

在计算机科学中,trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。

trie中的键通常是字符串,但也可以是其它的结构。trie的算法可以很容易地修改为处理其它结构的有序序列,比如一串数字或者形状的排列。比如,bitwise trie中的键是一串位元,可以用于表示整数或者内存地址。

基础性质

1.根节点不包含字符,任意子节点包含一个字符。
2.从根节点出发到任意一个叶子节点的路径上字符连接就是一个字符串。
3.每个节点的子节点包含的字符都是唯一的。

示图

image.png

trie.h

#ifndef TRIE_H
#define TRIE_H
#define MAX 26
typedef struct trie_s trie_t ;
struct trie_s{
    int is_terminal;
    int count;
    trie_t *node[MAX];
};
trie_t *trie_node_init();
int trie_insert(trie_t *root ,char *word);
int trie_delete(trie_t *root,char *word);
int trie_search(trie_t *root,char *word);
void trie_dump(trie_t *root,char *prefix);
void trie_destory(trie_t *root);
#endif /* TRIE_H */

trie.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "trie.h"
/**
 * 
 * @return 
 */
trie_t *trie_node_init(){
    trie_t *root;
    root = (trie_t *) malloc(sizeof(trie_t));
    root->count = 0;
    root->is_terminal = 0;
    int i;
    for(i=0;i<MAX;i++){
        root->node[i] = NULL;
    }
    return root;
}
/**
 * 
 * @param root
 * @param word
 * @return 
 */
int trie_insert(trie_t *root ,char *word){
    int i,val;
    int len = strlen(word);
    trie_t *node = root;
    for(i=0;i<len;i++){
        val = (int) (word[i] - 'a');
        //节点不存在
        if(node->node[val] == NULL){
            node->node[val] = trie_node_init();
        }
        node = node->node[val];
    }
    node->count = node->count + 1;
    node->is_terminal = 1;
    return 1;
}
/**
 * 
 * @param root
 * @param word
 * @return 
 */
int trie_delete(trie_t *root,char *word){
    int i,val;
    int len = strlen(word);
    trie_t *node = root;
    for(i=0;i<len;i++){
        val = (int) (word[i] - 'a');
        //节点不存在
        if(node->node[val] == NULL){
            return -1;
        }
        node = node->node[val];
    }
    node->count=0;
    node->is_terminal = 0;
    return 1;
}
/**
 * 
 * @param root
 * @param word
 * @return 
 */
int trie_search(trie_t *root,char *word){
    int i,val;
    int len = strlen(word);
    trie_t *node = root;
    int count = 0;
    for(i=0;i<len;i++){
        val = (int) (word[i] - 'a');
        //节点不存在
        if(node->node[val] == NULL){
            return count;
        }
        node = node->node[val];
    }
    count = node->count;
    return count;
}
/**
 * 
 * @param root
 * @param prefix
 */
void trie_dump(trie_t *root,char *prefix){
    if(!root){
        return;
    }
    int i,j,len;
    len = strlen(prefix);
    char new_prefix[len+1]; 
    char * new_prefix_pt;
    for(i=0;i<MAX;i++){
        if(root->node[i]){
            if(root->node[i]->is_terminal){
                printf("word:%s%c appear:%d times\n",prefix ,(char)('a' + i),root->node[i]->count);
            }
            new_prefix_pt = (char *) malloc(len + 1);
            sprintf(new_prefix_pt, "%s%c", prefix, ('a' + i));
            trie_dump(root->node[i] ,new_prefix_pt);
        }        
    }
}
/**
 * 
 * @param root
 */
void trie_destory(trie_t *root){
    if(!root){
        return ;
    }
    int i;
    for(i=0;i<MAX;i++){
        if(root->node[i]){
            trie_destory(root->node[i]);
        }
    }
    free(root);
}

trie_test.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "trie.c"

/*
 * 
 */
void main(){
    trie_t *root = trie_node_init();
    FILE *fp = fopen("./words.txt","r");
    char one_line[1024];
    char *word;
    int len=0,i=0;
    word = (char *)malloc(17);
    while (!feof(fp)) 
    {    
        fgets(one_line,1024,fp);
        len = strlen(one_line);
        if(len<=2){
            continue;
        }
        for(i=0;i<len-2;i++){
            *(word+i) = one_line[i];
        }
        *(word+i) = '\0';
        trie_insert(root ,word);
    }
    fclose(fp);
    char *the_word ="ttcoakblwwh";
    int count = trie_search(root,the_word);
    printf("%s:%d\n",the_word ,count);
    trie_delete(root ,the_word);
    count = trie_search(root,the_word);
    printf("%s:%d\n",the_word ,count);
    trie_destory(root);
}

相关文章

  • 2019-03-31字典树Tire

    字典树图示 字典树案例

  • (六)树结构---字典树

    1.字典树基础 1.1.字典树 字典树又称前缀树,对于一个字符串在加入字典树结构时,会合并相同的字符,字典树是一种...

  • Trie

    字典树 01字典树

  • 【一】 字典树

    前言 一个超过1GB的文件,每一行都是一个单词,且每行长度不超过16,请找出出现次数排名前100的单词,内存使用不...

  • Trie字典树(前缀树)

    对字典树的理解: a.Trie字典树又可以称为前缀树,是一种真正为字典设计的数据结构,其中的核心实现就包含了字典M...

  • 字典树

  • 字典树

    需求: 判断文本中是否包含某个词, 以及词频问题:中文分词实际使用的词典往往在几十万个词以上,逐个匹配成本太大。方...

  • 字典树

    功能 字典树是用数组存储大量字符串的一种算法 字典树算法开辟空间非常大,但是对于字符串插入和查询有很快的速度 用法...

  • 字典树

    UVA 11488题目链接https://uva.onlinejudge.org/index.php?option...

  • 字典树

    应用场景: 又称“单词查找树”,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但...

网友评论

      本文标题:【一】 字典树

      本文链接:https://www.haomeiwen.com/subject/cdpfpctx.html