#### 1.画出如下svg矢量图
<div width="100%" style="overflow-x: auto;">
<svg width="385pt" height="332pt"
viewBox="0.00 0.00 385.00 332.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 328)">
<title>G</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-328 381,-328 381,4 -4,4"/>
<!-- 1 -->
<g id="node1" class="node"><title>1</title>
<ellipse fill="none" stroke="black" cx="203" cy="-306" rx="18" ry="18"/>
<text text-anchor="middle" x="203" y="-302.3" font-family="Times New Roman,serif" font-size="14.00">1</text>
</g>
<!-- 2 -->
<g id="node2" class="node"><title>2</title>
<ellipse fill="none" stroke="black" cx="122" cy="-234" rx="18" ry="18"/>
<text text-anchor="middle" x="122" y="-230.3" font-family="Times New Roman,serif" font-size="14.00">0</text>
</g>
<!-- 1->2 -->
<g id="edge1" class="edge"><title>1->2</title>
<path fill="none" stroke="black" d="M189.624,-293.441C176.886,-282.432 157.521,-265.697 142.773,-252.952"/>
<polygon fill="black" stroke="black" points="135.127,-246.344 145.635,-249.478 138.91,-249.613 142.693,-252.883 142.693,-252.883 142.693,-252.883 138.91,-249.613 139.75,-256.287 135.127,-246.344 135.127,-246.344"/>
</g>
<!-- _1 -->
<!-- 1->_1 -->
<!-- 3 -->
<g id="node14" class="node"><title>3</title>
<ellipse fill="none" stroke="black" cx="307" cy="-234" rx="18" ry="18"/>
<text text-anchor="middle" x="307" y="-230.3" font-family="Times New Roman,serif" font-size="14.00">2</text>
</g>
<!-- 1->3 -->
<g id="edge13" class="edge"><title>1->3</title>
<path fill="none" stroke="black" d="M217.461,-295.267C234.672,-283.683 263.631,-264.191 283.943,-250.519"/>
<polygon fill="black" stroke="black" points="292.327,-244.876 286.544,-254.193 288.179,-247.668 284.031,-250.46 284.031,-250.46 284.031,-250.46 288.179,-247.668 281.518,-246.727 292.327,-244.876 292.327,-244.876"/>
</g>
<!-- 4 -->
<g id="node3" class="node"><title>4</title>
<ellipse fill="none" stroke="black" cx="70" cy="-162" rx="18" ry="18"/>
<text text-anchor="middle" x="70" y="-158.3" font-family="Times New Roman,serif" font-size="14.00">4</text>
</g>
<!-- 2->4 -->
<g id="edge2" class="edge"><title>2->4</title>
<path fill="none" stroke="black" d="M111.726,-219.17C104.462,-209.391 94.5736,-196.08 86.2464,-184.87"/>
<polygon fill="black" stroke="black" points="80.2522,-176.801 89.8278,-182.145 83.2338,-180.815 86.2155,-184.828 86.2155,-184.828 86.2155,-184.828 83.2338,-180.815 82.6031,-187.512 80.2522,-176.801 80.2522,-176.801"/>
</g>
<!-- _2 -->
<!-- 2->_2 -->
<!-- 5 -->
<g id="node10" class="node"><title>5</title>
<ellipse fill="none" stroke="black" cx="174" cy="-162" rx="18" ry="18"/>
<text text-anchor="middle" x="174" y="-158.3" font-family="Times New Roman,serif" font-size="14.00">0</text>
</g>
<!-- 2->5 -->
<g id="edge9" class="edge"><title>2->5</title>
<path fill="none" stroke="black" d="M132.274,-219.17C139.538,-209.391 149.426,-196.08 157.754,-184.87"/>
<polygon fill="black" stroke="black" points="163.748,-176.801 161.397,-187.512 160.766,-180.815 157.785,-184.828 157.785,-184.828 157.785,-184.828 160.766,-180.815 154.172,-182.145 163.748,-176.801 163.748,-176.801"/>
</g>
<!-- 8 -->
<g id="node4" class="node"><title>8</title>
<ellipse fill="none" stroke="black" cx="44" cy="-90" rx="18" ry="18"/>
<text text-anchor="middle" x="44" y="-86.3" font-family="Times New Roman,serif" font-size="14.00">6</text>
</g>
<!-- 4->8 -->
<g id="edge3" class="edge"><title>4->8</title>
<path fill="none" stroke="black" d="M63.9697,-144.765C60.8851,-136.46 57.0571,-126.154 53.5805,-116.794"/>
<polygon fill="black" stroke="black" points="49.9976,-107.147 57.6979,-114.955 51.7385,-111.834 53.4795,-116.522 53.4795,-116.522 53.4795,-116.522 51.7385,-111.834 49.2611,-118.088 49.9976,-107.147 49.9976,-107.147"/>
</g>
<!-- _4 -->
<!-- 4->_4 -->
<!-- 9 -->
<g id="node8" class="node"><title>9</title>
<ellipse fill="none" stroke="black" cx="96" cy="-90" rx="18" ry="18"/>
<text text-anchor="middle" x="96" y="-86.3" font-family="Times New Roman,serif" font-size="14.00">7</text>
</g>
<!-- 4->9 -->
<g id="edge7" class="edge"><title>4->9</title>
<path fill="none" stroke="black" d="M76.0303,-144.765C79.1149,-136.46 82.9429,-126.154 86.4195,-116.794"/>
<polygon fill="black" stroke="black" points="90.0024,-107.147 90.7389,-118.088 88.2615,-111.834 86.5205,-116.522 86.5205,-116.522 86.5205,-116.522 88.2615,-111.834 82.3021,-114.955 90.0024,-107.147 90.0024,-107.147"/>
</g>
<!-- 14 -->
<g id="node5" class="node"><title>14</title>
<ellipse fill="none" stroke="black" cx="18" cy="-18" rx="18" ry="18"/>
<text text-anchor="middle" x="18" y="-14.3" font-family="Times New Roman,serif" font-size="14.00">3</text>
</g>
<!-- 8->14 -->
<g id="edge4" class="edge"><title>8->14</title>
<path fill="none" stroke="black" d="M37.9697,-72.7646C34.8851,-64.4598 31.0571,-54.1539 27.5805,-44.7936"/>
<polygon fill="black" stroke="black" points="23.9976,-35.1473 31.6979,-42.9547 25.7385,-39.8344 27.4795,-44.5216 27.4795,-44.5216 27.4795,-44.5216 25.7385,-39.8344 23.2611,-46.0884 23.9976,-35.1473 23.9976,-35.1473"/>
</g>
<!-- _8 -->
<!-- 8->_8 -->
<!-- 10 -->
<g id="node11" class="node"><title>10</title>
<ellipse fill="none" stroke="black" cx="148" cy="-90" rx="18" ry="18"/>
<text text-anchor="middle" x="148" y="-86.3" font-family="Times New Roman,serif" font-size="14.00">1</text>
</g>
<!-- 5->10 -->
<g id="edge10" class="edge"><title>5->10</title>
<path fill="none" stroke="black" d="M167.97,-144.765C164.885,-136.46 161.057,-126.154 157.58,-116.794"/>
<polygon fill="black" stroke="black" points="153.998,-107.147 161.698,-114.955 155.739,-111.834 157.479,-116.522 157.479,-116.522 157.479,-116.522 155.739,-111.834 153.261,-118.088 153.998,-107.147 153.998,-107.147"/>
</g>
<!-- _5 -->
<!-- 5->_5 -->
<!-- 6 -->
<g id="node15" class="node"><title>6</title>
<ellipse fill="none" stroke="black" cx="255" cy="-162" rx="18" ry="18"/>
<text text-anchor="middle" x="255" y="-158.3" font-family="Times New Roman,serif" font-size="14.00">4</text>
</g>
<!-- 3->6 -->
<g id="edge14" class="edge"><title>3->6</title>
<path fill="none" stroke="black" d="M296.726,-219.17C289.462,-209.391 279.574,-196.08 271.246,-184.87"/>
<polygon fill="black" stroke="black" points="265.252,-176.801 274.828,-182.145 268.234,-180.815 271.215,-184.828 271.215,-184.828 271.215,-184.828 268.234,-180.815 267.603,-187.512 265.252,-176.801 265.252,-176.801"/>
</g>
<!-- _3 -->
<!-- 3->_3 -->
<!-- 7 -->
<g id="node20" class="node"><title>7</title>
<ellipse fill="none" stroke="black" cx="359" cy="-162" rx="18" ry="18"/>
<text text-anchor="middle" x="359" y="-158.3" font-family="Times New Roman,serif" font-size="14.00">5</text>
</g>
<!-- 3->7 -->
<g id="edge19" class="edge"><title>3->7</title>
<path fill="none" stroke="black" d="M317.274,-219.17C324.538,-209.391 334.426,-196.08 342.754,-184.87"/>
<polygon fill="black" stroke="black" points="348.748,-176.801 346.397,-187.512 345.766,-180.815 342.785,-184.828 342.785,-184.828 342.785,-184.828 345.766,-180.815 339.172,-182.145 348.748,-176.801 348.748,-176.801"/>
</g>
<!-- 11 -->
<g id="node16" class="node"><title>11</title>
<ellipse fill="none" stroke="black" cx="229" cy="-90" rx="18" ry="18"/>
<text text-anchor="middle" x="229" y="-86.3" font-family="Times New Roman,serif" font-size="14.00">6</text>
</g>
<!-- 6->11 -->
<g id="edge15" class="edge"><title>6->11</title>
<path fill="none" stroke="black" d="M248.97,-144.765C245.885,-136.46 242.057,-126.154 238.58,-116.794"/>
<polygon fill="black" stroke="black" points="234.998,-107.147 242.698,-114.955 236.739,-111.834 238.479,-116.522 238.479,-116.522 238.479,-116.522 236.739,-111.834 234.261,-118.088 234.998,-107.147 234.998,-107.147"/>
</g>
<!-- _6 -->
<!-- 6->_6 -->
<!-- 12 -->
<g id="node18" class="node"><title>12</title>
<ellipse fill="none" stroke="black" cx="281" cy="-90" rx="18" ry="18"/>
<text text-anchor="middle" x="281" y="-86.3" font-family="Times New Roman,serif" font-size="14.00">5</text>
</g>
<!-- 6->12 -->
<g id="edge17" class="edge"><title>6->12</title>
<path fill="none" stroke="black" d="M261.03,-144.765C264.115,-136.46 267.943,-126.154 271.42,-116.794"/>
<polygon fill="black" stroke="black" points="275.002,-107.147 275.739,-118.088 273.261,-111.834 271.521,-116.522 271.521,-116.522 271.521,-116.522 273.261,-111.834 267.302,-114.955 275.002,-107.147 275.002,-107.147"/>
</g>
<!-- 13 -->
<g id="node21" class="node"><title>13</title>
<ellipse fill="none" stroke="black" cx="333" cy="-90" rx="18" ry="18"/>
<text text-anchor="middle" x="333" y="-86.3" font-family="Times New Roman,serif" font-size="14.00">4</text>
</g>
<!-- 7->13 -->
<g id="edge20" class="edge"><title>7->13</title>
<path fill="none" stroke="black" d="M352.97,-144.765C349.885,-136.46 346.057,-126.154 342.58,-116.794"/>
<polygon fill="black" stroke="black" points="338.998,-107.147 346.698,-114.955 340.739,-111.834 342.479,-116.522 342.479,-116.522 342.479,-116.522 340.739,-111.834 338.261,-118.088 338.998,-107.147 338.998,-107.147"/>
</g>
<!-- _7 -->
<!-- 7->_7 -->
</g>
</svg>
</div>
#### 2.放出源码
```golang
package main
import (
"fmt"
"io"
"os"
"os/exec"
"strconv"
"strings"
)
/* 参考:https://blog.nanpuyue.com/2019/054.html */
func main() {
if len(os.Args) != 2 {
fmt.Printf("usage: %s \"1,0,2,4,0,4,5,6,7,1,null,6,5,4,nil,3\"\n", os.Args[0])
return
}
const maxInt = 1<<31 - 1
var arr []int
for _, v := range strings.Split(os.Args[1], ",") {
str := strings.TrimSpace(v)
if str == "nil" || str == "null" {
arr = append(arr, maxInt) // 表示nil节点
} else if tmp, err := strconv.Atoi(str); err == nil {
arr = append(arr, tmp)
} else {
fmt.Println(err)
return
}
}
lArr := len(arr)
if lArr <= 0 {
return
}
var (
i, num = 0, 2
head = &TreeNode{Val: arr[0], Num: 1}
queue = []*TreeNode{head}
)
// 根据输入还原二叉树
for len(queue) != 0 {
node := queue[0]
queue = queue[1:]
if i++; i < lArr && arr[i] != maxInt {
node.Left = &TreeNode{Val: arr[i], Num: num}
queue = append(queue, node.Left)
num++
}
if i++; i < lArr && arr[i] != maxInt {
node.Right = &TreeNode{Val: arr[i], Num: num}
queue = append(queue, node.Right)
num++
}
}
printTree(head)
}
type TreeNode struct {
Val int // 节点值
Num int // 节点序号,因为节点值可能重复
IsWrite bool // true表示已经将该节点序号和label写入文件
Left *TreeNode
Right *TreeNode
}
func printTree(root *TreeNode) error {
if root == nil {
return nil
}
const dotFile = "tree.dot"
fw, err := os.Create(dotFile)
if err != nil {
return err
}
fw.WriteString(`digraph G {
graph [nodesep=0.1]
node [shape=circle]
edge [arrowhead=vee]
`)
if root.Left != nil || root.Right != nil {
root.IsWrite = true
fmt.Fprintf(fw, " %d [group=%d,label=\"%d\"]\n", root.Num, root.Num, root.Val)
}
printNode(fw, root)
fw.WriteString("}")
fw.Close()
return exec.Command("dot", dotFile, "-Tsvg", "-o"+dotFile+".svg").Run()
}
func printNode(fw io.Writer, root *TreeNode) {
if !root.IsWrite {
fmt.Fprintf(fw, " %d [label=\"%d\"]\n", root.Num, root.Val)
}
target, distance := 0, 0
if root.Left != nil {
leftMax := root
leftDistance := 1
for leftMax.Right != nil {
leftMax = leftMax.Right
leftDistance++
}
// 找到root节点的root.left往下最右边的节点
target = leftMax.Num
distance = leftDistance
if root.Left.Left != nil || root.Left.Right != nil {
root.Left.IsWrite = true // 生成该节点值
fmt.Fprintf(fw, " %d [group=%d,label=\"%d\"]\n", root.Left.Num, root.Left.Num, root.Left.Val)
}
// 生成root指向root.left的关系
fmt.Fprintf(fw, " %d -> %d\n", root.Num, root.Left.Num)
printNode(fw, root.Left)
}
if root.Left != nil || root.Right != nil {
// 弄一个中间节点,隐藏起来,主要是让布局更美观
fmt.Fprintf(fw, " _%d [group=%d,label=\"\",width=0,style=invis]\n", root.Num, root.Num)
fmt.Fprintf(fw, " %d -> _%d [style=invis]\n", root.Num, root.Num)
}
if root.Right != nil {
rightMin := root.Right
rightDistance := 1
for rightMin.Left != nil {
rightMin = rightMin.Left
rightDistance++
}
// 找到root节点的root.Right往下最左边的节点
if rightDistance <= distance {
target = rightMin.Num
distance = rightDistance
}
if root.Right.Left != nil || root.Right.Right != nil {
root.Right.IsWrite = true // 生成该节点值
fmt.Fprintf(fw, " %d [group=%d,label=\"%d\"]\n", root.Right.Num, root.Right.Num, root.Right.Val)
}
// 生成root指向root.Right的关系
fmt.Fprintf(fw, " %d -> %d\n", root.Num, root.Right.Num)
printNode(fw, root.Right)
}
// 一个节点对应的占位节点应该与该节点的左子树的最大节点和右子树的最小节点中距离较近的那一个处于同一层
if distance > 1 && target != 0 {
fmt.Fprintf(fw, " {rank=same;_%d;%d}\n", root.Num, target)
}
}
```
#### 3. 总结
1. 原理的话可以看【[别人的解释](https://blog.nanpuyue.com/2019/054.html)】
2. 首先需要安装【[graphviz](https://graphviz.gitlab.io/_pages/Download/Download_windows.html)】
3. 然后编写还原二叉树的代码,生成【graphviz】的脚本,然后用dot命令产生svg矢量图
4. 在markdow编辑器中使用SVG可以用如下操作
```javascript
<div width="100%" style="overflow-x: auto;">
<svg width="140" height="170">
<title>SVG Sample</title>
<desc>This is a sample to use SVG in markdown on the website cnblogs.</desc>
<circle cx="70" cy="95" r="50" style="stroke: black; fill: none;"/>
</svg>
</div>
```
有疑问加站长微信联系(非本文作者)