C, Как “потянуть” Двоичное дерево к [закрытой] консоли

Вот чем я закончил. @ Мэри заставила меня продвинуться вперед. Но поскольку я использую класс COM, у меня не может быть открытых конструкторов с параметрами.

Я добавил метод AddAddress, который дает мне необходимую функциональность. В своем первоначальном посте я как-то пропустил MyBase.New, который требуется для класса COM.

Я приветствую комментарии с пониманием этого подхода.

<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)>
Public Class ComClass1
#Region "COM GUIDs"
    ' These  GUIDs provide the COM identity for this class 
    ' and its COM interfaces. If you change them, existing 
    ' clients will no longer be able to access the class.
    Public Const ClassId As String = "c8e723b4-f229-4368-9737-97c4c71d490a"
    Public Const InterfaceId As String = "16275ddb-5cfe-47c0-995f-84a5f868ad1b"
    Public Const EventsId As String = "dad73a5c-8ac4-4384-a5f9-8e2c388b5514"
#End Region
    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.

    'Fields  
    Private _name As String
    Private _CustAddress As List(Of address)

    'Constructor for class ComClass
    Public Sub New()
        MyBase.New
        _CustAddress = New List(Of address)
    End Sub

    Public Sub AddAddress(a1 As String, a2 As String)
        Dim addr As New address(a1, a2)
        _CustAddress.Add(addr)
    End Sub

    Public Property CustName() As String
        Get
            Return _name
        End Get
        Set(ByVal Value As String)
            _name = Value
        End Set
    End Property

    Public Property CustAddress() As List(Of address)
        Get
            Return _CustAddress
        End Get
        Set(value As List(Of address))
            _CustAddress = value
        End Set
    End Property

    Public Class address

        Private _address1 As String
        Private _address2 As String

        Public Sub New(a1 As String, a2 As String)
            _address1 = a1
            _address2 = a2
        End Sub

        Public Property Address1 As String
            Get
                Return _address1
            End Get
            Set(value As String)
                _address1 = value
            End Set
        End Property

        Public Property Address2 As String
            Get
                Return _address2
            End Get
            Set(value As String)
                _address2 = value
            End Set
        End Property
    End Class

End Class

И код для реализации / тестирования выглядит следующим образом:

Dim TestClass As New ComClass1
        Dim myint As Int32

        TestClass.CustName = "John Smith"
        TestClass.AddAddress("123 Main Street", "Los Angeles")

        TestClass.AddAddress("13 Park Avenue", "New York")

        Debug.Print(TestClass.CustAddress(0).Address1)   '123 Main Stree'
        Debug.Print(TestClass.CustAddress(1).Address1)   '13 Park Avenue

        TestClass.CustAddress.Remove(TestClass.CustAddress(0))

        Debug.Print(TestClass.CustAddress(0).Address1)    ' 13 Park Avenue
69
задан SouvikMaji 9 July 2015 в 11:42
поделиться

5 ответов

Проверить Печать двоичных деревьев в Ascii

Из @AnyOneElse Pastbin ниже:

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!Code originally from /http://www.openasthra.com/c-tidbits/printing-binary-trees-in-ascii/
!!! Just saved it, cause the website is down.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Printing Binary Trees in Ascii

Here we are not going to discuss what binary trees are (please refer this, if you are looking for binary search trees), or their operations but printing them in ascii.

The below routine prints tree in ascii for a given Tree representation which contains list of nodes, and node structure is this

    struct Tree 
    {
      Tree * left, * right;
      int element;
    };

This pic illustrates what the below routine does on canvas..
ascii tree

Here is the printing routine..

    b5855d39a6b8a2735ddcaa04a404c125001 

