Trie樹的構建

2021-06-21 09:53:34 字數 3867 閱讀 5842

分類: algorithm

2013-09-13 00:02

313人閱讀收藏 

舉報trie樹

trie樹

,又稱單詞查詢樹或鍵樹

,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計和排序大量的字串(但不僅限於字串),

所以經常被搜尋引擎系統用於文字詞頻統計,還可以用來求單詞的字首

。它的優點是:最大限度地減少無謂的字串比較,查詢效率比雜湊表高。

本文討論一棵最簡單的trie樹,基於英文26個字母組成的字串,討論插入字串、判斷字首是否存在、查詢字串等基本操作;至於trie樹的刪除單個節點實在是少見,故在此不做詳解。

ltrie

原理trie

的核心思想是空間換時間。利用字串的公共字首來降低查詢時間的開銷以達到提高效率的目的。

ltrie

性質好多人說trie的根節點不包含任何字元資訊,我所習慣的trie根節點卻是包含資訊的,而且認為這樣也方便,下面說一下它的性質 (基於本文所討論的簡單trie樹)

1.字元的種數決定每個節點的出度,即branch陣列(空間換時間思想)

2.branch

陣列的下標代表字元相對於a的相對位置

3.採用標記的方法確定是否為字串。

4.插入、查詢的複雜度均為o(len),len為字串長度

ltrie

的示意圖

如圖所示,該trie樹存有abc、d、da、dda四個字串,如果是字串會在節點的尾部進行標記。沒有後續字元的branch分支指向null

我有個小小的疑問如果按照:

struct trie

那我們將da,dc插入到trie樹,雖然們標記了第二層的節點flag,我們是不是就無法區分,到底是da還是dc呢。後來在床上想了一下,其實應該是這樣的。da插入到trie樹裡面,其實有三層,第一層的d-》乙個節點,這個節點a—》指向乙個空節點(flag被標記),從事上面的圖也可以看出來。上圖中插入abc,c節點指向乙個被標記的空節點。

ltrie

trie

的優點舉例

已知n個由小寫字母構成的平均長度為10的單詞,判斷其中是否存在某個串為另乙個串的字首子串。下面對比3種方法:

1.最容易想到的:即從字串集中從頭往後搜,看每個字串是否為字串集中某個字串的字首,複雜度為o(n^2)。

2.使用hash:我們用hash存下所有字串的所有的字首子串。建立存有子串hash的複雜度為o(n*len)。查詢的複雜度為o(n)* o(1)= o(n)。

3.使用trie:因為當查詢如字串abc是否為某個字串的字首時,顯然以b,c,d....等不是以a開頭的字串就不用查詢了。所以建立trie的複雜度為o(n*len),而建立+查詢在trie中是可以同時執行的,建立的過程也就可以成為查詢的過程,hash就不能實現這個功能。所以總的複雜度為o(n*len),實際查詢的複雜度只是o(len)。

解釋一下hash為什麼不能將建立與查詢同時執行,例如有串:911,911456輸入,如果要同時執行建立與查詢,過程就是查詢911,沒有,然後存入9、91、911,查詢911456,沒有然後存入9114、91145、911456,而程式沒有記憶功能,並不知道911在輸入資料中出現過。所以用hash必須先存入所有子串,然後for迴圈查詢。

而trie樹便可以,存入911後,已經記錄911為出現的字串,在存入911456的過程中就能發現而輸出答案;倒過來亦可以,先存入911456,在存入911時,當指標指向最後乙個1時,程式會發現這個1已經存在,說明911必定是某個字串的字首,該思想是我在做pku上的3630中發現的,詳見本文配套的「入門練習」。

[cpp]view plain

copy

print?

const

intbranchnum = 26; 

//宣告常量 

inti;  

struct

trie_node  

};  

class

trie;  

trie::trie()  

void

trie::insert(

const

char

* word)  

location = location->next[*word-'a'

];   

word++;  

}  location->isstr = true

; //到達尾部,標記乙個串

}  bool

trie::search(

char

*word)  

return

(location!=null && location->isstr);  

}  

單詞的刪除:

[cpp]view plain

copy

print?

bool

trie::deleteword(

const

char

* word)  

if(current && current->isstr)  

}  if(current->isstr == 0 && isnotvalid)

//當乙個節點無效,即它只和該word相關,可以刪除  

else

//說明當前這個中間結點也被其他的結點所用,不能刪除。  

nodes.top()->next[c - 'a'

] = 0;

//把上層的結點的next中指向current結點的指標清0  

nodes.pop();  

}  return

true

;  }  

else

}  

另外,貼乙個統計單詞的程式:

[cpp]view plain

copy

print?

/*檔名: trie.c

功能描述:用trie樹實現單詞詞頻統計以及單詞查詢

說明:對統計物件,要求符合正則"[a-z]*"的格式的單詞

若考慮大寫,標點和空白字元(空格.tab.回車換行符),

可修改next陣列大小,最多255可包含所有字元

*/#include 

#include 

#include 

#include 

using

namespace

std;  

typedef

struct

trie_node_stru  

trienode, *trie;  

trienode* trie_createtrienode()  

inttrie_insert(trie root, 

char

* word)  

node = node->next[*p-'a'

];  

p++;  

}  node->count += 1;  

,  word, node->count);  

return

0;  

}  int

trie_search(trie root, 

char

* word)  

return

(node!=null && node->count>0);  

}  int

trie_remove(trie root, 

char

* word)  

intmain()  

"font-size:18px"

>  

Trie樹的實現

一 定義 trie,又稱字典樹,是一種用於快速檢索的二十六叉樹結構。典型的空間換時間 二 結構圖 三 原理 特別地 和二叉查詢樹不同,在trie樹中,每個結點上並非儲存乙個元素。四 性質 0 利用串的公共字首,節約記憶體 1 在trie樹上進行檢索總是始於根結點 2 根節點不包含字元,除根節點外的每...

Trie樹的學習

所寫內容,是對自己所學知識的乙個記錄罷了。1.簡介 最近在做中國人名識別的時候,看到一篇文章是基於角色的人名識別,而角色字典中有2個角色是用雙陣列tire樹來建立的,當時沒有看懂,於是來先學習trie樹。trie樹,又稱字典樹,單詞查詢樹或者字首樹等,是一種快速 檢索的多叉樹結構。比如,英文本母的字...

可愛的Trie樹

鑑於ducati的建議下,講一下trie樹 見書p77 trie又被稱為字首樹 字典樹,所以當然是一棵樹。樹中的每一條邊上都標識有乙個字元。這些字元可以是任意乙個字符集中的字元。比如對於都是小寫字母的字串,字符集就是 a z 對於都是數字的字串,字符集就是 0 9 對於二進位制字串,字符集就是0和1...