字典樹的根本常識及應用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;
}