Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C如何;画;控制台的二叉树_C_Algorithm_Layout_Binary Tree - Fatal编程技术网

C如何;画;控制台的二叉树

C如何;画;控制台的二叉树,c,algorithm,layout,binary-tree,C,Algorithm,Layout,Binary Tree,在控制台中可以使用什么算法绘制二叉树?树是用C实现的。例如,一个编号为2 3 4 5 8的BST将在控制台中显示为: 我认为您不应该自己编写代码,而是应该看看哪一个Perl实现看起来不错,可能有不同的风格,并使用/port其中一个算法。一些提示:相同深度的节点之间的间距(例如,在您的示例中为2和4或3和8)是深度的函数 每个打印行由具有相同深度的所有节点组成,从最左侧节点打印到最右侧节点 因此,您需要一种方法,例如,根据节点的深度,按照其最左侧的顺序,将节点排列成行数组 从根节点开始,广度优先搜

在控制台中可以使用什么算法绘制二叉树?树是用C实现的。例如,一个编号为2 3 4 5 8的BST将在控制台中显示为:


我认为您不应该自己编写代码,而是应该看看哪一个Perl实现看起来不错,可能有不同的风格,并使用/port其中一个算法。

一些提示:相同深度的节点之间的间距(例如,在您的示例中为2和4或3和8)是深度的函数

每个打印行由具有相同深度的所有节点组成,从最左侧节点打印到最右侧节点

因此,您需要一种方法,例如,根据节点的深度,按照其最左侧的顺序,将节点排列成行数组

从根节点开始,广度优先搜索将按深度和最左侧的顺序访问节点

节点之间的间距可以通过查找树的最大高度来找到,对最深的节点使用一些恒定的宽度,并对每一个较小的深度将该宽度加倍,以便任何深度的宽度=(1+maxdepth-currentdepth)*DeepTestWidth

该数字给出了在任何特定深度处每个节点的打印“水平宽度”

左节点水平定位在其父节点宽度的左半部分,右半部分为righ节点。您将为没有父节点的任何节点插入虚拟间隔符;一种更简单的方法是确保所有叶与最深节点的深度相同,并将空白作为其值。显然,您还必须补偿值的宽度,可能是通过使最大深度的宽度至少与最大值节点的打印宽度(大概是十进制表示)一样宽。

检查

从下面的@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];  
    };

查看Linux中pstree命令的输出。
它不会以您想要的确切形式生成输出,但我认为这样更具可读性。

我支持litb的建议。我最近不得不这样做来打印Windows进程的VAD树,我使用了点语言(只需从二叉树遍历函数中打印节点):

例如,您的点文件将包含:

digraph graphname { 5 -> 3; 5 -> 8; 3 -> 4; 3 -> 2; } 有向图{ 5 -> 3; 5 -> 8; 3 -> 4; 3 -> 2; }
您可以使用dotty.exe生成图形,或者使用dot.exe将其转换为PNG。

我有一个Ruby程序,可以计算二叉树中每个节点的坐标:


这段代码使用一个非常基本的算法来计算坐标,它不是“面积效率”,但这是一个很好的开始。如果你想看到代码“Live”,你可以在这里测试:

< P>我在C++中有这个小的解决方案,它可以很容易地转换成C.< 我的解决方案确实需要一个补充数据结构来存储树中当前节点的深度(这是因为如果您使用的是一个不完整的树,那么给定的子树的深度可能与它在完整树中的深度不一致。)


在阵列中实现树时,还有一个注意事项:

#include <stdio.h>
#include <math.h>


#define PARENT(i) ((i-1) / 2)
#define NUM_NODES 15
#define LINE_WIDTH 70

