字典树查询时间复杂度

有一个存放英文单词的文本文件,现在需要知道某些给定的单词是否在该文件中存在,若存在,它又出现了多少次?

    这样的问题解法有多种,普通青年直接暴力查找,稍文艺点的用map。顺序查找的话,每给定一个单词就得遍历整个字符串数组,时间开销实在太大;如果将所有的单词都存放在一个map中,每次查找的时间复杂度则降为O(log(n))。不得不说,对于一般的应用场景,map足够满足所有需求。

    但对于这个问题,还有更好的方法。有一种数据结构似乎就是为解决此类问题而诞生的,它就是字典树。我们知道,英文单词有很多都有相同的前缀,对于相同的前缀,字典树只存储一次,而map则是有多少个单词就存储多少次,所以在这个问题中,字典树比map省空间;在字典树中查找字符串的时间复杂度只跟树的深度有关而跟究竟有多少个字符串无关,而树的深度只跟字符串的长度有关,超过30个拉丁字母的英文单词基本没有,所以在该问题中查找字符串的时间复杂度只有O(1),比map省时间。

    所以对于这样一个特定的问题,字典树自然是最佳的选择。

    对于字典树的空间结构以及如何在字典树中查找字符串,不再坠言,一切净在代码中:

[html]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4.   
  5. #define MAX_TREE_NODE 128  
  6.   
  7. typedef struct _DictTree  
  8. {  
  9.   int times;  
  10.   struct _DictTree* child[MAX_TREE_NODE];  
  11. }DictTree, *DictTreePtr;  
  12.   
  13. static DictTreePtr g_root = NULL;  
  14.   
  15. void insert(const char* str)  
  16. {  
  17.   int i              = 0;  
  18.   int len            = strlen(str);  
  19.   DictTreePtr prePtr = NULL;  
  20.   DictTreePtr nxtPtr = NULL;  
  21.     
  22.   if (!g_root)  
  23.   {  
  24.     g_root = (DictTreePtr)malloc(sizeof(DictTree));  
  25.     memset(g_root, 0, sizeof(DictTree));  
  26.   }  
  27.   prePtr = g_root;  
  28.   
  29.   for (i = 0; i < len; ++i)  
  30.   {  
  31.     nxtPtr = prePtr->child[str[i]];  
  32.     if (!nxtPtr)  
  33.     {  
  34.       nxtPtr = (DictTreePtr)malloc(sizeof(DictTree));  
  35.       memset(nxtPtr, 0, sizeof(DictTree));  
  36.     }  
  37.     prePtr->child[str[i]] = nxtPtr;  
  38.     prePtr                = nxtPtr;  
  39.     if (i == len -1)  
  40.       ++(prePtr->times);  
  41.   }  
  42. }  
  43.   
  44. int search(const char* str)  
  45. {  
  46.   int i = 0;  
  47.   int len = strlen(str);  
  48.   DictTreePtr prePtr = NULL;  
  49.   DictTreePtr nxtPtr = NULL;  
  50.   
  51.   if (!g_root)  
  52.     return 0;  
  53.   prePtr = g_root;  
  54.   
  55.   for (i = 0; i < len; ++i)  
  56.   {  
  57.     nxtPtr = prePtr->child[str[i]];  
  58.     if (!nxtPtr)  
  59.       return 0;  
  60.     prePtr = nxtPtr;  
  61.   }  
  62.   
  63.   return prePtr->times;  
  64. }  



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值