home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / lang / c / 16658 < prev    next >
Encoding:
Text File  |  1992-11-17  |  4.9 KB  |  215 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!europa.asd.contel.com!emory!sol.ctr.columbia.edu!ira.uka.de!math.fu-berlin.de!news.netmbx.de!Germany.EU.net!olymp!uran!hermann
  3. From: hermann@uran.informatik.uni-bonn.de (Hermann Stamm)
  4. Subject: Re: Printing out trees
  5. Message-ID: <1992Nov17.094008.17078@olymp.informatik.uni-bonn.de>
  6. Keywords: Printing of trees, PostScript-Output
  7. Sender: usenet@olymp.informatik.uni-bonn.de
  8. Reply-To: hermann@uran.informatik.uni-bonn.de (Hermann Stamm)
  9. Organization: Praktische Informatik III
  10. Date: Tue, 17 Nov 1992 09:40:08 GMT
  11. Lines: 202
  12.  
  13. /*
  14.  
  15. Hello all!
  16.  
  17. In article <gezTJc_00VQsAo9Vpl@andrew.cmu.edu> you write:
  18. |> Does anyone have code for printing out arbitrary binary trees,
  19. |> ie, not necessarily full, can have 0, 1 or 2 children?
  20. |> 
  21. |> Any sort of method or strategy would be nice, doesn't even
  22. |> really have to be code.  I'm just stumped for a nice, efficient
  23. |> way to do it--everything I've tried has been ugly.
  24. |> 
  25. |> -rick
  26.  
  27. The below function calc is very short and does a good job
  28. for the above problem. It is called initially "calc(v,0,0)"
  29. and generates coordinates for the placement of all nodes of
  30. the tree with root v (in the components x and y).
  31. The range of the coordinates are 0<=x<=number_of_nodes-1
  32. and 0<=y<=depth(v)-1.
  33. It does simply the following:
  34.  
  35. The y-coordinate of node w is simply its level in the tree
  36. (root has level 0).
  37.  
  38. The root v gets x-coordinate "number of nodes in left tree",
  39. such that the left subtree will be placed with x-coordinates
  40. in the range 0..v->x-1 and the right subtree in the range
  41. v->x+1..number_of_nodes-1.
  42.  
  43. The below demo-program generates a random-tree, determines
  44. the coordinates for the layout by the use of calc, and then
  45. generates a PostScript-file with the embedding as output to
  46. stdout.
  47.  
  48. To use it just do
  49.  
  50.   demo | lpr -PLASER
  51.  
  52. to print it on a laser-printer with name LASER or
  53.  
  54.   demo >x.ps ; gs x.ps    (or "demo | gs -")
  55.  
  56. for viewing it using GhostScript.
  57.  
  58.  
  59. Hope this helps,
  60.  
  61.    Hermann.
  62.  
  63.  
  64. P.S.:  Try "demo 1000 | lpr" ; its fine!
  65.  
  66. */
  67.  
  68. #include <stdio.h>
  69. #include <stdlib.h>
  70. #include <time.h>
  71.  
  72. typedef struct node
  73.   {
  74.   struct node  *left;
  75.   struct node  *right;
  76.   int        x;
  77.   int        y;
  78.   }
  79. * node;
  80.  
  81. /*----------------------------------------------------------------------------*/
  82.  
  83. int calc(node v, int height, int offset)
  84.   {
  85.   int count_left;
  86.  
  87.   if (v==NULL)
  88.     return(0);
  89.   else
  90.     {
  91.     v->y = height++;
  92.     count_left = calc(v->left,height,offset);
  93.     
  94.     return( count_left + 1 + calc(v->right,height,(v->x=count_left+offset)+1) );
  95.     }
  96.   }
  97.  
  98. /*----------------------------------------------------------------------------*/
  99.  
  100. int MAX(int a, int b)
  101.   {
  102.   return(a>b ? a : b);
  103.   }
  104.  
  105. int depth(node v)
  106.   {
  107.   if (v==NULL)
  108.     return(0);
  109.   else
  110.     return( 1 + MAX(depth(v->left),depth(v->right)) );
  111.   }
  112.  
  113. node random_tree(int n)
  114.   {
  115.   node v;
  116.   int  nodes_left;
  117.  
  118.   if (n==0)
  119.     return(NULL);
  120.   else
  121.     {
  122.     nodes_left    = random() % n;
  123.     v        = malloc(sizeof(*v));
  124.     v->left    = random_tree(nodes_left);
  125.     v->right    = random_tree(n-nodes_left-1);
  126.     return(v);
  127.     }
  128.   }
  129.  
  130. /*----------------------------------------------------------------------------*/
  131.  
  132. #define ps_translate(x,y)    printf("%f %f translate\n",x,y)
  133. #define ps_rotate(w)        printf("%f rotate\n",w)
  134. #define ps_scale(sx,sy)        printf("%f %f scale\n",sx,sy)
  135. #define ps_setlinewidth(l)    printf("%f setlinewidth\n",l)
  136. #define ps_showpage()        printf("showpage\n")
  137.  
  138. #define ps_rectangle(x,y,dx,dy)    printf("%f %f moveto %f 0 rlineto 0 %f rlineto ",x,y,dx,dy); \
  139.                                 printf("%f 0 rlineto closepath\n",-dx);                      \
  140.                                 printf("gsave 0.9 setgray fill grestore stroke\n");
  141.  
  142. #define ps_circle(x,y,r)    printf("%f %f %f 0 360 arc fill\n",x,y,r)
  143. #define ps_line(x1,y1,x2,y2)    printf("%f %f moveto %f %f lineto stroke\n",x1,y1,x2,y2)
  144.  
  145. #define ps_node(v)        ps_circle((float) v->x,(float) v->y,0.2)
  146. #define ps_edge(v,w)        ps_line((float) v->x,(float) v->y,(float) w->x,(float) w->y)
  147.  
  148. void ps_TREE(node v)
  149.   {
  150.   node son;
  151.  
  152.   if (v!=NULL)
  153.     {
  154.     if ((son=v->left)!=NULL)
  155.       {
  156.       ps_edge(v,son);
  157.       ps_TREE(son);
  158.       }
  159.     if ((son=v->right)!=NULL)
  160.       {
  161.       ps_edge(v,son);
  162.       ps_TREE(son);
  163.       }
  164.     ps_node(v);
  165.     }
  166.   }
  167.  
  168. void ps_tree(node v, int width, int height)
  169.   {
  170.   if (v!=NULL)
  171.     {
  172.     ps_rectangle(20.0,30.0,536.0,732.0);
  173.     ps_translate(38.0,46.0);
  174.     ps_rotate(-90.0);
  175.     ps_scale(-700.0/(width-1),500.0/(height-1));
  176.     ps_setlinewidth(0.02);
  177.     ps_TREE(v);
  178.     ps_showpage();
  179.     }
  180.   }
  181.  
  182. /*----------------------------------------------------------------------------*/
  183.  
  184. void show_tree(node v)
  185.   {
  186.   if (v!=NULL)
  187.     {
  188.     show_tree(v->left);
  189.     printf("%d %d\n",v->x,v->y);
  190.     show_tree(v->right);
  191.     }
  192.   }
  193.  
  194. /*----------------------------------------------------------------------------*/
  195.  
  196. int main(int argc, char *argv[])
  197.   {
  198.   node T;
  199.   int  size;
  200.  
  201.   srandom(time(NULL));
  202.  
  203.   T = random_tree( (argc<2) ? 10+(random()%100) : atoi(argv[1]) );
  204.  
  205.   ps_tree(T,calc(T,0,0),depth(T));
  206.  
  207. /*
  208.   show_tree(T);
  209. */
  210.  
  211.   return(0);
  212.   }
  213.  
  214.  
  215.