5

私は次のようなマルチレベル マーケティング (バイナリ) に取り組んでいます。

(ただし、二分木は完全である必要はありません。ノードは 0 ~ 2 個の子を持つことができます)

ここに画像の説明を入力

私の問題は、データベースから取得したデータがフラット リストであることです。 ここに画像の説明を入力 ここに画像の説明を入力

hierarchyidを使用していることに注意してください(SQL Server 2014)

基本的に、TextNode列はブレッドクラムのようなものです。

すべてのスラッシュ/は を表しますlevel

ルートとしてTextNode がある場合/1/。次に、 で始まるすべてのノードは/1/そのルートに属し/1/、 、/1/1/および/1/1/1/(レベル 0 になるルート ノードが含まれます)

この質問で受け入れられた回答を試しましたが、うまくいきません。

フラットリストをバイナリツリーに変換して、簡単にトラバースして画面に表示できるようにするにはどうすればよいですか?

問題があれば、C#、ASP MVC 5、SQL Server 2014 を使用しています。

4

2 に答える 2

-1

これは非常に単純な実装 (ノードが正しい順序であると仮定) であり、複数の方法で拡張できます。

public interface IRow<out T>
{
    string TextNode { get; }
    T Value { get; }
}

public class TreeNode<T>
{
    private struct NodeDescriptor
    {
        public int Level { get; }
        public int ParentIndex { get; }

        public NodeDescriptor(IRow<T> row)
        {
            var split = row.TextNode.Split(new [] {"/"}, StringSplitOptions.RemoveEmptyEntries);
            Level = split.Length;
            ParentIndex = split.Length > 1 ? int.Parse(split[split.Length - 2]) - 1 : 0;
        }
    }

    public T Value { get; }
    public List<TreeNode<T>> Descendants { get; }

    private TreeNode(T value)
    {
        Value = value;
        Descendants = new List<TreeNode<T>>();
    }

    public static TreeNode<T> Parse(IReadOnlyList<IRow<T>> rows)
    {
        if (rows.Count == 0)
            return null;
        var result = new TreeNode<T>(rows[0].Value);
        FillParents(new[] {result}, rows, 1, 1);
        return result;
    }

    private static void FillParents(IList<TreeNode<T>> parents, IReadOnlyList<IRow<T>> rows, int index, int currentLevel)
    {
        var result = new List<TreeNode<T>>();
        for (int i = index; i < rows.Count; i++)
        {
            var descriptor = new NodeDescriptor(rows[i]);
            if (descriptor.Level != currentLevel)
            {
                FillParents(result, rows, i, descriptor.Level);
                return;
            }
            var treeNode = new TreeNode<T>(rows[i].Value);
            parents[descriptor.ParentIndex].Descendants.Add(treeNode);
            result.Add(treeNode);
        }
    }
}

使用例:

public class Row : IRow<string>
{
    public string TextNode { get; }
    public string Value { get; }

    public Row(string textNode, string userName)
    {
        TextNode = textNode;
        Value = userName;
    }
}

class Program
{

    static void Main(string[] args)
    {
        IRow<string>[] rows =
        {
            new Row("/", "Ahmed"),
            new Row("/1/", "Saeed"),
            new Row("/2/", "Amjid"),
            new Row("/1/1/", "Noura"),
            new Row("/2/1/", "Noura01"),
            new Row("/2/2/", "Reem01"),
            new Row("/1/1/1", "Under_noura")
        };

        var tree = TreeNode<string>.Parse(rows);
        PrintTree(tree);
    }

    private static void PrintTree<T>(TreeNode<T> tree, int level = 0)
    {
        string prefix = new string('-', level*2);
        Console.WriteLine("{0}{1}", prefix, tree.Value);
        foreach (var node in tree.Descendants)
        {
            PrintTree(node, level + 1);
        }
    }
}
于 2016-08-10T10:34:40.777 に答える