int main() {
    int tree[NUM_NODES]={0,1,2,3,4,5,6,7,8,9,1,2,3,4,5};
    int print_pos[NUM_NODES];
    int i, j, k, pos, x=1, level=0;

    print_pos[0] = 0;
    for(i=0,j=1; i<NUM_NODES; i++,j++) {
        pos = print_pos[PARENT(i)] + (i%2?-1:1)*(LINE_WIDTH/(pow(2,level+1))+1);

        for (k=0; k<pos-x; k++) printf("%c",i==0||i%2?' ':'-');
        printf("%d",tree[i]);

        print_pos[i] = x = pos+1;
        if (j==pow(2,level)) {
            printf("\n");
            level++;
            x = 1;
            j = 0;
        }
    }
    return 0;
}
代码:


一个非常简单的C++解决方案:在水平方向打印树:

5
  1
    5
  9
    7
    14
代码(Node::print()函数才是关键):

#包括
使用名称空间std;
类树;
类节点{
公众:
节点(int val):_val(val){}
int val(){return_val;}
无效添加(节点*临时)
{
如果(临时->值()>_值)
{
如果(_rchild)
_rchild->add(临时);
其他的
{
_rchild=温度;
}
}
其他的
{
如果(_lchild)
_lchild->添加(临时);
其他的
{
_lchild=温度;
}
}
}
作废打印()
{
对于(int ix=0;ix<_级别;++ix)不能添加(温度);
}
作废打印()
{
if(!\u根)
返回;
_root->print();
}
私人:
节点*_根;
};
int main()
{
树木;
树。添加(5);
添加(9);
树。添加(1);
添加(7);
树。添加(5);
添加(14);
tree.print();
}

创建一个包含节点和边的.dot文件,并使用graphviz进行渲染。看neat@litb:很好。我实际上实现了一个renderlist和一个帧缓冲区,并生成了我自己的BMP!请更新图片:)正是我要找的,thanx很多!不幸的是,似乎是这样。在Google缓存或Internet Archive Wayback机器上找不到它。可能就是这样,我还没有尝试运行它:文本似乎已损坏,代码链接已断开。如果有人能找到代码,请帮忙!指向pastebin的链接可能没有超出范围…找到它,保存它!几年前我把它移植到JS!这个问题要求ASCII。@Norman-是的,但他也要求一个算法,他可以在我列出的帖子上找到。dot很棒,但这里的问题是ASCIIThanks。我正在使用您的解决方案,但有一个小错误。第二个q.push_back(node_depth(nd.n->l,last_lvl+1))应该是q.push_back(node_depth(nd.n->r,last_lvl+1))@sink-不确定你在说什么-它已经计算了右子树的
node_depth
。当你复制它的时候,你打错了吗?这里的工作代码:+1用于递归实现和输出的美观。我尝试将其用于带有字符串值的树。即使在增加宽度变量时,效果也不是很好。此外,固定数量的线路也是不幸的。
        0                                                                                                
    1       2                                                                                            
  3   4   5   6                                                                                          
#include <stdio.h>
#include <math.h>


#define PARENT(i) ((i-1) / 2)
#define NUM_NODES 15
#define LINE_WIDTH 70

int main() {
    int tree[NUM_NODES]={0,1,2,3,4,5,6,7,8,9,1,2,3,4,5};
    int print_pos[NUM_NODES];
    int i, j, k, pos, x=1, level=0;

    print_pos[0] = 0;
    for(i=0,j=1; i<NUM_NODES; i++,j++) {
        pos = print_pos[PARENT(i)] + (i%2?-1:1)*(LINE_WIDTH/(pow(2,level+1))+1);

        for (k=0; k<pos-x; k++) printf("%c",i==0||i%2?' ':'-');
        printf("%d",tree[i]);

        print_pos[i] = x = pos+1;
        if (j==pow(2,level)) {
            printf("\n");
            level++;
            x = 1;
            j = 0;
        }
    }
    return 0;
}
                                   0
                  1-----------------------------------2
          3-----------------4                 5-----------------6
      7---------8       9---------1       2---------3       4---------5
int _print_t(tnode *tree, int is_left, int offset, int depth, char s[20][255])
{
    char b[20];
    int width = 5;

    if (!tree) return 0;

    sprintf(b, "(%03d)", tree->val);

    int left  = _print_t(tree->left,  1, offset,                depth + 1, s);
    int right = _print_t(tree->right, 0, offset + left + width, depth + 1, s);

#ifdef COMPACT
    for (int i = 0; i < width; i++)
        s[depth][offset + left + i] = b[i];

    if (depth && is_left) {

        for (int i = 0; i < width + right; i++)
            s[depth - 1][offset + left + width/2 + i] = '-';

        s[depth - 1][offset + left + width/2] = '.';

    } else if (depth && !is_left) {

        for (int i = 0; i < left + width; i++)
            s[depth - 1][offset - width/2 + i] = '-';

        s[depth - 1][offset + left + width/2] = '.';
    }
#else
    for (int i = 0; i < width; i++)
        s[2 * depth][offset + left + i] = b[i];

    if (depth && is_left) {

        for (int i = 0; i < width + right; i++)
            s[2 * depth - 1][offset + left + width/2 + i] = '-';

        s[2 * depth - 1][offset + left + width/2] = '+';
        s[2 * depth - 1][offset + left + width + right + width/2] = '+';

    } else if (depth && !is_left) {

        for (int i = 0; i < left + width; i++)
            s[2 * depth - 1][offset - width/2 + i] = '-';

        s[2 * depth - 1][offset + left + width/2] = '+';
        s[2 * depth - 1][offset - width/2 - 1] = '+';
    }
#endif

    return left + width + right;
}

void print_t(tnode *tree)
{
    char s[20][255];
    for (int i = 0; i < 20; i++)
        sprintf(s[i], "%80s", " ");

    _print_t(tree, 0, 0, 0, s);

    for (int i = 0; i < 20; i++)
        printf("%s\n", s[i]);
}
                           .----------------------(006)-------.                 
                      .--(001)-------.                   .--(008)--.            
                 .--(-02)       .--(003)-------.       (007)     (009)          
       .-------(-06)          (002)       .--(005)                              
  .--(-08)--.                           (004)                                   
(-09)     (-07)                     
                                                  (006)                         
                           +------------------------+---------+                 
                         (001)                              (008)               
                      +----+---------+                   +----+----+            
                    (-02)          (003)               (007)     (009)          
                 +----+         +----+---------+                                
               (-06)          (002)          (005)                              
       +---------+                        +----+                                
     (-08)                              (004)                                   
  +----+----+                                                                   
(-09)     (-07)                                                       
5
  1
    5
  9
    7
    14
#include<iostream>

using namespace std;

class Tree;

class Node{
public:
    Node(int val): _val(val){}
    int val(){ return _val; }
    void add(Node *temp)
    {
        if (temp->val() > _val)
        {
            if (_rchild)
                _rchild->add(temp);
            else
            {
                _rchild = temp;
            }
        }
        else
        {
            if (_lchild)
                _lchild->add(temp);
            else
            {
                _lchild = temp;
            }
        }
    }
    void print()
    {
        for (int ix = 0; ix < _level; ++ix) cout << ' ';
        cout << _val << endl;
        ++_level;
        if (_lchild)
        {
            _lchild->print();
            --_level;
        }
        if (_rchild)
        {
            _rchild->print();
            --_level;
        }
    }
private:
    int _val;
    Node *_lchild;      
    Node *_rchild;
    static int _level;      
};

int Node::_level = 0;       

class Tree{
public:
    Tree(): _root(0){}  
    void add(int val)
    {
        Node *temp = new Node(val);
        if (!_root)
            _root = temp;
        else
            _root->add(temp);       
    }
    void print()
    {
        if (!_root)
            return;
        _root->print();             
    }
private:
    Node *_root;    
};

int main()
{
    Tree tree;
    tree.add(5);
    tree.add(9);
    tree.add(1);
    tree.add(7);
    tree.add(5);
    tree.add(14);
    tree.print();
}