5

我正在做一个看起来像这样的多层次营销(二进制):

(但二叉树不需要完美,一个节点可以有0-2个孩子)

在此处输入图像描述

我的问题是我从数据库中获取的数据是平面列表。 在此处输入图像描述 在此处输入图像描述

请注意,我使用的是hierarchyid (sql server 2014)

基本上,该TextNode列就像一个面包屑。

每个斜线/代表一个level

如果我有 TextNode/1/作为根。那么/1//1/_ /1/1/_ /1/1/1/_

我已经尝试了这个问题中接受的答案,但它不起作用。

如何将平面列表转换为二叉树,以便轻松遍历并将其显示在屏幕上?

如果重要的话,我正在使用 C#、ASP MVC 5、SQL Server 2014。

4

2 回答 2

0

我完全实现了这段代码根据 Alex 实现,但正如在某些情况下提到的那样它不能正常工作.. 看看我的图像和我的代码(从 Alex 帖子复制)[数据库中的数据是正确的,但在树中看来有些问题]

public class Row : IRow<string>
{
    public string TextNode { get; }
    public string Value { get; }
    public long Id { get; }
    public string FIN { get; }
    public Row(string textNode, string userName, long id, string fin)
    {
        FIN = fin;
        Id = id;
        TextNode = textNode;
        Value = userName;
    }
}

public interface IRow<out T>
{
    string TextNode { get; }
    long Id { get; }
    string FIN { 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 title { get; }
    public long Id { get; }
    public string FIN { get; }
    public List<TreeNode<T>> children { get; }

    private TreeNode(T value, long id, string fin)
    {
        Id = id;
        FIN = fin;
        title = value;
        children = 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, rows[0].Id, rows[0].FIN);
        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, rows[i].Id, rows[i].FIN);
            parents[descriptor.ParentIndex].children.Add(treeNode);
            result.Add(treeNode);
        }
    }
}

在此处输入图像描述

在此处输入图像描述G

这也是我的 JSON 输出以获取更多信息:

{"title":"Earth","Id":32,"FIN":"FIN","children":[{"title":"Europe","Id":33,"FIN":"FIN001","children":[{"title":"France","Id":35,"FIN":"FIN001001","children":[{"title":"Paris","Id":36,"FIN":"FIN001001001","children":[]},{"title":"Brasilia","Id":41,"FIN":"FIN002001001","children":[]},{"title":"Bahia","Id":42,"FIN":"FIN002001002","children":[]}]},{"title":"Spain","Id":38,"FIN":"FIN001002","children":[{"title":"Madrid","Id":37,"FIN":"FIN001002001","children":[{"title":"Salvador","Id":43,"FIN":"FIN002001002001","children":[]}]}]},{"title":"Italy","Id":45,"FIN":"FIN001003","children":[]},{"title":"Germany","Id":48,"FIN":"FIN001004","children":[]},{"title":"test","Id":10049,"FIN":"FIN001005","children":[]}]},{"title":"South America","Id":34,"FIN":"FIN002","children":[{"title":"Brazil","Id":40,"FIN":"FIN002001","children":[{"title":"Morano","Id":47,"FIN":"FIN001003001","children":[]}]}]},{"title":"Antarctica","Id":39,"FIN":"FIN003","children":[{"title":"McMurdo Station","Id":44,"FIN":"FIN003001","children":[]}]}]}
于 2020-05-28T22:38:36.443 回答
-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 回答