The node name is what lets GraphViz track individual nodes, so they have to be named uniquely.
You are, however, free to use duplicate labels. The labels is what will be shown in the end result, and labels for nodes are by default set to the node name.
Set the label together with the node name when creating:
tree.add_node(1, label=2)
tree.add_node(2, label=3)
tree.add_node(3, label=1)
tree.add_node(4, label=7)
tree.add_node(5, label=3)
tree.add_node(6, label=9)
tree.add_node(7, label=2)
Note that internally, everything is converted to strings here.
This results in:
You'll need to refactor your code to generate unique ids for your unique nodes, then use those ids to create your edges. Here I just traverse your tree with a stack with parent ids:
def drawTree(self, tree, f):
id = 0
nodes = [(None, self)] # queue with nodes to process
while nodes:
parent, node = nodes.pop(0)
tree.add_node(id, label=node.data, color='goldenrod2', style='filled')
if parent is not None:
tree.add_edge(parent, id, color='sienna', style='filled')
if node.left is not None:
nodes.append((id, node.left))
else:
none_id = '{}_left_none'.format(id)
tree.add_node(none_id, label='', color='goldenrod1', shape='box', style='filled')
tree.add_edge(id, none_id, color='sienna', style='filled')
if node.right is not None:
nodes.append((id, node.right))
else:
none_id = '{}_right_none'.format(id)
tree.add_node(none_id, label='', color='goldenrod1', shape='box', style='filled')
tree.add_edge(id, none_id, color='sienna', style='filled')
id += 1
tree.write(f)
img = pgv.AGraph(f)
img.layout(program='dot')
img.draw(f.split('.')[0] + '.pdf')
img.close()
which gives:
To straighten out the edges between nodes with equal values you need to experiment with adding weights to the edges:
def drawTree(self, tree, f):
id = 0
nodes = [(None, self)] # queue with nodes to process
while nodes:
parent, node = nodes.pop(0)
tree.add_node(id, label=node.data, color='goldenrod2', style='filled')
if parent is not None:
weight = 1
if tree.get_node(parent).attr['label'] == str(node.data):
# same value, increase weight of edge to straighten it.
weight = 10
tree.add_edge(parent, id, color='sienna', style='filled', weight=weight)
if node.left is not None:
nodes.append((id, node.left))
else:
none_id = '{}_left_none'.format(id)
tree.add_node(none_id, label='', color='goldenrod1', shape='box', style='filled')
tree.add_edge(id, none_id, color='sienna', style='filled')
if node.right is not None:
nodes.append((id, node.right))
else:
none_id = '{}_right_none'.format(id)
tree.add_node(none_id, label='', color='goldenrod1', shape='box', style='filled')
tree.add_edge(id, none_id, color='sienna', style='filled')
id += 1
tree.write(f)
img = pgv.AGraph(f)
img.layout(prog='dot')
img.draw(f.split('.')[0] + '.png')
img.close()
which results in:
You can tweak the exact weights.