Алгоритм визуализации дерева

174
18 июля 2019, 22:30

Как реализовать вертикальную иерархию дерева? Дерево - с произвольным количеством дочерних вершин. Узел дерева хранит условные координаты X, Y на плоскости. Под вертикальной иерархией, я подразумеваю, что узлы располагаются слева направо (т.е. слева - родитель, правее - дочерние узлы и т.д.)

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

Answer 1

Как-то так:

using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleTest
{
    //узел дерева
    public class TreeNode
    {
        public TreeNode(string n)
        {
            this.Name = n;
            this.Children = new List<TreeNode>();
        }
        public string Name { get; set; } //имя узла
        public int X { get; set; } //горизонтальная координата для отображения (заполняется TreeCalcCoordinates)
        public int Y { get; set; } //вертикальная координата для отображения (заполняется TreeCalcCoordinates) 
        public List<TreeNode> Children { get; set; } //список дочерних узлов
    }
    class Program
    {
        //получает суммарное количество всех дочерних узлов (высоту поддерева)
        static int GetChildrenCountSum(TreeNode node)
        {
            if (node.Children.Count == 0) return 1;
            int c = 0;
            foreach (TreeNode child in node.Children) c += GetChildrenCountSum(child);
            return c;
        }
        //получает максимальную ширину узла в дереве
        static void TreeGetMaxWidth(TreeNode root, ref int maxwidth)
        {
            if (root.Name.Length > maxwidth) maxwidth = root.Name.Length;
            foreach (TreeNode child in root.Children) TreeGetMaxWidth(child, ref maxwidth);
        }
        static void TreeCalcCoordinates_Recursive(TreeNode node, int basex, int basey, int dx)
        {            
            node.X = basex;
            node.Y = basey;
            int c = basey;
            foreach (TreeNode child in node.Children)
            {
                TreeCalcCoordinates_Recursive(child, basex + dx, c, dx);
                c += GetChildrenCountSum(child);                
            }
        }
        //вычисляет координаты узлов в дереве
        static void TreeCalcCoordinates(TreeNode root)
        {
            int maxwidth = 0;
            TreeGetMaxWidth(root, ref maxwidth);
            int dx = maxwidth + 1;            
            TreeCalcCoordinates_Recursive(root, 0, 0, dx);
        }
        static void TreePrint_Recursive(TreeNode node)
        {
            Console.SetCursorPosition(node.X, node.Y);
            Console.Write(node.Name);
            foreach(TreeNode child in node.Children)
            {
                TreePrint_Recursive(child);
            }
        }
        //выводит дерево в консоль, используя вычисленные координаты
        static void TreePrint(TreeNode root)
        {
            Console.Clear();
            TreePrint_Recursive(root);
        }

        static void Main(string[] args)
        {
            //заполняем дерево тестовыми данными
            TreeNode root = new TreeNode("Животные");
            TreeNode node = new TreeNode("Млекопитающие");
            TreeNode node2 = new TreeNode("Хищные");
            node2.Children.Add(new TreeNode("Волк"));
            node2.Children.Add(new TreeNode("Лиса"));
            node.Children.Add(node2);
            node2 = new TreeNode("Зайцеобразные");
            node2.Children.Add(new TreeNode("Заяц"));
            node2.Children.Add(new TreeNode("Кролик"));
            node.Children.Add(node2);
            root.Children.Add(node);            
            node = new TreeNode("Птицы");
            node.Children.Add(new TreeNode("Пингвин"));
            node.Children.Add(new TreeNode("Попугай"));
            node.Children.Add(new TreeNode("Ворона"));            
            root.Children.Add(node);
            node = new TreeNode("Пресмыкающиеся");
            node.Children.Add(new TreeNode("Черепаха"));
            node.Children.Add(new TreeNode("Крокодил"));
            root.Children.Add(node);
            //вычисляем координаты
            TreeCalcCoordinates(root);
            //выводим дерево в консоль
            TreePrint(root);
            Console.ReadKey();
        }
    }
}
READ ALSO
Как сделать потоковый прием сообщений TCPClient?

Как сделать потоковый прием сообщений TCPClient?

Я не могу найти ответ на вопрос, я делаю простой чат с сервером и клиентом, сервер принимает все сообщения отправление клиентами и рассылает...

157
Кастомный Identity не обращается к /Identity/Account/Login

Кастомный Identity не обращается к /Identity/Account/Login

Я пробовал разные варианты кастомного identity, даже мелкие отступления в сторону от типового решения (допустим, решил поменять тип поля для...

142
Скорость работы алгоритма на C#

Скорость работы алгоритма на C#

Есть такая задачка простенькаяПодсчитать количество повторений строковых элементов в неотсортированных коллекциях

132
Как правильно считать время

Как правильно считать время

Есть статический класс (мой) в котором я в начале игры достаю из сервера время, как мне потом к нему прибавлять время пройденное в игре что...

143