美文网首页
字典树 -- C语言实现

字典树 -- C语言实现

作者: lifanxin | 来源:发表于2020-11-24 08:34 被阅读0次

作者:__lifanxin
链接:https://blog.csdn.net/A951860555/article/details/108716487
来源:CSDN
著作权归作者所有,任何形式的转载都请联系作者。

基本概念

  字典树,又称单词查找树,Trie树,常用于统计、排序和保存大量的字符串。它的优点是利用字符串的公共前缀来减少存储空间以及查询时间,可以最大限度的减少无谓的字符串比较。
  其基本特点如下:一个根节点起始,根节点不存储字符,然后除根节点外每一个节点都只包含一个字符;将根节点沿着某一条路径到叶子节点的所有字符排列起来即存储的一个字符串或称为词组;另外就英文字母而言,如果不区分大小写,那么一个节点最大的子节点数是26,且每个子节点包含的字符都不相同。
  基本操作有:插入、查找、删除

代码实现

  采用c语言实现,分为三个文件:

trie_types.h
包括字典树的结构体定义和基本操作函数的声明

trie.c
字典树基本操作函数的实现

main.c
代码测试

头文件 trie_types.h

#ifndef TRIE_TYPE   
#define TRIE_TYPE

    #include <stdbool.h>


    #define MAX 26
    // 只考虑小写,英文最多26个字母,即每个节点最多拥有26个子节点

    // 可以灵活的在此结构中添加字段以实现程序的需求
    typedef struct TrieNode {
        char val;      // 存储单个字符
        bool isEnd;    // 标记单词最后一个字符,即叶子节点
        struct TrieNode *next[MAX];
    } *Trie, TrieNode;
    

    void init_trie(Trie *trie);       // 初始化字典树
    void insert_trie(Trie *trie, const char *str);  // 插入字符串
    void search_trie(Trie *trie, const char *str);   // 查找词组是否在字典树中
    void delete_trie(Trie *trie);     // 删除字典树

#endif

函数实现 trie.c

#include "trie_types.h"
#include <malloc.h>
#include <stdio.h>


static TrieNode *queue[1024];  // 数组实现队列


static TrieNode *create_node(int val);  // 创建新节点
static void traverse_trie(Trie *trie);  // 广度遍历字典树


static TrieNode *create_node(int val){
    // 创建新节点
    TrieNode *newNode;
    newNode = (TrieNode *)malloc(sizeof(TrieNode));

    newNode->val = val;
    newNode->isEnd = false;
    for (int i=0; i<MAX; i++){
        newNode->next[i] = NULL;
    }

    return newNode;
}


static void traverse_trie(Trie *trie){
    // 广度优先遍历
    TrieNode *node = *trie;
    int head = 0, tail = 0;       // 队列头尾指针

    queue[tail++] = node;         // 头节点入队
    while (head != tail){
        node = queue[head++];     // 节点出队
        for (int i=0; i<MAX; i++){
            if (node->next[i]){
                queue[tail++] = node->next[i];
            }
        }
    }
}


void init_trie(Trie *trie){
    // 初始化一个空的字典树
    *trie = NULL;
}


void insert_trie(Trie *trie, const char *str){
    // 插入单词到字典树中
    TrieNode *node;
    int i = 0, index = 0;

    if (!*trie){
        // 头节点为空,先创建头节点
        *trie = create_node(0);
    }

    node = *trie;
    while (str[i]){
        /*
           利用字符相减,使用index记录节点的插入位置,
           保证处于同一层次且相同的字符不会被重复插入
        */
        index = str[i] - 'a';
        if (!node->next[index]){
            node->next[index] = create_node(str[i]);
        }
        node = node->next[index];
        i++;
    }
    node->isEnd = true;    // 单词最后一个字母标记为true
}


void search_trie(Trie *trie, const char *str){
    /*
        查询单词是否在字典树中,不包括含有相同前缀的
        例如已插入:he,那么h和her都不算在字典树中
    */
    TrieNode *node = *trie;
    int i = 0, index = 0;

    if (!node){
        // 判断是否是空树
        fputs("Trie is null!\n", stdout);
        return;
    }

    while(str[i]){
        /*
            比较str中的每一个字符,
            直到走到字符数组结尾或者字典树中不存在对应节点
        */
        index = str[i] - 'a';
        if (!node->next[index])
            break;
        node = node->next[index];
        i++;
    }
    if (node->isEnd && !str[i]) {
        printf("%s is exist!\n", str);
    } else {
        printf("%s is not exist!\n", str);
    }
}


void delete_trie(Trie *trie){
    // 释放字典树内存
    int i = 0;

    traverse_trie(trie);  // 存储字典树节点指针到队列中
    while (queue[i]){
        free(queue[i++]);
    }
}

代码测试 main.c

#include "trie_types.h"
#include <stdio.h>


int main(void){
    // 测试字典树
    char str[][4] = {
        "he",
        "she",
        "his"
    };
    char tStr[][4] = {
        "he",
        "she",
        "his",
        "her",
        "hh",
        "oo"
    };
    Trie *trie;

    init_trie(trie);       // 初始化
    for (int i=0; i<3; i++)
        // 插入
        insert_trie(trie, str[i]);
    for (int i=0; i<6; i++)
        // 查找
        search_trie(trie, tStr[i]);
    delete_trie(trie);     // 释放

    return 0;
}

测试结果

测试结果

  如上图所示,上述代码很好的实现了字典树的初始化、插入、查询以及删除操作,能够正确的查询到被存储在字典树中的词组;而具有相同前缀但没有完整存储在字典树中的词组将不会被查询到。

相关文章

  • 字典树 -- C语言实现

    作者:__lifanxin链接:https://blog.csdn.net/A951860555/article/...

  • 用C语言实现字典树

    前言 前段时间,面试百度人工智能部门的测试开发岗的时候,面试官给了我一道算法题:有一堆数据,都是由英文字母构成的,...

  • 简单的字典树

    实现了一个C语言写的简单字典树,节点之间跳转,用链表实现 节点定义 插入节点 查找节点 测试代码 实现的很粗糙, ...

  • cjson 源码分析

    cjson 的源码大约1000行左右,用C语言实现了一个json的解析器。c语言没有字典或key-value这样的...

  • 001 红黑树(二)之 C语言的实现(3)

    红黑树的测试文件(rbtree_test.c): 1/** 2*C语言实现的红黑树(RedBlackTree) 3...

  • 字典树

    字典树的python实现

  • redis-字典

    redis所使用的C语言并没有内置丰富的数据结构,因而redis实现了很多数据结构,本文主要介绍字典。 字典又叫映...

  • 算法与数据结构系列之[二叉树-下]

    上篇贴出了二叉树的C语言代码实现,这篇贴出Java代码实现。

  • 实现字典树

    题目:实现字典树 (算法课第七课) Trie树,又称为字典树、单词查找树或者前缀树,是一种用于快速检索的多叉数结构...

  • 前缀树(字典树/Trie)Java实现和应用

    摘要: 前缀树,字典树,插入查询逻辑,Java实现,时间复杂度分析 前缀树介绍 Trie树又被称为前缀树、字典树,...

网友评论

      本文标题:字典树 -- C语言实现

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