微信邦

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 18937|回复: 0

教你用代码画一颗树

[复制链接]
发表于 2018-8-6 22:12:01 | 显示全部楼层 |阅读模式
| 导语 一直以来自己都是通过Visio在画流程图和架构图,原来通过写代码的方式也可以画图,这种方式简洁而高效,完美搭配vim,并且可以轻松实现脚本化,于是就入坑了。

教你用代码画一颗树

教你用代码画一颗树

写在前面

优点
自动布局和连线
易于实现脚本化

缺点
无法绘制需要自定义或固定布局的图
下面我们就来画一棵Merkle树吧

代码的分割线

教你用代码画一颗树

教你用代码画一颗树


等等,Merkle树是神马?

Merkle树,也叫哈希树,是一种用做快速归纳和校验大规模数据完整性的树形数据结构。
下图就是《精通比特币》一书中的Merkle树示意图,图中每个叶子节点即一笔交易,两两组合,逐层Hash到根节点。通过Merkle树可以在只知道部分节点的Hash的情况下,就能验证某笔交易是否存在或正确,而无需获取所有交易节点的Hash值。要知道一般这个代价是很大的,以比特币区块为例,目前整个区块链账本大小接近200G。
所以,Merkle树也是SPV(简单的支付认证,即Simple Payment Verification)的基础。
🔻

教你用代码画一颗树

教你用代码画一颗树

Merkle树应用

快速比较大量数据:当两个Merkle树的根哈希值相同时,说明所代表的的数据都相同
快速定位修改:如上图,如果交易K发生改变,那么就会导致HK、HKL、HIJKL、HIJKLMNOP和Merkle Root发生改变。所以,我们想要快速定位,只需要沿着Root => HIJKLMNOP => HIJKL => HKL => HK,就可以定位到交易K发生改变
零知识证明:例如,想要证明一组交易中包含某个交易K,但又不想让对方知道交易K的具体内容,那么就可以构建Merkle树,向对方公布HK、HL、HKL、HIJKL、HIJKLMNOP和Merkle Root,对方就可以确认交易K的存在,但无法知道交易K的具体内容。

开始画图/写代码
🔻
怎样画节点?
最简单的节点

寥寥四行代码就画出了3个节点

  1. <font color="rgb(102, 217, 239)">digraph</font> G1 {    <font color="rgb(102, 217, 239)">A</font>       B       C   }
复制代码


教你用代码画一颗树

教你用代码画一颗树
装饰节点

  1. <div class="quote"><blockquote><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);">digraph G2 {
  2.     //对节点进行全局设置
  3.     node [fontname=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"Microsoft YaHei"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);"> fontsize=15 shape=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"record"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);"> color=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"black"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);"> fillcolor=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"gray90"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);">style=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"filled,bold"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);">];

  4.     HA  [label=<H<SUB>A</SUB>>]
  5.     HK  [label=<H<SUB>K</SUB>> fillcolor=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"forestgreen"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);"> fontcolor=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"white"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);">]                                                                        
  6.     HKL [label=<H<SUB>KL</SUB>> color=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"dodgerblue3"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);"> style=</span><span class="" style="margin: 0px; padding: 0px; max-width: 100%; font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; color: rgb(230, 219, 116); box-sizing: border-box !important; word-wrap: break-word !important;">"filled,bold,dashed"</span><span style="color: rgb(248, 248, 242); font-family: Consolas, Monaco, monospace; font-size: 14px; letter-spacing: 2px; text-align: justify; white-space: pre; background-color: rgb(35, 36, 31);">]
  7. }</span>
复制代码



教你用代码画一颗树

教你用代码画一颗树

节点属性

[td]
属性名
默认值
说明
labelnode name节点显示内容
colorblacknode边框颜色
fontcolorblack字体颜色
fillcolor
背景色
fontnameTimes-Roman字体
fontsize14字体大小
shapeellipse形状:box、ellipse、circle、diamond、
plaintext、point、triangle、invtriangle
style
图形样式: bold、dashed、dotted、filled
image
背景图片地址

