<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">% Binary tree drawing in LaTeX using the PiCTeX macros.
%
% Edward M. Reingold (reingold@cs.uiuc.edu)
% Nachum Dershowitz (nachum@cs.uiuc.edu)
%
\typeout{Binary Tree Macros.  Released 18 Jan 1991; modified 2 Apr 1992.}
%
% These macros are in the public domain.  You may use them and copy them at
% will, provided you retain the authorship information.
%
%
% USAGE: \tree[optional root symbol]{left subtree}{right subtree}
%
% For example,
%
%     \tree[X]
%        {\setdots\tree[Z]
%           {\setsolid\tree[Y]{a}{}}
%           {\setsolid\tree{c}{d}}}
%        {\tree
%           {\tree{}{f}}
%           {\tree{g}{h}}}
%
% The root symbol and leaves can be anything you can construct in LaTeX
% or PiCTeX.  The trees constructed can be used in any context in LaTeX
% or PiCTeX.  That is, you can have, say, tables of trees of equations.
%
%
% WARNING: Do not use the tilde (~) as the first character in any subtree!
%
%
% PARAMETERS: Feel free to change the following tree drawing parameters;
%             these parameters can be reset even in the middle of a tree.
%
\newdimen\subtreesep \subtreesep=10pt   % Distance between nonempty subtrees
\newdimen\levelsep   \levelsep=30pt     % Distance between successive levels
\def\nodesymbol{$\bullet$}              % Default symbol for an internal node
%                          Tree edges connecting to the default node symbol
%                          will go to it's center.  Other tree edges will be
%                          chopped off at a node's bounding box.
%
%
% Here's an example that changes the parameters in the middle of the tree:
%
%     \subtreesep=15pt\levelsep=40pt
%     \tree[\fbox{\subtreesep=5pt\levelsep=13pt\tree[o]{a}{a}}]
%        {b}{b}
%
%
% You can get triangular subtrees by using \triangle which has the format 
%
%      \triangle[optional apex label]{width}{height}
%
% For example,
%
%      \tree{\triangle[A]{2\subtreesep}{2\levelsep}}
%           {\tree{\triangle{\subtreesep}{\levelsep}}
%                 {\tree{\fbox{}}
%                       {\fbox{}}}}
%
%
% Don't fiddle with the stuff that follows; it's fairly delicate.
%
% Working variables
%
\catcode`@=11%
\newdimen\halfsubtreesep % half the subtree separation
%
\newdimen\leftwd         % width of left subtree
\newdimen\rightwd        % width of right subtree
%
\newcount\rootbullet     % flag indicating if root is the default bullet
\newdimen\rootwd         % width of root
\newdimen\rootht         % height of root
\newdimen\rootdp         % depth of root
%
\newcount\leftrootbullet % flag indicating if left root is the default bullet
\newdimen\leftrootht     % height of left subtree's root
\newdimen\leftrootwd     % width of left subtree's root
\newcount\rightrootbullet% flag indicating if right root is the default bullet
\newdimen\rightrootht    % height of right subtree's root
\newdimen\rightrootwd    % width of right subtree's root
%
\newdimen\@@root           % distance of root midpointfrom left edge of tree
\newdimen\leftroot       % distance of root midpoint of left subtree
                         % from left edge of tree
\newdimen\rightroot      % distance of root midpoint of right subtree
                         % from left edge of tree
%
\newcount\leafnode       % flag indicating if subtree just placed is a leaf
%
\newdimen\rootxpos       % x-cooordinate of the root midpoint
\newdimen\leftrootpos    % position of the root of the left subtree
\newdimen\rightrootpos   % position of the root of the right subtree
\newdimen\leftpos        % position of the NE corner of the left subtree
\newdimen\rightpos       % position of the NW corner of the right subtree
%
\newbox\rootnode         % the root node, as placed
\newbox\leftsubtree      % the left subtree, as placed
\newbox\rightsubtree     % the right subtree, as placed
%
\newdimen\xa             % (\xa,\ya) = coordinates of the point on the root
\newdimen\ya             % node at which to connect the line to a child
\newdimen\xb             % (\xb,\yb) = coordinates of the point on the child
\newdimen\yb             % at which to connect the line to the parent
%
\let\ifnextchar=\@ifnextchar%
\def\tree{\ignorespaces%
\def\tree{\ifnextchar[{\treey}{\treex}}%
%
\setdimensionmode%
\setlinear%
%
\@ifnextchar[{\treey}{\treex}%
}%
%
\long\def\treex#1#2{\itree{#1}{#2}{\nodesymbol}}  % use default node symbol
\long\def\treey[#1]#2#3{\itree{#2}{#3}{#1}}       % use specified node symbol
%
\long\def\itree#1#2#3{\ignorespaces  % #1=left, #2=right, #3=root
%
\halfsubtreesep=\subtreesep     % Do this calculation for each node so its...
\divide\halfsubtreesep by 2     % ...value can vary throughout the tree
%
\ignorespaces%
%
% Recursively draw nonempty left subtree
%
\ifx ~#1~\ignorespaces%
 \else%
   \leafnode=1  % Assume left subtree is a leaf
   \setbox\leftsubtree=\hbox{#1}\ignorespaces
   \leftwd=\wd\leftsubtree%
   \leftroot=\@@root%
   \leftrootbullet=\rootbullet%
   \leftrootht=\rootht%
   \leftrootwd=\rootwd%
   \ifnum \leafnode=1%
      \leftroot=\leftwd%
      \divide\leftroot by 2%
      \leftrootbullet=0%
      \leftrootht=\ht\leftsubtree%
      \advance\leftrootht by \dp\leftsubtree%
      \leftrootwd=\leftwd%
   \fi%
\fi%
%
% Recursively draw nonempty right subtree
%
\ifx ~#2~\ignorespaces%
 \else%
   \leafnode=1  % Assume right subtree is a leaf
   \setbox\rightsubtree=\hbox{#2}\ignorespaces%
   \rightwd=\wd\rightsubtree%
   \rightroot=\@@root%
   \rightrootbullet=\rootbullet%
   \rightrootht=\rootht%
   \rightrootwd=\rootwd%
   \ifnum \leafnode=1%
      \rightroot=\rightwd%
      \divide\rightroot by 2%
      \rightrootbullet=0%
      \rightrootht=\ht\rightsubtree%
      \advance\rightrootht by \dp\rightsubtree%
      \rightrootwd=\rightwd%
   \fi%
\fi%
%
% In the case of empty subtrees, give artificial values for those empty
% trees so that the later calculations are done properly.
%
\ifx ~#1#2~\ignorespaces        %  Both subtrees empty
   \rightroot=0pt%
   \leftroot=-\halfsubtreesep%
   \leftwd=-\halfsubtreesep%
\else\ifx ~#1~\ignorespaces     %  Left subtree empty, right subtree not empty
   \leftroot=\rightroot%
   \advance\leftroot by -\subtreesep%
   \leftwd=-\subtreesep%
\else\ifx ~#2~\ignorespaces     %  Right subtree empty, left subtree not empty
   \rightroot=\leftroot%
   \advance\rightroot by -\leftwd%
\fi\fi\fi%
%
% With the subtrees done, now do the root node
%
\setbox\rootnode=\hbox{\setcoordinatemode #3}\ignorespaces%
\global\rootwd=\wd\rootnode%
\global\rootht=\ht\rootnode%
\global\advance\rootht by \dp\rootnode%
\ifx \nodesymbol#3\ignorespaces%
    \global\rootbullet=1%
  \else\ignorespaces%
    \global\rootbullet=0%
\fi%
%
% Find distance of the root midpoint from left edge of the tree
%
\global\@@root=\leftroot%
\global\advance\@@root by \rightroot%
\global\advance\@@root by \leftwd%
\global\advance\@@root by \subtreesep%
\ifdim \@@root&lt;\rootwd \global\@@root=\rootwd \fi%
\global\divide\@@root by 2%
%
% Indicate this root and all its ancestors are not a leaves
%
\global\leafnode=0%
%
% Find positions of the root and those of the roots of the subtrees
%
\leftrootpos=\leftroot%
\advance\leftrootpos by -\leftwd%
\advance\leftrootpos by -\halfsubtreesep%
%
\rightrootpos=\rightroot%
\advance\rightrootpos by \halfsubtreesep%
%
\rootxpos=\leftrootpos%
\advance\rootxpos by \rightrootpos%
\divide\rootxpos by 2%
%
\leftpos=0pt%
\advance\leftpos by \leftrootht%
\divide\leftpos by 2%
%
\rightpos=0pt%
\advance\rightpos by \rightrootht%
\divide\rightpos by 2%
%
% Now the root is a box of width \rootwd and total height \rootht, centered
% at (\rootxpos,\levelsep); the root of the left subtree is a box of
% width \leftrootwd and total height \leftrootht, centered at
% (\leftrootpos,0); the root of the right subtree is a box of width
% \rightrootwd and total height \rightrootht, centered at (\rightrootpos,0).
%
%
\beginpicture
%
\put {\box\rootnode} at {\rootxpos} {\levelsep}     % Draw the root
%
\ifx ~#1~\else                                      % Draw the left subtree
   \put {\box\leftsubtree} [rt] at {-\halfsubtreesep} {\leftpos}
   \xa=\rootxpos%
   \ya=\levelsep%
   \ifnum\rootbullet=0%
      \chop{\rootxpos}{\levelsep}{-\rootwd}{\rootht}{\leftrootpos}{0}%
           {\xa}{\ya}%
   \fi%
   \xb=\leftrootpos%
   \yb=0pt%
   \ifnum\leftrootbullet=0%
      \chop{\leftrootpos}{0}{\leftrootwd}{-\leftrootht}{\rootxpos}{\levelsep}%
           {\xb}{\yb}%
   \fi%
   \plot {\xa} {\ya}  {\xb} {\yb} /%
\fi%
%
\ifx ~#2~\else                                      % Draw the right subtree
   \put {\box\rightsubtree} [lt] at {\halfsubtreesep} {\rightpos}
   \xa=\rootxpos%
   \ya=\levelsep%
   \ifnum\rootbullet=0%
      \chop{\rootxpos}{\levelsep}{\rootwd}{\rootht}{\rightrootpos}{0}%
           {\xa}{\ya}%
   \fi%
   \xb=\rightrootpos%
   \yb=0pt%
   \ifnum\rightrootbullet=0%
      \chop{\rightrootpos}{0}{-\rightrootwd}{-\rightrootht}{\rootxpos}%
           {\levelsep}{\xb}{\yb}%
   \fi
   \plot {\xa} {\ya}  {\xb} {\yb} /%
\fi%
%
% Draw the bottom of the triangle, when appropriate.
%
\ifx#1. \ifx#2. \plot {\leftrootpos} {0pt} {\rightrootpos} {0pt} / \fi\fi%
%
\endpicture%
}%
%
\long\def\triangle{\ifnextchar[{\triangley}{\trianglex}}%
\long\def\trianglex#1#2{\itriangle{#1}{#2}{}}       % use empty apex symbol
\long\def\triangley[#1]#2#3{\itriangle{#2}{#3}{#1}} % use specified apex symbol
\long\def\itriangle#1#2#3{%  A triangle #1 wide and #2 high, #3 at apex
   \subtreesep=#1%
   \levelsep=#2%
   \tree[#3]{.}{.}%
}%
%
\newcount\@@x%  Scratch counters used in the computations of \chop
\newcount\@@y%  to find the location on the border of a node's bounding
\newcount\@@a%  box at which to attach a line aimed at a target point
\newcount\@@b%  from the center of the box.
\newcount\@@c%
\newcount\@@d%  It would be better to do all these calculation in dimen's
\newcount\@@e%  instead of counters, but so many dimen's are used above
\newcount\@@f%  that to do so would make running out of dimen's very probable.
\newcount\@@g%  
\newcount\@@h%  Forgive us for not explaining the following computations;
\newcount\@@l%  they're based on elementary analytical geometry.
%
\def\chop#1#2#3#4#5#6#7#8{\ignorespaces%
                          % (#1,#2) = coordinates of center of bounding box
                          % #3 x #4 = width x height of bounding box
                          % (#5,#6) = coordinates of target point
                          % (#7,#8) = coordinates of computed intersection
                          %           point
%
\@@a=#1\divide \@@a by 10000%  Scale down to prevent arithmetic overflow.
\@@b=#2\divide \@@b by 10000%
\@@c=#3\divide \@@c by 10000%
\@@d=#4\divide \@@d by 10000%
\@@e=#5\divide \@@e by 10000%
\@@f=#6\divide \@@f by 10000%
%
\@@l=-\@@f\advance\@@l by \@@b%
%%
\@@y=-\@@d%
\divide \@@y by 2%
\advance\@@y by \@@b%
%%
\@@g=\@@c%
\divide \@@g by 2%
\advance\@@g by \@@a%
%%
\@@x=-\@@a%
\advance\@@x by \@@e%
\multiply\@@x by \@@d%
\divide\@@x by \@@l%
\divide\@@x by 2%
\advance \@@x by \@@a%
%%
\count255=-\@@a%
\advance\count255 by \@@e%
\multiply\count255 by 2%
\@@h=-\@@c%
\multiply \@@h by \@@l%
\divide \@@h by \count255%
\advance \@@h by \@@b%
%
\ifnum #5&gt;#1%
   \ifnum\@@x&gt;\@@g\else\@@g=\@@x\@@h=\@@y\fi%
\else%
   \ifnum\@@x&lt;\@@g\else\@@g=\@@x\@@h=\@@y\fi%
\fi%
\multiply\@@g by 10000%  Scale back up
\multiply\@@h by 10000%
\global#7=\@@g sp%
\global#8=\@@h sp%
}%
\catcode`@=12%
</pre></body></html>