Dowemo


Question:

I am working on a multi-level marketing (binary) which looks like this:

(but the binary tree is not required to be perfect. A node can have 0-2 child)

enter image description here

My problem is the data that I fetch from the database is flat list. enter image description here enter image description here

Notice that I am using hierarchyid (sql server 2014)

Basically the TextNode column is like a breadcrumb.

every slash / represents a level.

If I have TextNode of /1/ as root. then every node that starts with /1/ belongs to that root which are /1/, /1/1/ and /1/1/1/ (the root node is included which will be the level 0)

I've tried the accepted answer in this question but its not working.

How can I transform the flatlist to a Binary Tree so that I can easily traverse and display it on a screen?

Im using C#, ASP MVC 5, SQL Server 2014 if it matters.


Best Answer:


Here is a very simple implementation (assuming that Nodes are in the right order), which may be enhanced in multiple ways

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);


        }


    }


}


Sample usage:

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);


        }


    }


}





Copyright © 2011 Dowemo All rights reserved.    Creative Commons   AboutUs