Trie树

作者: TomyZhang | 来源:发表于2019-05-12 15:11 被阅读0次

一、概念

Trie树又称为字典树、单词查找树、前缀树等,是一种树状结构。

对于英文字符串,其每个结点包括26个next指针,每个指针对应一个字母,即每一条边为一个字母,同时每个结点包含一个标识,表示从根结点到该结点的边是否组成了一个单词。

Trie树

二、数据结构

#define NUM 26

struct TrieNode {
    bool isStr;
    TrieNode *next[NUM];
};

三、相关操作

  • 插入
  • 查找
  • 删除

Trie树相关操作

四、实现

#include<stdio.h>
#include<malloc.h>
#define SEARCHWORD_MAXCOUNT 100
#define SEARCHWORD_MAXLEN 12
#define TRIE_NUM 26

struct TrieNode { //Trie树结点
    char ch; //当前字母
    bool isStrEnd; //单词结束标志
    int frequency; //词频统计
    TrieNode *child[TRIE_NUM]; //孩子结点指针
};

struct SearchNode { //查找结果结点
    char ch[SEARCHWORD_MAXLEN + 1]; //单词
    int frequency; //词频
};

TrieNode root;
SearchNode searchNode[SEARCHWORD_MAXCOUNT];
int searchIndex;

int mstrlen(char *a) {
    int len = 0;
    while (a[len] != '\0') {
        len++;
    }
    return len;
}

void mstrncpy(char *dest, char *src, int len) {
    for (int i = 0; i < len; i++) {
        dest[i] = src[i];
    }
    dest[len] = '\0';
}

TrieNode* newNode(char ch) { //创建并初始化新结点
    TrieNode *node = (TrieNode*)malloc(sizeof(TrieNode));
    node->ch = ch;
    node->isStrEnd = false;
    node->frequency = 0;
    for(int i=0; i<TRIE_NUM; i++) {
        node->child[i] = NULL;
    }
    return node;
}

void freeTrie(TrieNode *node) { //使用DFS后根序方式释放结点内存
    if(node == NULL) {
        return;
    }

    for(int i=0; i<TRIE_NUM; i++) {
        freeTrie(node->child[i]);
    }

    if(node != &root) {
        free(node);
    } else {
        for(int i=0; i<TRIE_NUM; i++) {
            node->child[i] = NULL;
        }   
    }
}

void printSearchResult(char pre[]) {
    printf("printSearchResult, pre: %s\n", pre);
    for(int i=0; i<searchIndex; i++) {
        printf("%d: %s, %d times\n", i, searchNode[i].ch, searchNode[i].frequency);
    }
}

void insertStr(char ch[]) { //插入或者更新字符串
    int n = mstrlen(ch);
    TrieNode *p = &root;
    for(int i=0; i<n; i++) {
        char temp = ch[i];
        int index = temp - 'a';
        if(p->child[index] == NULL) { //子节点为空,创建一个新的子节点
            TrieNode *node = newNode(temp);
            p->child[index] = node;
        }
        p = p->child[index];
    }
    if(p->isStrEnd) { //如果已经是字符串结尾,则frequency加1
        p->frequency++;
    } else { //如果不是字符串结尾,则设置为字符串结尾,并将frequency设置为 1
        p->isStrEnd = true;
        p->frequency = 1;
    }
}

void findStrEnd(char preStr[], int n, TrieNode *node) { //使用DFS先根序方式查找字符串
    if(node == NULL) {
        return;
    }

    SearchNode temp;
    mstrncpy(temp.ch, preStr, n); //拷贝前面出现的字符串
    temp.ch[n] = node->ch; //追加当前字母
    temp.ch[n+1] = '\0'; //追加字符串结束标记
    if(node->isStrEnd) {
        temp.frequency = node->frequency;
        searchNode[searchIndex] = temp;
        searchIndex++;
    }

    for(int i=0; i<TRIE_NUM; i++) {
        findStrEnd(temp.ch, n+1, node->child[i]);
    }
}

void searchStr(char pre[]) { //根据前缀查找字符串
    int n = mstrlen(pre);
    searchIndex = 0;
    TrieNode *p = &root;
    for(int i=0; i<n; i++) {
        char temp = pre[i];
        int index = temp - 'a';
        if(p->child[index] == NULL) { //子节点为空, 无查找结果
            return;
        } else { //子节点不为空,继续查找
            p = p->child[index];
        }
    }

    if(p->isStrEnd) {
        SearchNode temp;
        mstrncpy(temp.ch, pre, n);
        temp.ch[n] = '\0';
        temp.frequency = p->frequency;
        searchNode[searchIndex] = temp;
        searchIndex++;  
    } 

    for(int i=0; i<TRIE_NUM; i++) {
        findStrEnd(pre, n, p->child[i]);
    }

    printSearchResult(pre);
}

void main() {
    root.ch = ' ';
    root.isStrEnd = false;
    root.frequency = 0;
    insertStr("abc");
    insertStr("abcde");
    insertStr("abc");
    insertStr("adeb");
    insertStr("abcde");
    insertStr("adebc");
    insertStr("afgbb");
    insertStr("abcde");
    insertStr("afg");
    insertStr("afgb");
    searchStr("abc");
    searchStr("ade");
    searchStr("afg");
}

相关文章

  • trie树

    文章内容来自 Trie树:应用于统计和排序Trie树 trie树又称:字典树、单词查找树、前缀树等,总之是一种树状...

  • 树结构之Trie

    1. 什么是trie树 1.Trie树 (特例结构树)Trie树,又称单词查找树、字典树,是一种树形结构,是一种哈...

  • 实现 Trie

    数据结构之Trie树Trie树:应用于统计和排序

  • Trie树

    一、定义 Trie树,又称为单词查找树,是一种树形结构(Trie一词源于单词Retrieval-取出)。Trie树...

  • leetcode——字典树(Trie树)的实现

    leetcode——实现Trie(前缀树) 题目 实现一个 Trie (前缀树),包含 insert, searc...

  • 算法笔记 - Trie 树

    Trie树是一种非常常见的算法 Trie树的主要用途是快速地匹配字符串 Tire树可以记录数值 Trie树的实现成...

  • 以太坊详解 之 Merkle Patricia Tree

    基础知识 Trie树 Trie是一种搜索树,又称字典树(digital tree)和前缀树(prefix tree...

  • 数据结构与算法笔记day21:Trie树|AC自动机

    1Trie树 这节课学习了一种特殊的树,Trie树。Trie树是一种解决字符串快速匹配问题的数据结构。如果用来...

  • Leetcode 208 实现 Trie (前缀树)

    实现 Trie (前缀树) 题目 实现一个 Trie (前缀树),包含 insert, search, 和 sta...

  • 208-实现Trie(前缀树)

    实现Trie(前缀树) 题目 实现一个 Trie (前缀树),包含 insert, search, 和 start...

网友评论

      本文标题:Trie树

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