浅谈OI中的画图利器——Graphviz入门

zhylj

2018-08-14 16:06:56

Personal

## 浅谈$\rm OI$中的画图利器——$\rm Graphviz$入门 --- ### 那是什么? 在写题解/博客时,我们有可能遇到需要画有向/无向图、流程图等等,$\rm Windows$自带的画图又不能满足我们的需求,我们就可以用到$\rm Graphviz$来画图。 $\rm DOT$:是一个纯文本图像描述语言。 $\rm Graphviz$:是一个开源的软件,其中包含$\rm DOT$ ### 如何下载&安装? 进入[http://www.graphviz.org/download/](http://www.graphviz.org/download/) $\rm Ubuntu$用户下载$\rm Ubuntu\ packages$ $\rm Windows$用户下载$\rm Stable\ 2.38\ Windows\ install\ packages \rightarrow \text{graphviz-2.38.zip}$ $\rm Windows$用户下载之后需要配置环境变量,以下以$\rm Windows\ 10$为例, 首先,点击“此电脑”->“属性” ![Skip 1](https://cdn.luogu.com.cn/upload/pic/28568.png) 弹出来的窗口左侧“高级系统设置”->“环境变量(N)...” ![Skip 2](https://cdn.luogu.com.cn/upload/pic/28570.png) 上方“xxx的用户变量”->“$\rm Path$”->“编辑(E)...” ![Skip 3](https://cdn.luogu.com.cn/upload/pic/28569.png) 接下来分两种情况: 第一种:在弹出窗口内“变量值”后加上“你的解压后的目录\release\bin;”(注意分号) ![Skip 4(1)](https://cdn.luogu.com.cn/upload/pic/28572.png) 第二种:在弹出窗口内点击“新建”,然后输入“你的解压后的目录\release\bin”然后确定。 ![Skip 4(2)](https://cdn.luogu.com.cn/upload/pic/28571.png) 然后,一路点确定下来即可。 如何验证是否完成? 打开命令行(win+R,输入cmd然后回车/shift+右键->在此处打开命令窗口/Linux 终端)输入 ``` dot -version ``` ![](https://cdn.luogu.com.cn/upload/pic/28573.png) ![](https://cdn.luogu.com.cn/upload/pic/28577.png) 如果没有报错,那么你设置完成 ### 如何使用? (以下操作在$\rm Ubuntu\ 16.04\ LTS$中进行,其他操作系统没有太大差别。 建立一个文件$\rm xxx.dot$。 ![](https://cdn.luogu.com.cn/upload/pic/28579.png) 使用纯文本编辑器(如记事本/notepad++/vim/gedit等)编辑。 我们有一个例子来测试它: ``` digraph example{ node[shape=box] a->b; b->c; } ``` (这里,我们使用vim做示范,其它编辑器同理) ![](https://cdn.luogu.com.cn/upload/pic/28583.png) 在同样目录下,打开命令行(或使用```cd```命令),输入 ``` dot test.dot -T png -o test.png ``` 则会在目录下生成一个文件test.png ![](https://cdn.luogu.com.cn/upload/pic/28586.png) ### 怎么写$\rm DOT$?(DOT入门) #### 无向图 无向图的格式如下: ``` graph 名字(随意){ 无向图的内容 } ``` 无向图使用```a--b```的形式来描述边,$\rm dot$会帮你自动调整每个节点的位置。 例如: ``` graph example{ a--b; a--c; b--c; } ``` 效果: ![](https://cdn.luogu.com.cn/upload/pic/28587.png) 如果边数太多,我们还可以使用```a->{b;c;d;e}```的方式来描述很多条边,比如: ``` graph example{ a--{b;c;d;e;f;g;h;i}; } ``` 效果: ![](https://cdn.luogu.com.cn/upload/pic/28588.png) 如果你还需要不同的形状/颜色,你可以参考以下的例子: ``` graph example{ a--b[color=red;label="233"]; a--c[label="2333"]; b--{d;e}; b[shape=box]; } ``` 效果: ![](https://cdn.luogu.com.cn/upload/pic/28589.png) 即边、点后面可以加```[color=xxx]```表示颜色 ```[label="xxx"]```表示边权 ```[shape=xxx]```表示形状 常用的形状(点)有: ```box,oval,circle,point,egg,triangle,square,record```等,可以到网上去找,这里不一一枚举。 还有一点,若所有的边或点都需要设置,可以使用 ``` edge[xxx] node[xxx] ``` 的方式,比如: ``` graph example{ edge[color=red]; node[shape=box]; a--b; b--c; } ``` 效果: ![](https://cdn.luogu.com.cn/upload/pic/28590.png) #### 有向图 有向图的格式和无向图基本一样: ``` digraph 名字(随意){ 图 } ``` 其中边使用```a->b```描述,比如: ``` digraph example{ node[shape=circle]; root[shape=box]; root->{b;e}; b->{c;d}; } ``` 效果: ![](https://cdn.luogu.com.cn/upload/pic/28592.png) #### 进阶&实例 如何指定边射出的方向? 我们通过具体例子来说明: ``` digraph example{ a0:w->b0;//其中w意思是west,支持w,e,n,s,sw,se,nw,ne a1:e->b1; a2:n->b2; a3:s->b3; a4:nw->b4; a5:ne->b5; a6:sw->b6; a7:se->b7; } ``` ![](https://cdn.luogu.com.cn/upload/pic/28622.png) 如何让修改图片的朝向? 我们把上面的例子做些修改,添加一句```rankdir = LR;``` ``` digraph example{ rankdir = LR; a0:w->b0;//其中w意思是west,支持w,e,n,s,sw,se,nw,ne a1:e->b1; a2:n->b2; a3:s->b3; a4:nw->b4; a5:ne->b5; a6:sw->b6; a7:se->b7; } ``` 效果: ![](https://cdn.luogu.com.cn/upload/pic/28623.png) 想要”结构体“的效果? 我们以一个链表的例子来理解: ``` digraph example{ rankdir = LR; //让图片横过来 node[shape = record]//record形状是专门用来做类似”结构体“的东西的 a[label = "{A|}"];//每个的'|'都是一列 b[label = "{B|}"]; c[label = "{C|}"]; d[label = "{D|NULL}"]; a->b:w; b->c:w; c->d:w; } ``` 效果: ![](https://cdn.luogu.com.cn/upload/pic/28617.png) 我们通过几个例子来熟悉```record``` ``` digraph example{ a[shape = record; label = "A|B|C|D"]; } ``` 效果: ![](https://cdn.luogu.com.cn/upload/pic/28624.png) ``` digraph example{ a[shape = record; label = "{A|B|C|D}"]; } ``` 效果: ![](https://cdn.luogu.com.cn/upload/pic/28625.png) (注意:```rankdir = LR;```也会影响方向) --- ### 后记 $\rm Graphviz$的功能还有很多,网上也有许多详细的教程,这边只选取一些常用功能进行介绍,再加上本人的水平还很低,所以出错是难免的,希望大家谅解。