C#实现字典树

 C#实现字典树,欢迎测试。

 
  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication7
{
public class Trie
{
private static Node Root = new Node( ' ' );
private int Capbility = 10 ;
public Trie( int capbility)
{
Capbility
= capbility;
}
public void AddWord( string Word)
{
List
< char > charArr = new List < char > (Word.ToCharArray());
AddNode(Root, charArr);
}
public List < string > Search( string Word)
{
List
< string > SearchResult = new List < string > ();
// 先深度先直线搜索,到达节点,再广度优先搜索。
Node DFSCurrentNode = Root;
char [] CharArr = Word.ToCharArray();
bool IsExists = true ;
for ( int i = 0 ; i < Word.Length; i ++ )
{
if (DFSCurrentNode.Nodes != null )
{
// 如果找到了
if (DFSCurrentNode.Nodes.ContainsKey(CharArr[i]))
{
// 继续找。
DFSCurrentNode = DFSCurrentNode.Nodes[CharArr[i]];
}
else
{
// 没找到中断。
IsExists = false ;
}
}
}
// 深搜到了节点,在此节点上广搜。
if (IsExists)
{
List
< SearchInfo > CurrentNodeList = new List < SearchInfo > () { new SearchInfo(DFSCurrentNode, Word) };
BFS(SearchResult, CurrentNodeList);
}
return SearchResult;
}


// 广度优先搜索
private void BFS(List < string > SearchResult, List < SearchInfo > CurrentNodeList)
{
// 结果足够,退出
if (SearchResult.Count >= Capbility || CurrentNodeList.Count == 0 )
{
return ; }
bool IsOver = false ;
// 记录当前节点CurrentNodeList旧长度OldCount,以便于事后移除。
int OldCount = CurrentNodeList.Count;
// 遍历当前节点集合。
// foreach (SearchInfo SI in CurrentNodeList)
for ( int i = 0 ; i < OldCount; i ++ )
{
SearchInfo SI
= CurrentNodeList[i];
/// /遍历当前单个节点的子节点。
if (SI.CurrentNode.Nodes != null )
{
foreach (Node N in SI.CurrentNode.Nodes.Values)
{
// 记录路径。
string Word = SI.Word + N.Char;
// 路径有结尾标记,进入结果。
if (N.IsEnd)
{
SearchResult.Add(Word);
}
// 结果足够,退出
if (SearchResult.Count >= Capbility)
{
IsOver
= true ;
break ;
}
else
{
// 把子节点追加到CurrentNodeList尾部。
CurrentNodeList.Add( new SearchInfo(N, Word));
}
}
}
if (IsOver)
{
break ;
}
}
// 如果结果还不够
if ( ! IsOver)
{
// 移除当前节点,就是CurrentNodeList在L0以前的记录。
CurrentNodeList.RemoveRange( 0 , OldCount);
// 进入下一轮搜索。
BFS(SearchResult, CurrentNodeList);
}
}
private void AddNode(Node N, List < char > charArr)
{
if (charArr.Count > 0 )
{
char C = charArr[ 0 ];
if (N.Nodes == null )
{
N.Nodes
= new Dictionary < char , Node > ();
}
if ( ! N.Nodes.ContainsKey(C))
{
Node newNode
= new Node(C);
N.Nodes.Add(C, newNode);
}
if (charArr.Count == 1 )
{
N.Nodes[C].IsEnd
= true ;
}
charArr.RemoveAt(
0 );
AddNode(N.Nodes[C], charArr);
}
}
// 当前搜索的节点信息。相当于键值对

private bool Contains(Dictionary < char , Node > Nodes, char C)
{

return true ;
}
private class SearchInfo
{
public SearchInfo(Node N, string W)
{
CurrentNode
= N;
Word
= W;
}
public string Word;
public Node CurrentNode;
}
private class Node
{
public Node( char C)
{
Char
= C;
}
public char Char;
public bool IsEnd = false ;
public Dictionary < char , Node > Nodes;
}
}
}

测试代码:

 
  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace ConsoleApplication7
{
class Program
{
static void Main( string [] args)
{
// 在网站启动时候,批量添加词库。也可以在运行中单独添加新词。
// 注意,核心容器是Static的全局变量,如果一个站运行多个词库,复制Trie类为其他名字,比如TrieFeeling,TrieOtherWord等
// 操作实例可以各个页面随意创建新实例,其中添加操作是影响全局的,搜索是动态的互不干扰的。
int n = 100 ; // 期望结果大小

Trie T
= new Trie(n);
int count = 10 * 10000 ;
Double M1
= getMem();
string [] Arr = new string [count];
for ( int i = 0 ; i < Arr.Length; i ++ )
{
Arr[i]
= (Guid.NewGuid()).ToString();
}
Stopwatch SW
= new Stopwatch();
Console.WriteLine(
" 原始内存消耗(兆) " + (getMem() - M1));
M1
= getMem();

SW.Start();
for ( int i = 0 ; i < Arr.Length; i ++ )
{
T.AddWord(Arr[i]);
}
SW.Stop();
Console.WriteLine(
" 插入 " + Arr.Length + " 条单词耗时: " + SW.ElapsedMilliseconds + " 毫秒,增加内存消耗(兆) " + (getMem() - M1));
// 搜索测试一
M1 = getMem();
Console.WriteLine(
" -------------输入:‘‘12’’--------------- " );
SW.Start();
List
< string > Result1 = T.Search( " 12 " );
SW.Stop();

Console.WriteLine(
" 查询耗时: " + SW.ElapsedMilliseconds + " 毫秒,增加内存消耗(兆) " + (getMem() - M1));
foreach ( string S in Result1)
{
Console.WriteLine(S);
}
// 搜索测试二
Console.WriteLine( " -------------对比测试,常规IndexOf:‘‘12’’--------------- " );
int Num = 0 ;
SW.Start();
foreach ( string S in Arr)
{
if (S.IndexOf( " 12 " ) == 0 )
{
Console.WriteLine(S);
Num
++ ;
}
if (Num == n)
{
break ;
}
}
SW.Stop();
Console.WriteLine(
" 查询耗时: " + SW.ElapsedMilliseconds + " 毫秒 " );
Console.WriteLine(
" 仅仅快了一两百毫秒,却消耗了大量内存来存储? " );
Console.Read();
}

static Double getMem()
{
Process CurrentProcess
= Process.GetCurrentProcess();
return CurrentProcess.WorkingSet64 / 1024 / 1024 ; // 占用内存

}

}
}

转载于:https://www.cnblogs.com/dullwolf/archive/2011/04/15/2017479.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值