0%

使用Graphviz画一颗二叉树

概述

发现有一个工具叫Graphviz,类似于markdown,它使用dot标记语言来编写,能将其转换为图形。

准备工作

(非必需,文末有精简版下载地址)
下载并安装Graphviz
安装目录/bin添加到环境变量

步骤

编写脚本

1
2
3
4
5
6
7
8
9
digraph binTree{
node[shape=circle,fontsize=30,color=blue];
root->a[side=left];
root->b[side=right];
a->c[side=left];
a->d[side=right];
b->e[side=left];
e->f[side=right];
}}

直接使用dot -Tpng -o tree.png tree.dot转换,结果为:

左右节点不明显。

使用优化模板转换

binarytree.gvpr内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// from Emden Gansner
// https://mailman.research.att.com/pipermail/graphviz-interest/2010q2/007101.html
// requires GraphViz 2.28.0 (fails with 2.26.3 at least)
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", &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 > 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", &x, &y);
$.pos = sprintf("0,%f", y);
}
if ($.outdegree == 0) return;
sscanf ($.pos, "%f,%f", &x, &y);
wd = tw[$];
e1 = fstout($);
n = e1.head;
sscanf (n.pos, "%f,%f", &z, &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", &z, &y);
n.pos = sprintf("%f,%f", x + sp/2.0 + xoff[n], y);
}
}

保存到文件后,执行:

1
dot tree.dot | gvpr -c -f binarytree.gvpr | neato -n -Tpng -o tree.png

转换结果为:

精简版打包下载地址

链接: https://pan.baidu.com/s/1DV4PVU09lt-RHeqoD1-qRA 提取码: 2333

包含执行以上命令所需的必要文件(体积由47M缩减为10M不到),以及本文中的例子
解压后,执行convert.bat即可将tree.dot转化为图片
PS:如果需要使用其他功能,请下载完整版

参考

如何画一棵漂亮的二叉树