Auxiliary routines..

    //This function prints the given level of the given tree, assuming
    //that the node has the given x cordinate.
    void print_level(asciinode *node, int x, int level) 
    {
      int i, isleft;
      if (node == NULL) return;
      isleft = (node->parent_dir == -1);
      if (level == 0) 
      {
        for (i=0; i<(x-print_next-((node->lablen-isleft)/2)); i++) 
        {
          printf(" ");
        }
        print_next += i;
        printf("%s", node->label);
        print_next += node->lablen;
      } 
      else if (node->edge_length >= level) 
      {
        if (node->left != NULL) 
        {
          for (i=0; i<(x-print_next-(level)); i++) 
          {
            printf(" ");
          }
          print_next += i;
          printf("/");
          print_next++;
        }
        if (node->right != NULL) 
        {
          for (i=0; i<(x-print_next+(level)); i++) 
          {
            printf(" ");
          }
          print_next += i;
          printf("\\");
          print_next++;
        }
      } 
      else 
      {
        print_level(node->left, 
                    x-node->edge_length-1, 
                    level-node->edge_length-1);
        print_level(node->right, 
                    x+node->edge_length+1, 
                    level-node->edge_length-1);
      }
    }


    //This function fills in the edge_length and 
    //height fields of the specified tree
    void compute_edge_lengths(asciinode *node) 
    {
      int h, hmin, i, delta;
      if (node == NULL) return;
      compute_edge_lengths(node->left);
      compute_edge_lengths(node->right);

      /* first fill in the edge_length of node */
      if (node->right == NULL && node->left == NULL) 
      {
        node->edge_length = 0;
      } 
      else 
      {
        if (node->left != NULL) 
        {
          for (i=0; i<node->left->height && i < MAX_HEIGHT; i++) 
          {
            rprofile[i] = -INFINITY;
          }
          compute_rprofile(node->left, 0, 0);
          hmin = node->left->height;
        } 
        else 
        {
          hmin = 0;
        }
        if (node->right != NULL) 
        {
          for (i=0; i<node->right->height && i < MAX_HEIGHT; i++) 
          {
            lprofile[i] = INFINITY;
          }
          compute_lprofile(node->right, 0, 0);
          hmin = MIN(node->right->height, hmin);
        } 
        else 
        {
          hmin = 0;
        }
        delta = 4;
        for (i=0; i<hmin; i++) 
        {
          delta = MAX(delta, gap + 1 + rprofile[i] - lprofile[i]);
        }

        //If the node has two children of height 1, then we allow the
        //two leaves to be within 1, instead of 2 
        if (((node->left != NULL && node->left->height == 1) ||
              (node->right != NULL && node->right->height == 1))&&delta>4) 
        {
          delta--;
        }

        node->edge_length = ((delta+1)/2) - 1;
      }

      //now fill in the height of node
      h = 1;
      if (node->left != NULL) 
      {
        h = MAX(node->left->height + node->edge_length + 1, h);
      }
      if (node->right != NULL) 
      {
        h = MAX(node->right->height + node->edge_length + 1, h);
      }
      node->height = h;
    }

    asciinode * build_ascii_tree_recursive(Tree * t) 
    {
      asciinode * node;

      if (t == NULL) return NULL;

      node = malloc(sizeof(asciinode));
      node->left = build_ascii_tree_recursive(t->left);
      node->right = build_ascii_tree_recursive(t->right);

      if (node->left != NULL) 
      {
        node->left->parent_dir = -1;
      }

      if (node->right != NULL) 
      {
        node->right->parent_dir = 1;
      }

      sprintf(node->label, "%d", t->element);
      node->lablen = strlen(node->label);

      return node;
    }


    //Copy the tree into the ascii node structre
    asciinode * build_ascii_tree(Tree * t) 
    {
      asciinode *node;
      if (t == NULL) return NULL;
      node = build_ascii_tree_recursive(t);
      node->parent_dir = 0;
      return node;
    }

    //Free all the nodes of the given tree
    void free_ascii_tree(asciinode *node) 
    {
      if (node == NULL) return;
      free_ascii_tree(node->left);
      free_ascii_tree(node->right);
      free(node);
    }

    //The following function fills in the lprofile array for the given tree.
    //It assumes that the center of the label of the root of this tree
    //is located at a position (x,y).  It assumes that the edge_length
    //fields have been computed for this tree.
    void compute_lprofile(asciinode *node, int x, int y) 
    {
      int i, isleft;
      if (node == NULL) return;
      isleft = (node->parent_dir == -1);
      lprofile[y] = MIN(lprofile[y], x-((node->lablen-isleft)/2));
      if (node->left != NULL) 
      {
        for (i=1; i <= node->edge_length && y+i < MAX_HEIGHT; i++) 
        {
          lprofile[y+i] = MIN(lprofile[y+i], x-i);
        }
      }
      compute_lprofile(node->left, x-node->edge_length-1, y+node->edge_length+1);
      compute_lprofile(node->right, x+node->edge_length+1, y+node->edge_length+1);
    }

    void compute_rprofile(asciinode *node, int x, int y) 
    {
      int i, notleft;
      if (node == NULL) return;
      notleft = (node->parent_dir != -1);
      rprofile[y] = MAX(rprofile[y], x+((node->lablen-notleft)/2));
      if (node->right != NULL) 
      {
        for (i=1; i <= node->edge_length && y+i < MAX_HEIGHT; i++) 
        {
          rprofile[y+i] = MAX(rprofile[y+i], x+i);
        }
      }
      compute_rprofile(node->left, x-node->edge_length-1, y+node->edge_length+1);
      compute_rprofile(node->right, x+node->edge_length+1, y+node->edge_length+1);
    }

