开发者

Adding multiple unique children at multiple levels with one or more loops and “clean” code

I’m a C# beginner and at the moment I’m trying to challenge myself with different problems.

At the moment I’m trying to build a web application where you can input letters and wildcards to search after possible words.

Trough previous questions about this I’ve decided to build a Trie containing letters generated from 400k+ words. Later I’ll search the Trie for possible word matches depending on letter and wildcard input.

I’ve built two classes, one representing one node in the Trie and one representing the whole Trie.

I’m currently at a standstill, my problem is that I want to add multiple children to the Trie at multiple levels and every child has to be uniqe.

Doing this manually would look something like this:

//Level 1
Root.Children.Add(new TrieNode(Letter, false, new List<TrieNode>()));
//Level 2
Root.Children[0].Children.Add(new TrieNode(Letter, false, new List<TrieNode>()));
//Level 3
Root.Children[0].Children[0].Children.Add(new TrieNode(Letter, false, new List<TrieNode>()));

Problem is that I want to add children with one or more loops and doing it this way seems a little “wrong”:

LetterArray = Word.ToCharArray();
int level = 0;
foreach (char Letter in LetterArray)
{
    //Level 1
    if (level == 0)
        Root.Children.Add(new TrieNode(Letter, false, new List<TrieNode>()));
    //Level 2
    if (level == 1)    
        Root.Children[0].Children.Add(new TrieNode(Letter, false, new List<TrieNode>()));
    //Level 3
    if (level == 2)
        Root.Children[0].Children[0].Children.Add(new TrieNode(Letter, false, new List<Tri开发者_如何学GoeNode>()));

    level++;
}

What I need is one or more loops with “clean” code, think you can help me? For the Trie to be searchable later the letters needs to come in order i think. Here are my other questions related to this: Question 1, Question 2.

Here’s my TrieNode Class:

public class TrieNode
{
    private char _Letter;
    private bool _IsEndOfWord;
    private List<TrieNode> _Children;

    public char Letter {
        get { return _Letter; }
        set { _Letter = value; }
    }
    public bool IsEndOfWord {
        get { return _IsEndOfWord; }
        set { _IsEndOfWord = value; }
    }
    public List<TrieNode> Children {
        get { return _Children; }
        set { _Children = value; }
    }

    public TrieNode(char letter, bool isEndOfWord, List<TrieNode> children) {
        Letter = letter;
        IsEndOfWord = isEndOfWord;
        Children = children;
    }
}

… and here is my Trie Class:

public class Trie
{
    private TrieNode _Root;

    public TrieNode Root
    {
        get { return _Root; }
        set { _Root = value; }
    }

    public Trie(List<string> Words)
    {
        Root = new TrieNode('^', false, new List<TrieNode>());
        char[] LetterArray;

        foreach (String Word in Words)
        {
            LetterArray = Word.ToCharArray();

            foreach (char Letter in LetterArray)
            {
                // Here is where I want to add nodes to my Trie
            }
        }
    }
}


Are you looking for recursion?
http://en.wikipedia.org/wiki/Recursion_%28computer_science%29

using System.Linq;

public Trie(List<string> words)
{
    Root = new TrieNode('^', false, new List<TrieNode>());
    // Might have gotten the wrong method, check with intellisense
    char[] letters = words.SelectMany( word => word.ToCharArray());
    RecursiveAdd(letters, Root, 0);
}

private const int desiredDepth = 5;
private void RecursiveAdd(char[] letters, TrieNode branch, currentDepth)
{
    foreach(char letter in letters) {
        TrieNode node = new TrieNode(Letter, false, new List<TrieNode>());
        branch.Children.Add(node);
        if( currentDepth < desiredDepth ) {
            RecursiveAdd(letters, node, currentDepth+1);
        }
    }
}

I hope this helps, and sorry if I did too much work for you.
The best way to learn is doing, I agree.


I'd accomplish this through recursion as well, however my recursive method would be inside the TrieNode class:

public AddWord(string word)
{
    if (String.IsNullOrEmpty(word))
    {
        throw new ArgumentException("word must contain values.", word);
    }

    var letter = word[0];
    var child = Children.FirstOrDefault(x => x.Letter = letter);

    if (child == null)
    {
        //The child doesn't exist.  Create it.
        child = new TrieNode(letter, false, new List<TrieNode>());
    }

    if (word.Length > 1)
    {
        child.AddWord(word.Substring(1);
    }
    else
    {
        child.IsEndOfWord = true;
    }
}

Finally you just have to change your initial loop in your Trie constructor:

foreach (String Word in Words)
{
    _Root.AddWord(Word);
}

(note: I haven't tested this code so there may be typos).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