怎样画连线?
最简单的连线
通过->很形象的建立了节点间的有向连线

  1. <font size="4"><span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(166, 226, 46);">digraph</span> <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">G3</span> {    <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">A</span>        
  2.     <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">B</span>        
  3.     <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">C</span>        

  4.     <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">A</span> -> <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">C</span>
  5.     <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">B</span> -> <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">C</span>                                                       }</font>
复制代码


教你用代码画一颗树

教你用代码画一颗树

装饰连线

  1. <font size="4">digraph G4 {
  2.     //边全局设置                                             
  3.     edge [style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"bold"</span>];
  4.     A                     
  5.     B                     
  6.     C                     

  7.     A -> C [label=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"A2C"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"green"</span> arrowhead=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"diamond"</span>]
  8.     B -> C [style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"bold,dashed"</span> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> arrowsize=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"2.0"</span>]
  9. }</font>
复制代码


教你用代码画一颗树教你用代码画一颗树

教你用代码画一颗树教你用代码画一颗树

连线属性

[td]
属性名
默认值
说明
label
描述关系
colorblack箭头颜色
fontcolorblack关系文字颜色
dirforward设置方向:forward、back、both、none
arrowheadnormal箭头头部形状:box、crow、diamond、dot、none、normal、vee
arrowtailnone箭头尾部形状
arrowsize1.0箭头大小
style
图形样式: bold、dashed、dotted、filled
仿制Merkle树完整代码
  1. <font size="4">$ cat MerkleTree.dot
  2. digraph MerkleTree {
  3.     rankdir = BT;
  4.     label=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"MerkleTree draw by jasonruan"</span>

  5.     node [fontname=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"Microsoft YaHei"</span> fontsize=15 shape=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"record"</span> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"black"</span> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"gray90"</span>style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold"</span>];
  6.     edge [style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"bold"</span>];

  7.     HA          [label=<H<SUB>A</SUB>>]
  8.     HB          [label=<H<SUB>B</SUB>>]
  9.     HAB         [label=<H<SUB>AB</SUB>>]
  10.     HC          [label=<H<SUB>C</SUB>>]
  11.     HD          [label=<H<SUB>D</SUB>>]
  12.     HCD         [label=<H<SUB>CD</SUB>>]
  13.     HABCD       [label=<H<SUB>ABCD</SUB>>]
  14.     HE          [label=<H<SUB>E</SUB>>]
  15.     HF          [label=<H<SUB>F</SUB>>]
  16.     HEF         [label=<H<SUB>EF</SUB>>]
  17.     HG          [label=<H<SUB>G</SUB>>]
  18.     HH          [label=<H<SUB>H</SUB>>]
  19.     HGH         [label=<H<SUB>GH</SUB>>]
  20.     HEFGH       [label=<H<SUB>EFGH</SUB>>]
  21.     HABCDEFGH   [label=<H<SUB>ABCDEFGH</SUB>> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"white"</span> style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold"</span>]

  22.     HI          [label=<H<SUB>I</SUB>>]
  23.     HJ          [label=<H<SUB>J</SUB>>]
  24.     HIJ         [label=<H<SUB>IJ</SUB>> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"white"</span>]
  25.     HK          [label=<H<SUB>K</SUB>> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"forestgreen"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"white"</span>]
  26.     HL          [label=<H<SUB>L</SUB>> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"white"</span>]
  27.     HKL         [label=<H<SUB>KL</SUB>> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold,dashed"</span>]
  28.     HIJKL       [label=<H<SUB>IJKL</SUB>> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold,dashed"</span>]
  29.     HM          [label=<H<SUB>M</SUB>>]
  30.     HN          [label=<H<SUB>N</SUB>>]
  31.     HMN         [label=<H<SUB>MN</SUB>>]
  32.     HO          [label=<H<SUB>O</SUB>>]
  33.     HP          [label=<H<SUB>P</SUB>>]
  34.     HOP         [label=<H<SUB>OP</SUB>>]
  35.     HMNOP       [label=<H<SUB>MNOP</SUB>> fillcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> fontcolor=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"white"</span>]
  36.     HIJKLMNOP   [label=<H<SUB>IJKLMNOP</SUB>> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold,dashed"</span>]


  37.     {HA,HB}    -> HAB
  38.     {HC,HD}    -> HCD
  39.     {HAB,HCD}   -> HABCD
  40.     {HE,HF}    -> HEF
  41.     {HG,HH}    -> HGH
  42.     {HEF,HGH}   -> HEFGH
  43.     {HABCD,HEFGH} -> HABCDEFGH

  44.     {HI,HJ}    -> HIJ
  45.     {HK,HL}    -> HKL
  46.     {HIJ,HKL}   -> HIJKL
  47.     {HM,HN}    -> HMN
  48.     {HO,HP}    -> HOP
  49.     {HMN,HOP}   -> HMNOP
  50.     {HIJKL,HMNOP} -> HIJKLMNOP

  51.     HABCDEFGHIJKLMNOP [label=<Root<br/><SUB>ABCDEFGHIJKLMNOP</SUB>> color=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"red"</span> style=<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"filled,bold,dashed"</span>]
  52.     {HABCDEFGH,HIJKLMNOP} -> HABCDEFGHIJKLMNOP</font>
复制代码

Merkle树仿制图

教你用代码画一颗树

教你用代码画一颗树

工具安装

最后再来介绍下画图工具和vim插件安装。

软件安装

官网:https://graphviz.  gitlab .io/

当前版本:graphviz-2.40.1.tar.gz

这里采用源码方式安装:

  1. <font size="4">$ wget https://graphviz.gitlab.io/pub/graphviz/stable/SOURCES/graphviz.tar.gz
  2. $ tar -zxf graphviz.tar.gz
  3. $ <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">cd</span> graphviz-2.40.1
  4. $ ./configure --prefix=/home/rzexin/Software/ALL
  5. $ make -j2 && make install</font>
复制代码

vim整合

(1)插件安装

.vimrc新增

  1. <font size="4">Plugin <span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">'wannesm/wmgraphviz.vim'</span></font>
复制代码

执行安装命令

  1. <font size="4">:PluginInstall</font>
复制代码

(2)vim配置

  1. <font size="4"><span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(249, 38, 114);">function</span> HeaderDot()  
  2.     call append (1,<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"digraph G {"</span>)         
  3.     call append (2,<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">""</span>)
  4.     call append (3,<span class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: rgb(230, 219, 116);">"}"</span>)
  5.     normal 3G         
  6. endfunction           
  7. autocmd bufnewfile *.dot call HeaderDot()

  8. nmap <Leader>ln :w<CR>:! dot -Tpng -o %<.png %<CR>:! eog %<.png <CR>
  9. nmap <Leader>ls :w<CR>:! dot -Tsvg -o %<.svg %<CR>:! eog %<.svg <CR></font>
复制代码

配置说明:



打开.dot后缀文件,自动执行HeaderDot函数创建dot文件框架

vim normal模式下执行,ln将自动保存png格式文件并自动预览,同样,使用,ls将保存为svg格式文件并自动预览

%<表示去掉后缀的当前文件名

写在最后

graphviz的功能也确实强大,自己只是初步入门,但感觉这点入门知识也已经大大提升了自己的工作效率。之前通过Visio画图要不断的去调整样式、配色,是件很繁琐的事情,特别是当要修改时,可能要不断调整已有图形的布局,很是费时。现在,通过graphviz一切都自动的帮你完成好了,而且图形还挺美观。自己能不入坑吗:)

end


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

微信邦网联系QQ|Archiver|手机版|小黑屋|鲁公网安备 37082802000167号|微信邦 ( 鲁ICP备19043418号-5 )

GMT+8, 2024-9-17 04:41 , Processed in 0.096927 second(s), 25 queries .

Powered by Discuz! X3.4

© 2001-2013 Wxuse Inc. | Style by ytl QQ:1400069288

快速回复 返回顶部 返回列表