Here is the asciii tree structure…

    struct asciinode_struct
    {
      asciinode * left, * right;

      //length of the edge from this node to its children
      int edge_length; 

      int height;      

      int lablen;

      //-1=I am left, 0=I am root, 1=right   
      int parent_dir;   

      //max supported unit32 in dec, 10 digits max
      char label[11];  
    };

вывод:

        2
       / \
      /   \
     /     \
    1       3
   / \     / \
  0   7   9   1
 /   / \     / \
2   1   0   8   8
       /
      7
41
ответ дан 24 November 2019 в 13:47
поделиться

Я рекомендую второй лит. Мне пришлось сделать это в последнее время, чтобы напечатать VAD-дерево процесса Windows, и я использовал язык DOT (просто распечатывал узлы из функции бинарного обхода дерева):

http://en.wikipedia.org/wiki/DOT_language

Например, ваш файл DOT будет содержать:

digraph graphname {
     5 -> 3;
     5 -> 8;
     3 -> 4;
     3 -> 2;
}

Вы генерируете график с помощью dotty.exe или конвертируете его в PNG с помощью dot.exe.

3
ответ дан 24 November 2019 в 13:47
поделиться

Некоторые подсказки: расстояние между узлами на одной глубине (например, 2 и 4 или 3 и 8 в вашем примере) является функцией глубины.

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

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

Начиная с корневого узла, поиск в ширину будет посещать узлы в порядке глубины и самой левой позиции.

Расстояние между узлами можно найти, найдя максимальную высоту дерева, используя некоторую постоянную ширину для самых глубоких узлов, и удвоив эту ширину для каждой меньшей глубины, чтобы ширина для любой глубины = (1 + maxdepth - currentdepth ) * deepestwidth.

Это число дает вам напечатанное " вставлю фиктивные проставки для любого узла, у которого нет родителей; более простой способ сделать это - убедиться, что все листья находятся на той же глубине, что и самый глубокий узел, с пустым значением . Очевидно, что вам также придется компенсировать ширину значений, возможно, делая ширину наибольшей глубины, по крайней мере, такой же ширины, как напечатанная (предположительно, десятичное представление) самого большого узла.

вставлю фиктивные проставки для любого узла, у которого нет родителей; более простой способ сделать это - убедиться, что все листья находятся на той же глубине, что и самый глубокий узел, с пустым значением . Очевидно, что вам также придется компенсировать ширину значений, возможно, делая ширину наибольшей глубины, по крайней мере, такой же ширины, как напечатанная (предположительно, десятичное представление) самого большого узла.

20
ответ дан 24 November 2019 в 13:47
поделиться

Я думаю, вам не следует кодировать это самостоятельно, но взгляните на Tree :: Visualize , который, похоже, является хорошей реализацией Perl с различными возможными стилями и использует / порт один из алгоритмов там.

1
ответ дан 24 November 2019 в 13:47
поделиться

Посмотрите на вывод команды pstree в Linux. Он не производит вывод в точной форме, которую вы хотите, но, IMHO, он более читабелен.

3
ответ дан 24 November 2019 в 13:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: