<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh">
	<id>https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=Trie</id>
	<title>Trie - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=Trie"/>
	<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=Trie&amp;action=history"/>
	<updated>2026-07-16T18:26:57Z</updated>
	<subtitle>在这个wiki上该页的修订历史</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://arolstar52-zhtest.hf.space/index.php?title=Trie&amp;diff=8151&amp;oldid=prev</id>
		<title>imported&gt;范：​回退到由Duchuan1024（讨论）做出的修订版本79423348</title>
		<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=Trie&amp;diff=8151&amp;oldid=prev"/>
		<updated>2025-06-19T05:23:13Z</updated>

		<summary type="html">&lt;p&gt;回退到由&lt;a href=&quot;/wiki/Special:%E7%94%A8%E6%88%B7%E8%B4%A1%E7%8C%AE/Duchuan1024&quot; title=&quot;Special:用户贡献/Duchuan1024&quot;&gt;Duchuan1024&lt;/a&gt;（&lt;a href=&quot;/index.php?title=User_talk:Duchuan1024&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;User talk:Duchuan1024（页面不存在）&quot;&gt;讨论&lt;/a&gt;）做出的修订版本79423348&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{NoteTA&lt;br /&gt;
|G1 = IT&lt;br /&gt;
}}&lt;br /&gt;
[[File:trie example.svg|thumb|250px|一个保存了8个键的trie结构，&amp;quot;A&amp;quot;, &amp;quot;to&amp;quot;, &amp;quot;tea&amp;quot;, &amp;quot;ted&amp;quot;, &amp;quot;ten&amp;quot;, &amp;quot;i&amp;quot;, &amp;quot;in&amp;quot;, &amp;quot;inn&amp;quot;.]]&lt;br /&gt;
&lt;br /&gt;
在[[计算机科学]]中，&amp;#039;&amp;#039;&amp;#039;trie&amp;#039;&amp;#039;&amp;#039;，又称&amp;#039;&amp;#039;&amp;#039;前缀树&amp;#039;&amp;#039;&amp;#039;或&amp;#039;&amp;#039;&amp;#039;字典樹&amp;#039;&amp;#039;&amp;#039;，是一种有序[[树 (数据结构)|树]]，用于保存[[关联数组]]，其中的键通常是[[字符串]]。与[[二叉查找树]]不同，键不是直接保存在节点中，而是由节点在树中的位置决定。一个节点的所有子孙都有相同的[[前缀]]，也就是这个节点对应的字符串，而根节点对应[[空字符串]]。一般情况下，不是所有的节点都有对应的值，只有叶子节点和部分内部节点所对应的键才有相关的值。&lt;br /&gt;
&lt;br /&gt;
Trie这个术语来自于re&amp;#039;&amp;#039;&amp;#039;trie&amp;#039;&amp;#039;&amp;#039;val。trie的发明者Edward Fredkin把它读作{{IPAc-en|ˈ|t|r|iː}} &amp;quot;tree&amp;quot;。&amp;lt;ref name=DADS&amp;gt;{{cite web |url=http://www.nist.gov/dads/HTML/trie.html |title=trie |first=Paul E. |last=Black |date=2009-11-16 |work=Dictionary of Algorithms and Data Structures |publisher=[[国家标准技术研究所]] |archiveurl=https://www.webcitation.org/5pqUULy24?url=http://www.itl.nist.gov/div897/sqg/dads/HTML/trie.html |archivedate=2010-05-19 |deadurl=yes |accessdate=2012-07-08 }}&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;Liang1983&amp;quot;&amp;gt;{{cite thesis |degree=Doctor of Philosophy |title=Word Hy-phen-a-tion By Com-put-er |url=http://www.tug.org/docs/liang/liang-thesis.pdf |author=Franklin Mark Liang |year=1983 |publisher=Stanford University |accessdate=2010-03-28 |archiveurl=https://www.webcitation.org/5pqOfzlIA?url=http://www.tug.org/docs/liang/liang-thesis.pdf |archivedate=2010-05-19 |deadurl=yes }}&amp;lt;/ref&amp;gt;但是，其他作者把它读作{{IPAc-en|ˈ|t|r|aɪ}} &amp;quot;try&amp;quot;。&amp;lt;ref name=DADS/&amp;gt;&amp;lt;ref name=&amp;quot;Liang1983&amp;quot;/&amp;gt;&amp;lt;ref name = KnuthVol3&amp;gt;{{cite book|last=Knuth|first=Donald|authorlink=Donald Knuth|title=The Art of Computer Programming Volume 3: Sorting and Searching|edition=2nd|year=1997|publisher=Addison-Wesley|isbn=0-201-89685-0|page=492|chapter=6.3: Digital Searching}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在图示中，键标注在节点中，值标注在节点之下。每一个完整的英文单词对应一个特定的整数。Trie可以看作是一个[[确定有限状态自动机]]，尽管边上的符号一般是隐含在分支的顺序中的。&lt;br /&gt;
&lt;br /&gt;
键不需要被显式地保存在节点中。图示中标注出完整的单词，只是为了演示trie的原理。&lt;br /&gt;
&lt;br /&gt;
trie中的键通常是字符串，但也可以是其它的结构。trie的算法可以很容易地修改为处理其它结构的有序序列，比如一串数字或者形状的排列。比如，&amp;#039;&amp;#039;&amp;#039;bitwise trie&amp;#039;&amp;#039;&amp;#039;中的键是一串位元，可以用于表示整数或者内存地址。&lt;br /&gt;
&lt;br /&gt;
== 应用 ==&lt;br /&gt;
trie树常用于搜索提示。如当输入一个网址，可以自动搜索出可能的选择。当没有完全匹配的搜索结果，可以返回前缀最相似的可能。&amp;lt;ref&amp;gt;{{cite thesis |title=大规模中文文本检索中的高性能索引研究|degree=硕士|author=米嘉|origyear=2005}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 实现方式 ==&lt;br /&gt;
trie树实际上是一个[[确定有限状态自动机]](DFA)，通常用[[转移矩阵]]表示。行表示状态，列表示输入字符，（行，列）位置表示转移状态。这种方式的查询效率很高，但由于稀疏的现象严重，空间利用效率很低。也可以采用压缩的存储方式即链表来表示状态转移，但由于要线性查询，会造成效率低下。&lt;br /&gt;
&lt;br /&gt;
于是人们提出了下面两种结构。&amp;lt;ref name=&amp;quot;datrie&amp;quot;&amp;gt;{{Cite web |url=http://linux.thai.net/~thep/datrie/datrie.html |title=An Implementation of Double-Array Trie |access-date=2012-07-19 |archive-url=https://web.archive.org/web/20090319161214/http://linux.thai.net/~thep/datrie/datrie.html |archive-date=2009-03-19 |dead-url=yes }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 三数组Trie ===&lt;br /&gt;
三数组Trie（Triple-Array Trie）结构包括三个数组：base,next和check.&lt;br /&gt;
&lt;br /&gt;
=== 二数组Trie ===&lt;br /&gt;
二数组Trie（Double-Array Trie）包含base和check两个数组。base数组的每个元素表示一个Trie节点，即一个状态；check数组表示某个状态的前驱状态。&lt;br /&gt;
&lt;br /&gt;
== 实例 ==&lt;br /&gt;
这是一个用于词频统计的程序范例，因使用了&amp;lt;code&amp;gt;getline(3)&amp;lt;/code&amp;gt;，所以需要[[glibc]]才能链接成功，没有[[glibc]]的话可以自行改写。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define TREE_WIDTH 256&lt;br /&gt;
&lt;br /&gt;
#define WORDLENMAX 128&lt;br /&gt;
&lt;br /&gt;
struct trie_node_st {&lt;br /&gt;
        int count;&lt;br /&gt;
        int pass; //add a count for the part-include for example &amp;#039;this is&amp;#039; then the &amp;#039;is&amp;#039; is hited two times &lt;br /&gt;
        struct trie_node_st *next[TREE_WIDTH];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
static struct trie_node_st root={0, 0, {NULL}};&lt;br /&gt;
&lt;br /&gt;
static const char *spaces=&amp;quot; \t\n/.\&amp;quot;\&amp;#039;()&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
void myfree(struct trie_node_st * rt)&lt;br /&gt;
{&lt;br /&gt;
	for(int i=0; i&amp;lt;TREE_WIDTH; i++){&lt;br /&gt;
		if(rt-&amp;gt;next[i]!=NULL){&lt;br /&gt;
			myfree(rt-&amp;gt;next[i]);&lt;br /&gt;
			rt-&amp;gt;next[i] = NULL;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	free(rt);&lt;br /&gt;
	return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static int&lt;br /&gt;
insert (const char *word)&lt;br /&gt;
{&lt;br /&gt;
        int i;&lt;br /&gt;
        struct trie_node_st *curr, *newnode;&lt;br /&gt;
&lt;br /&gt;
        if (word[0]==&amp;#039;\0&amp;#039;){&lt;br /&gt;
                return 0;&lt;br /&gt;
        }&lt;br /&gt;
        curr = &amp;amp;root;&lt;br /&gt;
        for (i=0; ; ++i) {&lt;br /&gt;
                if (word[i] == &amp;#039;\0&amp;#039;) {&lt;br /&gt;
                        break;&lt;br /&gt;
                }&lt;br /&gt;
                curr-&amp;gt;pass++;//count&lt;br /&gt;
                if (curr-&amp;gt;next[ word[i] ] == NULL) {&lt;br /&gt;
                        newnode = (struct trie_node_st*)malloc(sizeof(struct trie_node_st));&lt;br /&gt;
                        memset (newnode, 0, sizeof(struct trie_node_st));&lt;br /&gt;
                        curr-&amp;gt;next[ word[i] ] = newnode;&lt;br /&gt;
                } &lt;br /&gt;
                curr = curr-&amp;gt;next[ word[i] ];&lt;br /&gt;
        }&lt;br /&gt;
        curr-&amp;gt;count ++;&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void&lt;br /&gt;
printword (const char *str, int n)&lt;br /&gt;
{&lt;br /&gt;
        printf (&amp;quot;%s\t%d\n&amp;quot;, str, n);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static int&lt;br /&gt;
do_travel (struct trie_node_st *rootp)&lt;br /&gt;
{&lt;br /&gt;
        static char worddump[WORDLENMAX+1];&lt;br /&gt;
        static int pos=0;&lt;br /&gt;
        int i;&lt;br /&gt;
&lt;br /&gt;
        if (rootp == NULL) {&lt;br /&gt;
                return 0;&lt;br /&gt;
        }&lt;br /&gt;
        if (rootp-&amp;gt;count) {&lt;br /&gt;
                worddump[pos]=&amp;#039;\0&amp;#039;;&lt;br /&gt;
                printword (worddump, rootp-&amp;gt;count+rootp-&amp;gt;pass);&lt;br /&gt;
        }&lt;br /&gt;
        for (i=0;i&amp;lt;TREE_WIDTH;++i) {&lt;br /&gt;
                worddump[pos++]=i;&lt;br /&gt;
                do_travel (rootp-&amp;gt;next[i]);&lt;br /&gt;
                pos--;&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int&lt;br /&gt;
main (void)&lt;br /&gt;
{&lt;br /&gt;
        char *linebuf=NULL, *line, *word;&lt;br /&gt;
        size_t bufsize=0;&lt;br /&gt;
        int ret;&lt;br /&gt;
&lt;br /&gt;
        while (1) {&lt;br /&gt;
                ret=getline (&amp;amp;linebuf, &amp;amp;bufsize, stdin);&lt;br /&gt;
                if (ret==-1) {&lt;br /&gt;
                        break;&lt;br /&gt;
                }&lt;br /&gt;
                line=linebuf;&lt;br /&gt;
                while (1) {&lt;br /&gt;
                        word = strsep (&amp;amp;line, spaces);&lt;br /&gt;
                        if (word==NULL) {&lt;br /&gt;
                                break;&lt;br /&gt;
                        }&lt;br /&gt;
                        if (word[0]==&amp;#039;\0&amp;#039;) {&lt;br /&gt;
                                continue;&lt;br /&gt;
                        }&lt;br /&gt;
                        insert (word);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        do_travel (&amp;amp;root);&lt;br /&gt;
&lt;br /&gt;
        free (linebuf);&lt;br /&gt;
&lt;br /&gt;
	for(int i=0; i&amp;lt;TREE_WIDTH; i++){&lt;br /&gt;
		if(root.next[i]!=NULL){&lt;br /&gt;
			myfree(root.next[i]);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
        exit (0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 参考资料 ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{计算机科学中的树}}&lt;br /&gt;
&lt;br /&gt;
[[Category:树结构]]&lt;/div&gt;</summary>
		<author><name>imported&gt;范</name></author>
	</entry>
</feed>