Подтвердить что ты не робот

Создайте простую, высокоэффективную структуру данных дерева в С#

Мне нужно создать каталог продукта в виде дерева.

каждое дерево node представляет идентификатор (строка), функции только для данных дерева 2:

  • getChild(string ID), дать идентификатор, получить детей (нет необходимости включать детские дети), если идентификатор равен null, получите все корневые узлы
  • getParent(string ID), вернуть родительский идентификатор, если есть, или null, если root

С тех пор как дерево решило, не изменится, поэтому я думаю, что лучший код в статике будет лучше. Поэтому я начинаю использовать словарь

"id": {parent:ID, child:[id2, id3, id4....]}

Так как у нас около 1000+ каталогов, я обнаружил, что быстро сбиваюсь с пути, много ошибок в статических данных и делаю конечный результат применимым. Кроме того, теперь я написал только десятки, и код выглядит как беспорядок.

Просьба посоветовать вам создать это простое дерево каталогов с высокой производительностью. Благодаря

4b9b3361

Ответ 1

Просто сделайте класс из него.

ОБНОВЛЕНО:

class TreeNode : IEnumerable<TreeNode>
{
    private readonly Dictionary<string, TreeNode> _children =
                                        new Dictionary<string, TreeNode>();

    public readonly string ID;
    public TreeNode Parent { get; private set; }

    public TreeNode(string id)
    {
        this.ID = id;
    }

    public TreeNode GetChild(string id)
    {
        return this._children[id];
    }

    public void Add(TreeNode item)
    {
        if (item.Parent != null)
        {
            item.Parent._children.Remove(item.ID);
        }

        item.Parent = this;
        this._children.Add(item.ID, item);
    }

    public IEnumerator<TreeNode> GetEnumerator()
    {
        return this._children.Values.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    public int Count
    {
        get { return this._children.Count; }
    }
}

Использование будет довольно простым для статического определения:

var tree = new TreeNode("Root")
               {
                   new TreeNode("Category 1")
                       {
                           new TreeNode("Item 1"),
                           new TreeNode("Item 2"),
                           new TreeNode("Item 3"),
                       },
                   new TreeNode("Category 2")
                       {
                           new TreeNode("Item 1"),
                           new TreeNode("Item 2"),
                           new TreeNode("Item 3"),
                           new TreeNode("Item 4"),
                       }
               };

Edit

Еще несколько функций для еще более простого создания...

public static TreeNode BuildTree(string tree)
{
    var lines = tree.Split(new[] { Environment.NewLine },
                           StringSplitOptions.RemoveEmptyEntries);

    var result = new TreeNode("TreeRoot");
    var list = new List<TreeNode> { result };

    foreach (var line in lines)
    {
        var trimmedLine = line.Trim();
        var indent = line.Length - trimmedLine.Length;

        var child = new TreeNode(trimmedLine);
        list[indent].Add(child);

        if (indent + 1 < list.Count)
        {
            list[indent + 1] = child;
        }
        else
        {
            list.Add(child);
        }
    }

    return result;
}

public static string BuildString(TreeNode tree)
{
    var sb = new StringBuilder();

    BuildString(sb, tree, 0);

    return sb.ToString();
}

private static void BuildString(StringBuilder sb, TreeNode node, int depth)
{
    sb.AppendLine(node.ID.PadLeft(node.ID.Length + depth));

    foreach (var child in node)
    {
        BuildString(sb, child, depth + 1);
    }
}


Применение:

var tree = TreeNode.BuildTree(@"
Cat1
 Sub1
  Item1
  Item2
  Item3
 Sub2
  Item1
  Item2
Cat2
 Sub1
 Sub2
  Item1
  Item2
 Sub3
  Item1
Cat3
Cat4");

Ответ 2

Я создал Node класс, который может быть полезен. Он быстрый и имеет некоторые дополнительные свойства, например:

  • Предки
  • Потомки
  • Siblings
  • Уровень node
  • Родитель
  • Root
  • Etc.

Ответ 3

Вы можете написать простое двоичное дерево, я пишу псевдокод:

class TreeNode {
    TreeNode Right;
    TreeNode Left;
    int id;
    //...
}

class BinTree {

    void Insert(TreeNode node)
    {
        while(true) {   
            if(node.id > target.id) {
                if(target.Right != null) {
                    target = target.Right;
                    continue;
                }
                else {
                    target.Right = node;
                    break;
                }
            }

            else if(node.id < target.id) {
                if(target.Left != null) {
                    target = target.Left;
                    continue;
                }
                else {
                    target.Left = node;
                    break;
                }   
            }

            else {
                throw new ArgumentException("Duplicated id");
            }
        }
    }


    TreeNode Search(int id)
    {
        TreeNode target = root;

        while(target != null) {
            if(id > target.id) {
                target = target.Right;
            }
            else if(id < target.id) {
                target = target.Left;
            }
            else {
                return target;
            }
        }

        return null;
    }

}

Но если ваш счетчик данных очень велик, возможно, дерево AVL более эффективно