程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 字典樹的根本常識及應用C說話的相干完成

字典樹的根本常識及應用C說話的相干完成

編輯:關於C++

字典樹的根本常識及應用C說話的相干完成。本站提示廣大學習愛好者:(字典樹的根本常識及應用C說話的相干完成)文章只能為提供參考,不一定能成為您想要的結果。以下是字典樹的根本常識及應用C說話的相干完成正文


概念

     假如我們有and,as,at,cn,com這些症結詞,那末trie樹(字典樹)是如許的:

     從下面的圖中,我們或多或少的可以發明一些好玩的特征。

      第一:根節點不包括字符,除根節點外的每個子節點都包括一個字符。

      第二:從根節點到某一節點,途徑上經由的字符銜接起來,就是該節點對應的字符串。

      第三:每一個單詞的公共前綴作為一個字符節點保留。

 

應用規模

     既然學Trie樹,我們確定要曉得這玩意是用來干嗎的。

     第一:詞頻統計。

            能夠有人要說了,詞頻統計簡略啊,一個hash或許一個堆便可以打完出工,但成績來了,假如內存無限呢?還能這麼

             玩嗎?所以這裡我們便可以用trie樹來緊縮下空間,由於公共前綴都是用一個節點保留的。

     第二: 前綴婚配

            就拿下面的圖來講吧,假如我想獲得一切以"a"開首的字符串,從圖中可以很顯著的看到是:and,as,at,假如不消trie樹,

            你該怎樣做呢?很明顯樸實的做法時光龐雜度為O(N2) ,那末用Trie樹就紛歧樣了,它可以做到h,h為你檢索單詞的長度,

            可以說這是秒殺的後果。

數據構造界說

  #define MAX 26 // 字符集年夜小 
   
  typedef struct trieNode { 
    struct trieNode *next[MAX]; 
    int count; // 記載該字符湧現次數 
  } trieNode; 



next數組表現每層有若干類的數,假如只是小寫字母,26便可


完成辦法
搜刮字典項目標辦法:

  •     從根節點開端一次搜刮
  •     獲得要查找症結詞的第一個字母,並依據該字母選擇對應的子樹並轉到該子樹持續停止檢索
  •     在響應的子樹上,獲得要查找症結詞的第二個字母,並進一步選擇對應的子樹停止檢索
  •     迭代進程
  •     在某個節點處,症結詞的一切字母已被掏出,則讀取附在該結點上的信息,即完成查找


其他操作相似


完成模板

初始化根結點

  /** 
   * 初始化Trie樹根結點 
   */ 
  void initTrie(trieNode **root) 
  { 
    int i; 
   
    *root = (trieNode *)malloc(sizeof(trieNode)); 
    (*root)->count = 0; 
   
    for (i = 0; i < MAX; i ++) { 
      (*root)->next[i] = NULL; 
    } 
  } 

拔出單詞到trie樹

 

  /** 
   * Trie樹拔出操作 
   */ 
  void insert(char *str, trieNode *root) 
  { 
    int i; 
   
    trieNode *p = root; 
   
    while (*str != '\0') { 
      if (p->next[*str - 'a'] == NULL) { 
        trieNode *tmp = (trieNode *)malloc(sizeof(trieNode)); 
        for (i = 0; i < MAX; i ++) { 
          tmp->next[i] = NULL; 
        } 
        tmp->count = 1; 
        p->next[*str - 'a'] = tmp; 
        p = p->next[*str - 'a']; 
      } else { 
        p = p->next[*str - 'a']; 
        p->count ++; 
      } 
   
      str ++; 
    } 
  } 

統計查找單詞數目

  /** 
   * 統計前綴湧現次數 
   */ 
  int count(char *search, trieNode *root) 
  { 
    trieNode *p = root; 
   
    while (*search != '\0') { 
      if (p->next[*search - 'a'] == NULL) { 
        return 0; 
      } else { 
        p = p->next[*search - 'a']; 
        search ++; 
      } 
    } 
   
    return p->count; 
  } 


清算trie樹

  /** 
   * 清算trie樹 
   */ 
  void delTrie(trieNode *root) 
  { 
    int i; 
   
    for (i = 0; i < MAX; i ++) { 
      if (root->next[i] != NULL) { 
        delTrie(root->next[i]); 
      } 
    } 
   
    free(root); 
  } 

時光龐雜度
拔出、查找的時光龐雜度均為O(n),n為字符串的長度

空間龐雜度較高,O(26^n),典范空間換時光


參考標題

ac代碼:

 

  #include <stdio.h> 
  #include <stdlib.h> 
  #include <string.h> 
   
  #define MAX 26 // 字符集年夜小 
   
  typedef struct trieNode { 
    struct trieNode *next[MAX]; 
    int count; // 記載該字符湧現次數 
  } trieNode; 
   
   
  /** 
   * 初始化Trie樹根結點 
   */ 
  void initTrie(trieNode **root) 
  { 
    int i; 
   
    *root = (trieNode *)malloc(sizeof(trieNode)); 
    (*root)->count = 0; 
   
    for (i = 0; i < MAX; i ++) { 
      (*root)->next[i] = NULL; 
    } 
  } 
   
  /** 
   * Trie樹拔出操作 
   */ 
  void insert(char *str, trieNode *root) 
  { 
    int i; 
   
    trieNode *p = root; 
   
    while (*str != '\0') { 
      if (p->next[*str - 'a'] == NULL) { 
        trieNode *tmp = (trieNode *)malloc(sizeof(trieNode)); 
        for (i = 0; i < MAX; i ++) { 
          tmp->next[i] = NULL; 
        } 
        tmp->count = 1; 
        p->next[*str - 'a'] = tmp; 
        p = p->next[*str - 'a']; 
      } else { 
        p = p->next[*str - 'a']; 
        p->count ++; 
      } 
   
      str ++; 
    } 
  } 
   
  /** 
   * 統計前綴湧現次數 
   */ 
  int count(char *search, trieNode *root) 
  { 
    trieNode *p = root; 
   
    while (*search != '\0') { 
      if (p->next[*search - 'a'] == NULL) { 
        return 0; 
      } else { 
        p = p->next[*search - 'a']; 
        search ++; 
      } 
    } 
   
    return p->count; 
  } 
   
  /** 
   * 清算trie樹 
   */ 
  void delTrie(trieNode *root) 
  { 
    int i; 
   
    for (i = 0; i < MAX; i ++) { 
      if (root->next[i] != NULL) { 
        delTrie(root->next[i]); 
      } 
    } 
   
    free(root); 
  } 
   
   
  int main(void) 
  { 
    char str[15]; 
    trieNode *root; 
   
    // 初始化根結點 
    initTrie(&root); 
   
    while (gets(str) && str[0] != '\0') { 
      // 拔出Trie樹 
      insert(str, root); 
    } 
   
    // 查找前綴湧現次數 
    while (gets(str) && str[0] != '\0') { 
      printf("%d\n", count(str, root)); 
    } 
   
    delTrie(root); 
   
    return 0; 
  } 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved