拜读了 Jeffery Zhao 的大作 后,有自己写一棵前缀树的冲动,于是花了一点时间,朴素地实现了。
[EDIT]发现这个实现有很多漏洞,隐藏了……真要看,点此展开
代码:
using System.Collections.Generic; namespace DataStructure.Trees { public sealed class Trie<TKeyFragment, TValue> { private TrieNode<TKeyFragment, TValue> root; public Trie() { root = new TrieNode<TKeyFragment, TValue>(); } public Trie( TrieNode<TKeyFragment, TValue> root ) { this.root = root; } public bool Store( IEnumerable<TKeyFragment> key, TValue value ) { return root.Expand(key.GetEnumerator(), value); } public IEnumerable<TValue> LookFor( IEnumerable<TKeyFragment> key ) { return root.LookFor(key.GetEnumerator()); } } public class TrieNode<TKeyFragment, TValue> { protected Dictionary<TKeyFragment, TrieNode<TKeyFragment, TValue>> Table = new Dictionary<TKeyFragment, TrieNode<TKeyFragment, TValue>>(); protected List<TValue> ValueCollection = new List<TValue>(); protected internal virtual bool Expand( IEnumerator<TKeyFragment> keyEnumerator, TValue value ) { if ( keyEnumerator.MoveNext() ) { var nextfragment = keyEnumerator.Current; if ( !Table.ContainsKey(nextfragment) ) { Table.Add(nextfragment, new TrieNode<TKeyFragment, TValue>()); } return Table[nextfragment].Expand(keyEnumerator, value); } else { if ( !this.ValueCollection.Contains(value) ) { this.ValueCollection.Add(value); } return true; } } protected internal virtual IEnumerable<TValue> LookFor( IEnumerator<TKeyFragment> keyEnumerator ) { if ( keyEnumerator.MoveNext() ) { var nextfragment = keyEnumerator.Current; if ( !Table.ContainsKey(nextfragment) ) { return new List<TValue>(); } return Table[nextfragment].LookFor(keyEnumerator); } else { return ValueCollection; } } } }
用的话键的类型要实现 IEnumerable<TKeyFragment>,用法简单:
class Program { static void Main( string[] args ) { var mytrie = new Trie<char, string>(); mytrie.Store("I Love You", "Guys"); mytrie.Store("I Love You", "Cnblogs"); mytrie.Store("I Hate You", "Bad Guy"); mytrie.Store("I Hate You", "WTF"); mytrie.LookFor("I Love You").ToList().ForEach(str => Console.WriteLine(str)); mytrie.LookFor("I Hate You").ToList().ForEach(str => Console.WriteLine(str)); } }
还没有想到怎么合并没有对应 Value 的中间节点,回去再想想。