Trie是一种有效的信息Trie val数据结构。使用Trie,可以使搜索复杂度达到最佳极限(密钥长度)。如果我们将密钥存储在二进制搜索树中,那么平衡良好的BST将需要与M * log N成正比的时间,其中M是最大字符串长度,N是树中密钥的数量。使用Trie,我们可以搜索O(M)时间的密钥。但是,惩罚取决于Trie的存储要求(有关更多详细信息,请参阅Trie的应用程序)
Trie的每个节点都包含多个分支。每个分支代表键的可能字符。我们需要将每个键的最后一个节点标记为单词节点的末尾。 Trie节点字段isEndOfWord用于将节点区分为单词节点的末尾。代表英文字母节点的简单结构如下:
// Trie node
struct TrieNode
{
struct TrieNode *children[ALPHABET_SIZE];
// isEndOfWord为true,如果节点
//表示单词的结尾
bool isEndOfWord;
};
将密钥插入Trie是一种简单的方法。输入键的每个字符都作为一个单独的Trie节点插入。请注意,子级是指向下一级Trie节点的指针(或引用)的数组。键字符作为一个指数到阵列的儿童。如果输入键是新键或现有键的扩展,则需要构造键的不存在节点,并将单词的结尾标记为最后一个节点。如果输入键是Trie中现有键的前缀,我们只需将键的最后一个节点标记为单词的结尾即可。密钥长度决定了Trie深度。
搜索键类似于插入操作,但是,我们仅比较字符并向下移动。搜索可能由于字符串或Trie中缺少关键字而终止。在前一种情况下,如果最后一个节点的isEndofWord字段为true,则该键存在于trie中。在第二种情况下,搜索将终止,而不检查键的所有字符,因为该键不在Trie中。
下图说明了如何使用以下示例中给出的键构造trie,
root
/ \ \
t a b
| | |
h n y
| | \ |
e s y e
/ | |
i r w
| | |
r e e
|
r
在图片中,每个字符的类型都是trie_node_t 。例如,根的类型为trie_node_t,并且填充了子a , b和t ,root的所有其他节点均为NULL。类似地,下一级别的“ a”只有一个孩子(“ n”),所有其他孩子均为NULL。叶节点为蓝色。
插入和搜索成本为O(key_length) ,但是Trie的内存要求为O(ALPHABET_SIZE * key_length * N) ,其中N是Trie中的键数。有效表示Trie节点(例如压缩的Trie,三进制搜索树等),以最大程度地减少Trie的内存需求。
C++
// C++ implementation of search and insert
// operations on Trie
#include
using namespace std;
const int ALPHABET_SIZE = 26;
// trie node
struct TrieNode
{
struct TrieNode *children[ALPHABET_SIZE];
// isEndOfWord is true if the node represents
// end of a word
bool isEndOfWord;
};
// Returns new trie node (initialized to NULLs)
struct TrieNode *getNode(void)
{
struct TrieNode *pNode = new TrieNode;
pNode->isEndOfWord = false;
for (int i = 0; i < ALPHABET_SIZE; i++)
pNode->children[i] = NULL;
return pNode;
}
// If not present, inserts key into trie
// If the key is prefix of trie node, just
// marks leaf node
void insert(struct TrieNode *root, string key)
{
struct TrieNode *pCrawl = root;
for (int i = 0; i < key.length(); i++)
{
int index = key[i] - 'a';
if (!pCrawl->children[index])
pCrawl->children[index] = getNode();
pCrawl = pCrawl->children[index];
}
// mark last node as leaf
pCrawl->isEndOfWord = true;
}
// Returns true if key presents in trie, else
// false
bool search(struct TrieNode *root, string key)
{
struct TrieNode *pCrawl = root;
for (int i = 0; i < key.length(); i++)
{
int index = key[i] - 'a';
if (!pCrawl->children[index])
return false;
pCrawl = pCrawl->children[index];
}
return (pCrawl != NULL && pCrawl->isEndOfWord);
}
// Driver
int main()
{
// Input keys (use only 'a' through 'z'
// and lower case)
string keys[] = {"the", "a", "there",
"answer", "any", "by",
"bye", "their" };
int n = sizeof(keys)/sizeof(keys[0]);
struct TrieNode *root = getNode();
// Construct trie
for (int i = 0; i < n; i++)
insert(root, keys[i]);
// Search for different keys
search(root, "the")? cout << "Yes\n" :
cout << "No\n";
search(root, "these")? cout << "Yes\n" :
cout << "No\n";
return 0;
}
C
// C implementation of search and insert operations
// on Trie
#include
#include
#include
#include
#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
// Alphabet size (# of symbols)
#define ALPHABET_SIZE (26)
// Converts key current character into index
// use only 'a' through 'z' and lower case
#define CHAR_TO_INDEX(c) ((int)c - (int)'a')
// trie node
struct TrieNode
{
struct TrieNode *children[ALPHABET_SIZE];
// isEndOfWord is true if the node represents
// end of a word
bool isEndOfWord;
};
// Returns new trie node (initialized to NULLs)
struct TrieNode *getNode(void)
{
struct TrieNode *pNode = NULL;
pNode = (struct TrieNode *)malloc(sizeof(struct TrieNode));
if (pNode)
{
int i;
pNode->isEndOfWord = false;
for (i = 0; i < ALPHABET_SIZE; i++)
pNode->children[i] = NULL;
}
return pNode;
}
// If not present, inserts key into trie
// If the key is prefix of trie node, just marks leaf node
void insert(struct TrieNode *root, const char *key)
{
int level;
int length = strlen(key);
int index;
struct TrieNode *pCrawl = root;
for (level = 0; level < length; level++)
{
index = CHAR_TO_INDEX(key[level]);
if (!pCrawl->children[index])
pCrawl->children[index] = getNode();
pCrawl = pCrawl->children[index];
}
// mark last node as leaf
pCrawl->isEndOfWord = true;
}
// Returns true if key presents in trie, else false
bool search(struct TrieNode *root, const char *key)
{
int level;
int length = strlen(key);
int index;
struct TrieNode *pCrawl = root;
for (level = 0; level < length; level++)
{
index = CHAR_TO_INDEX(key[level]);
if (!pCrawl->children[index])
return false;
pCrawl = pCrawl->children[index];
}
return (pCrawl != NULL && pCrawl->isEndOfWord);
}
// Driver
int main()
{
// Input keys (use only 'a' through 'z' and lower case)
char keys[][8] = {"the", "a", "there", "answer", "any",
"by", "bye", "their"};
char output[][32] = {"Not present in trie", "Present in trie"};
struct TrieNode *root = getNode();
// Construct trie
int i;
for (i = 0; i < ARRAY_SIZE(keys); i++)
insert(root, keys[i]);
// Search for different keys
printf("%s --- %s\n", "the", output[search(root, "the")] );
printf("%s --- %s\n", "these", output[search(root, "these")] );
printf("%s --- %s\n", "their", output[search(root, "their")] );
printf("%s --- %s\n", "thaw", output[search(root, "thaw")] );
return 0;
}
Java
// Java implementation of search and insert operations
// on Trie
public class Trie {
// Alphabet size (# of symbols)
static final int ALPHABET_SIZE = 26;
// trie node
static class TrieNode
{
TrieNode[] children = new TrieNode[ALPHABET_SIZE];
// isEndOfWord is true if the node represents
// end of a word
boolean isEndOfWord;
TrieNode(){
isEndOfWord = false;
for (int i = 0; i < ALPHABET_SIZE; i++)
children[i] = null;
}
};
static TrieNode root;
// If not present, inserts key into trie
// If the key is prefix of trie node,
// just marks leaf node
static void insert(String key)
{
int level;
int length = key.length();
int index;
TrieNode pCrawl = root;
for (level = 0; level < length; level++)
{
index = key.charAt(level) - 'a';
if (pCrawl.children[index] == null)
pCrawl.children[index] = new TrieNode();
pCrawl = pCrawl.children[index];
}
// mark last node as leaf
pCrawl.isEndOfWord = true;
}
// Returns true if key presents in trie, else false
static boolean search(String key)
{
int level;
int length = key.length();
int index;
TrieNode pCrawl = root;
for (level = 0; level < length; level++)
{
index = key.charAt(level) - 'a';
if (pCrawl.children[index] == null)
return false;
pCrawl = pCrawl.children[index];
}
return (pCrawl != null && pCrawl.isEndOfWord);
}
// Driver
public static void main(String args[])
{
// Input keys (use only 'a' through 'z' and lower case)
String keys[] = {"the", "a", "there", "answer", "any",
"by", "bye", "their"};
String output[] = {"Not present in trie", "Present in trie"};
root = new TrieNode();
// Construct trie
int i;
for (i = 0; i < keys.length ; i++)
insert(keys[i]);
// Search for different keys
if(search("the") == true)
System.out.println("the --- " + output[1]);
else System.out.println("the --- " + output[0]);
if(search("these") == true)
System.out.println("these --- " + output[1]);
else System.out.println("these --- " + output[0]);
if(search("their") == true)
System.out.println("their --- " + output[1]);
else System.out.println("their --- " + output[0]);
if(search("thaw") == true)
System.out.println("thaw --- " + output[1]);
else System.out.println("thaw --- " + output[0]);
}
}
// This code is contributed by Sumit Ghosh
Python
# Python program for insert and search
# operation in a Trie
class TrieNode:
# Trie node class
def __init__(self):
self.children = [None]*26
# isEndOfWord is True if node represent the end of the word
self.isEndOfWord = False
class Trie:
# Trie data structure class
def __init__(self):
self.root = self.getNode()
def getNode(self):
# Returns new trie node (initialized to NULLs)
return TrieNode()
def _charToIndex(self,ch):
# private helper function
# Converts key current character into index
# use only 'a' through 'z' and lower case
return ord(ch)-ord('a')
def insert(self,key):
# If not present, inserts key into trie
# If the key is prefix of trie node,
# just marks leaf node
pCrawl = self.root
length = len(key)
for level in range(length):
index = self._charToIndex(key[level])
# if current character is not present
if not pCrawl.children[index]:
pCrawl.children[index] = self.getNode()
pCrawl = pCrawl.children[index]
# mark last node as leaf
pCrawl.isEndOfWord = True
def search(self, key):
# Search key in the trie
# Returns true if key presents
# in trie, else false
pCrawl = self.root
length = len(key)
for level in range(length):
index = self._charToIndex(key[level])
if not pCrawl.children[index]:
return False
pCrawl = pCrawl.children[index]
return pCrawl != None and pCrawl.isEndOfWord
# driver function
def main():
# Input keys (use only 'a' through 'z' and lower case)
keys = ["the","a","there","anaswe","any",
"by","their"]
output = ["Not present in trie",
"Present in trie"]
# Trie object
t = Trie()
# Construct trie
for key in keys:
t.insert(key)
# Search for different keys
print("{} ---- {}".format("the",output[t.search("the")]))
print("{} ---- {}".format("these",output[t.search("these")]))
print("{} ---- {}".format("their",output[t.search("their")]))
print("{} ---- {}".format("thaw",output[t.search("thaw")]))
if __name__ == '__main__':
main()
# This code is contributed by Atul Kumar (www.facebook.com/atul.kr.007)
C#
// C# implementation of search and
// insert operations on Trie
using System;
public class Trie
{
// Alphabet size (# of symbols)
static readonly int ALPHABET_SIZE = 26;
// trie node
class TrieNode
{
public TrieNode[] children = new TrieNode[ALPHABET_SIZE];
// isEndOfWord is true if the node represents
// end of a word
public bool isEndOfWord;
public TrieNode()
{
isEndOfWord = false;
for (int i = 0; i < ALPHABET_SIZE; i++)
children[i] = null;
}
};
static TrieNode root;
// If not present, inserts key into trie
// If the key is prefix of trie node,
// just marks leaf node
static void insert(String key)
{
int level;
int length = key.Length;
int index;
TrieNode pCrawl = root;
for (level = 0; level < length; level++)
{
index = key[level] - 'a';
if (pCrawl.children[index] == null)
pCrawl.children[index] = new TrieNode();
pCrawl = pCrawl.children[index];
}
// mark last node as leaf
pCrawl.isEndOfWord = true;
}
// Returns true if key
// presents in trie, else false
static bool search(String key)
{
int level;
int length = key.Length;
int index;
TrieNode pCrawl = root;
for (level = 0; level < length; level++)
{
index = key[level] - 'a';
if (pCrawl.children[index] == null)
return false;
pCrawl = pCrawl.children[index];
}
return (pCrawl != null && pCrawl.isEndOfWord);
}
// Driver
public static void Main()
{
// Input keys (use only 'a'
// through 'z' and lower case)
String []keys = {"the", "a", "there", "answer",
"any", "by", "bye", "their"};
String []output = {"Not present in trie", "Present in trie"};
root = new TrieNode();
// Construct trie
int i;
for (i = 0; i < keys.Length ; i++)
insert(keys[i]);
// Search for different keys
if(search("the") == true)
Console.WriteLine("the --- " + output[1]);
else Console.WriteLine("the --- " + output[0]);
if(search("these") == true)
Console.WriteLine("these --- " + output[1]);
else Console.WriteLine("these --- " + output[0]);
if(search("their") == true)
Console.WriteLine("their --- " + output[1]);
else Console.WriteLine("their --- " + output[0]);
if(search("thaw") == true)
Console.WriteLine("thaw --- " + output[1]);
else Console.WriteLine("thaw --- " + output[0]);
}
}
/* This code contributed by PrinciRaj1992 */
输出 :
the --- Present in trie
these --- Not present in trie
their --- Present in trie
thaw --- Not present in trie
注意:在视频中, isEndOfWord被称为isLeaf 。
相关文章:
- 删除
- 显示Trie的内容
- Trie的应用
- 使用Trie的自动完成功能
- 最小断字
- 使用Trie对字符串(或单词)进行排序
- 使用所有后缀的特里搜索模式
练习题:
- 搜寻和插入
- 删除
- 二进制矩阵中的唯一行
- 不同子串的计数
- 单词花花公子
最近关于特里的文章