TikZ-PGF – How to Make Two Nodes Grow Up While the Rest Grow Down in TikZ Tree

tikz-pgftikz-trees

This is my first use of Tikz. I have a Tikz Tree using this code

\documentclass{standalone}
\usepackage{tikz-qtree}
\begin{document}
\tikzset{every tree node/.style={minimum width=2em,draw,circle},
            blank/.style={draw=none}, 
            edge from parent/.style=
            {draw,edge from parent path={(\tikzparentnode) -- (\tikzchildnode)}},
            level distance=1.5cm}
\begin{tikzpicture}
\Tree
    [.c
        \edge[]; [.a 
        ]
        \edge[]; [.b
        ]
        \edge[]; [.d 
            \edge[]; {d1}
            \edge[]; {d2}
        ]
        \edge[]; [.e
            \edge[]; {e1}
            \edge[]; {e2}
        ]
    ]
\end{tikzpicture}
\end{document}

This gives me;

This tree

What I would like is to have 'a' above-left of 'c' and 'b' above-right, while the rest of the tree grows down as normal.

I've been poking around for Tikz examples, but haven't found one that looks as I would like. All advice welcome. Thanks.

=== Second iteration

\documentclass{standalone}
\usepackage{tikz-qtree}
\begin{document}
    \tikzset{every tree node/.style={minimum width=2em,draw,circle},
                blank/.style={draw=none}, 
                edge from parent/.style=
                {draw,edge from parent path={(\tikzparentnode) -- (\tikzchildnode)}},
                level distance=1.5cm}
    \begin{tikzpicture}
    \Tree
        [.c
            \edge[]; \node(first) [draw, align=left, above=28mm, left=14mm] {\textbf{a}};
            \edge[]; \node(second) [draw, align=right, above=28mm, right=14mm] {\textbf{b}};
            \edge[]; [.d 
                \edge[]; {d1}
                \edge[]; {d2}
            ]
            \edge[]; [.e
                \edge[]; {e1}
                \edge[]; {e2}
            ]
        ]
    \end{tikzpicture}
\end{document}

Give me almost what I want, but 'a' and 'b' are squished to the left.

squished left

Best Answer

Update: Here is a more general solution.

Here is a solution using forest, which is somewhat more flexible than qtree. You can add manual adjustments to the individual nodes by using before drawing tree. You can add or subtract to the x or y coordinates by using y±=<length>,x±=<length>, or set the coordinates with y=<coordinate>,x=<coordinate>.

I was unclear if you also wanted the d and e subtrees to be shifted so they are symmetric with respect to the c node.

enter image description here

\documentclass{article}

\usepackage{forest}

\begin{document}

\begin{forest}
for tree={draw,circle,minimum width=2em,anchor=center}
[c
    [a,before drawing tree={y=1cm,x=-1cm}]
    [b,before drawing tree={y=1cm,x=1cm}]
    [d
        [d1]
        [d2]]
    [e
        [e1]
        [e2]]]
\end{forest}

\end{document}

For a more flexible solution, in case the a and b nodes have nonempty subtrees, you can create two empty children for the c node and set their grow directions. But before computing the position of the empty children, use before computing xy={l=0,s=0} to place the empty nodes at the root. The syntax if level=1{<do this>}{<else do this>} can be placed in the main for tree.

enter image description here

\documentclass{article}

\usepackage{forest}

\begin{document}

\begin{forest}
for tree={minimum width=2.5em, anchor=center, circle,
    if level=1{no edge, before computing xy={l=0,s=0}}{draw}}
[c
[, for tree={grow'=north}
    [a[a1][a2]]
    [b[b1][b2]]]
[, 
    [d
        [d1]
        [d2]]
    [e
        [e1]
        [e2]]]]
\end{forest}

\end{document}