5
$\begingroup$

A binary tree is one that distinguishes left child from right child. However, in TreePlot you cannot specify which child is left, which is right, so the output is not a binary-looking tree. For example, what I want is

enter image description here

But the output using the following

TreePlot[{1 -> 2, 1 -> 6, 2 -> 3, 2 -> 4, 6 -> 7, 4 -> 5}, Top, 1, VertexLabeling -> True, DirectedEdges -> True]

is

enter image description here

Anyone can help with plotting a binary tree in Mathematica? Thank you!

| improve this question | | | | |
$\endgroup$
  • $\begingroup$ If you're willing to do it in a completely brute force way, add in some extra children and surround your command with FullForm[ ]: FullForm[TreePlot[{1 -> 2, 1 -> 6, 2 -> 3, 2 -> 4, 6 -> 7, 6 -> "A", 4 -> "B", 4 -> 5}, Top, 1, VertexLabeling -> True, DirectedEdges -> True]]. Then copy the resulting code and edit out the offending pieces. (There's gotta be a better way.) $\endgroup$ – JimB Oct 12 '16 at 3:49
8
$\begingroup$

One possibility is to somehow represent missing left and right nodes, but not to draw edges and vertices for those nodes. Something like this (not extensively tested):

maybeP = Except[nothing]|nothing
binaryTreeNodeP = {Except[nothing], maybeP, maybeP}

childOrEmptyNode[value:Except[nothing], nothing, side:(left|right)] := "empty" <> ToString[value] <> ToString[side]
childOrEmptyNode[Except[nothing], child:Except[Nothing], (left|right)] := child

binaryTreeNodeEdges[{v:Except[nothing], l:maybeP, r:maybeP}] := { v -> childOrEmptyNode[v, l, left], v -> childOrEmptyNode[v, r, right]}
makeBinaryTree[nodes:{binaryTreeNodeP..}] := Flatten[Map[binaryTreeNodeEdges, nodes]]

removeEmptyEdges = ( If[!StringMatchQ[ToString[#2[[2]]], "empty"~~__], {Darker[ Red], Arrowheads[{{Medium, 0.5}}], Arrow[#1]}]& )
removeEmptyVertices = ( If[!StringMatchQ[ToString[#2], "empty"~~__], {Background -> LightYellow, Inset[Framed[#2], #1]}]& )

Usage is simple:

nodes = {{1, 2, 6}, {2, 3, 4}, {6, 7, nothing}, {4, nothing, 5}}
TreePlot[makeBinaryTree[nodes], Top, 1, VertexRenderingFunction -> removeEmptyVertices, EdgeRenderingFunction -> removeEmptyEdges]

enter image description here

| improve this answer | | | | |
$\endgroup$
5
$\begingroup$

Update: An alternative approach to add invisible nodes and edges:

TreeGraph[{1 -> 2, 1 -> 6, 2 -> 3, 2 -> 4, 6 -> 7, 
  Property[6->"7", EdgeShapeFunction -> None],
  Property[4->"5", EdgeShapeFunction -> None], 4 -> 5}, 
 VertexShapeFunction -> {_ -> "Square", "5" -> None, "7" -> None}, 
 VertexLabels -> {_ -> Placed["Name", Center], "5" -> None, "7" -> None}, 
 VertexSize -> .2, VertexStyle -> Orange]

Mathematica graphics

Original post:

(Not to detract from Ivica M.'s excellent answer), you can also use TreeGraph and use the option Properties to specify whether a node is a left child or right child:

options = Sequence[VertexLabels -> Placed["Name", Center], 
   VertexShapeFunction -> "Square", VertexSize -> .2,  VertexStyle -> Orange];

tg = TreeGraph[{1 -> 2, 1 -> 6, 2 -> 3, 2 -> 4, 6 -> 7, 4 -> 5}, 
  options, Properties -> {5 -> {"side" -> Right}, 7 -> {"side" -> Left}}]

And post-proces tg to adjust the coordinates of left-child and right-child nodes:

Fold[SetProperty[{##},  VertexCoordinates -> .25 {PropertyValue[{##}, 
         "side"] /. {Right -> 1, Left -> -1}, 0} + 
     PropertyValue[{##}, VertexCoordinates]] &, tg, 
 Select[VertexList[tg], PropertyValue[{tg, #}, "side"] =!= $Failed &]]

Mathematica graphics

| improve this answer | | | | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.