Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You could follow the usual approach of adding invisible nodes and invisible edges, and playing with edge weight etc. as proposed on the <a href="http://www.graphviz.org/content/FaqBalanceTree" rel="nofollow noreferrer">graphviz FAQ about balanced trees</a>. In some <a href="https://stackoverflow.com/q/3105923/63733">simple cases</a>, this is enough.</p> <p>But there is a better solution: Graphviz comes with a tool called <strong>gvpr</strong> (<em>graph pattern scanning and processing language</em>) which allows to</p> <blockquote> <p>copy input graphs to its output, possibly transforming their structure and attributes, creating new graphs, or printing arbitrary information</p> </blockquote> <p>And since <a href="https://mailman.research.att.com/pipermail/graphviz-interest/2010q2/007101.html" rel="nofollow noreferrer">Emden R. Gansner did all the work already by creating a script which does layout nicely binary trees</a>, heres how to to that (all credit goes to ERG):</p> <p>Save the following gvpr script into a file called <code>tree.gv</code> :</p> <pre><code>BEGIN { double tw[node_t]; // width of tree rooted at node double nw[node_t]; // width of node double xoff[node_t]; // x offset of root from left side of its tree double sp = 36; // extra space between left and right subtrees double wd, w, w1, w2; double x, y, z; edge_t e1, e2; node_t n; } BEG_G { $.bb = ""; $tvtype=TV_postfwd; // visit root after all children visited } N { sscanf ($.width, "%f", &amp;w); w *= 72; // convert inches to points nw[$] = w; if ($.outdegree == 0) { tw[$] = w; xoff[$] = w/2.0; } else if ($.outdegree == 1) { e1 = fstout($); w1 = tw[e1.head]; tw[$] = w1 + (sp+w)/2.0; if (e1.side == "left") xoff[$] = tw[$] - w/2.0; else xoff[$] = w/2.0; } else { e1 = fstout($); w1 = tw[e1.head]; e2 = nxtout(e1); w2 = tw[e2.head]; wd = w1 + w2 + sp; if (w &gt; wd) wd = w; tw[$] = wd; xoff[$] = w1 + sp/2.0; } } BEG_G { $tvtype=TV_fwd; // visit root first, then children } N { if ($.indegree == 0) { sscanf ($.pos, "%f,%f", &amp;x, &amp;y); $.pos = sprintf("0,%f", y); } if ($.outdegree == 0) return; sscanf ($.pos, "%f,%f", &amp;x, &amp;y); wd = tw[$]; e1 = fstout($); n = e1.head; sscanf (n.pos, "%f,%f", &amp;z, &amp;y); if ($.outdegree == 1) { if (e1.side == "left") n.pos = sprintf("%f,%f", x - tw[n] - sp/2.0 + xoff[n], y); else n.pos = sprintf("%f,%f", x + sp/2.0 + xoff[n], y); } else { n.pos = sprintf("%f,%f", x - tw[n] - sp/2.0 + xoff[n], y); e2 = nxtout(e1); n = e2.head; sscanf (n.pos, "%f,%f", &amp;z, &amp;y); n.pos = sprintf("%f,%f", x + sp/2.0 + xoff[n], y); } } </code></pre> <p>Assuming your dot file containing the graph is called <code>binarytree.gv</code>, you may execute the following line:</p> <pre><code>dot binarytree.gv | gvpr -c -ftree.gv | neato -n -Tpng -o binarytree.png </code></pre> <p>The result is:</p> <p><img src="https://i.stack.imgur.com/st6rl.png" alt="Binary tree nicely layouted with graphiv and a gvpr script thanks to Emden R. Gansner"></p> <p>By switching around a line or two in the script, you'll even get to have the single child nodes go to the left instead of the right side.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload