您现在的位置是:网站首页> 编程资料编程资料
Go语言制作svg格式树形图的示例代码_Golang_
2023-05-26
452人已围观
简介 Go语言制作svg格式树形图的示例代码_Golang_
最近一直在刷二叉树题目,但在要验证结果时,通常用中序遍历、层序遍历查看结果,验证起来没有画图来得直观,所有想到自己动手制作二叉树的树形图。 直接开干,先从svg入手:

什么是SVG
SVG定义
SVG是可伸缩矢量图形 (Scalable Vector Graphics),于2003年1月14日成为 W3C 推荐标准。
SVG 用来定义用于网络的基于矢量的图形
SVG 使用 XML 格式定义图形
SVG 是万维网联盟的标准
SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体
SVG优点
- SVG 可被非常多的工具读取和修改(比如记事本)
- SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
- SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失
- SVG 图像可在任何的分辨率下被高质量地打印
- SVG 可在图像质量不下降的情况下被放大
- SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)
- SVG 可以与 JavaScript 技术一起运行
- SVG 是开放的标准
- SVG 文件是纯粹的 XML
预定义元素
- 矩形
- 圆形
- 椭圆
- 直线
- 文字
- 路径
- 折线
- 多边形

制作二叉树的树形图,就使用圆形、直线、文字三种即可:
圆形
cx和cy属性定义圆点的x和y坐标;r属性定义圆的半径
如果省略cx和cy,圆的中心会被设置为(0, 0)
直线
x1,y2 属性定义线条的起始端点坐标
x2,y2 属性定义线条的结束端点坐标
文字
x,y 属性定义文字左对齐显示时的起始坐标(居中对齐则是文字中间点)
fill 属性定义文字的颜色

结点SVG格式
根结点
由
1
子树结点
比根结点多出
2
叶结点
与子树结点相同,为区别显示把
3
结点坐标
坐标的确定
结点坐标确定,把二叉树还原成满二叉树,结点位置标记为:
[ [0,0], [1,0], [1,1], [2,0], [2,1], [2,2], [2,3], [3,0]......],再用循环计算出各点坐标。
连线的夹角
实际上不用考虑连线夹角,只要计算出连线始终两端点的坐标即可:

结点文本
以字符串形式保存好属性变量的特征关键词,用于遍历二叉树时替换成实际数据:
func XmlNode(M, N, X, Y int, Data string, Color ...string) string { var cColor, tColor string R := 30 Node := `DATA ` if len(Color) == 0 { cColor, tColor = "orange", "red" } else if len(Color) == 1 { cColor, tColor = Color[0], "red" } else { cColor, tColor = Color[0], Color[1] } Node = strings.Replace(Node, "M", strconv.Itoa(M), 1) Node = strings.Replace(Node, "N", strconv.Itoa(N), 1) Node = strings.Replace(Node, "X", strconv.Itoa(X), 2) Node = strings.Replace(Node, "Y", strconv.Itoa(Y), 2) Node = strings.Replace(Node, "RC", strconv.Itoa(R), 1) Node = strings.Replace(Node, "DATA", Data, 1) Node = strings.Replace(Node, "COLOR", cColor, 1) Node = strings.Replace(Node, "TextColor", tColor, 1) Node = strings.Replace(Node, "", "\n", -1) Node = strings.Replace(Node, "", "\t", -1) Node = strings.Replace(Node, "\n\t\t", " ", -1) return Node } 二叉树转SVG
遍历二叉树对应的满二叉树,读出数据域并计算坐标,转成svg格式:
格式转换
func (bt *biTree) Xml4Tree() string { var Xml, Node string Head := "" Line := ` ` Link := `Hann's CSDN Homepage ` List := bt.LevelNullwith() Levels := len(List) for i := Levels - 1; i >= 0; i-- { negative := -1 TmpXml := "" for j := 0; j < Pow2(i); j++ { t := Pow2(Levels - i - 1) x, y := 50*(2*t*j+t), 120*i+50 if List[i][j] != nil { fillColor := "orange" if i == Levels-1 || i > 0 && i < Levels-1 && List[i+1][j*2] == nil && List[i+1][j*2+1] == nil { fillColor = "lightgreen" } TmpStr := "" switch List[i][j].(type) { case int: TmpStr = strconv.Itoa(List[i][j].(int)) case float64: TmpStr = strconv.FormatFloat(List[i][j].(float64), 'g', -1, 64) case string: TmpStr = List[i][j].(string) default: TmpStr = "Error Type" } Xml = XmlNode(i, j, x, y, TmpStr, fillColor) } if i > 0 { line1 := strings.Replace(Line, "X1", strconv.Itoa(x), 1) line1 = strings.Replace(line1, "Y1", strconv.Itoa(y-30), 1) negative *= -1 x0, y0 := 21, 21 x += 50*negative*(2*t*j%2+t) - negative*x0 line1 = strings.Replace(line1, "X2", strconv.Itoa(x), 1) line1 = strings.Replace(line1, "Y2", strconv.Itoa(y-120+y0), 1) Xml = strings.Replace(Xml, " ", line1, 1) } if List[i][j] != nil { TmpXml += Xml } } Node = TmpXml + Node } Xml = strings.Replace(Head, "CONTENT", Node, 1) Xml = strings.Replace(Xml, "Width", strconv.Itoa(Pow2(Levels)*50), 1) Xml = strings.Replace(Xml, "Height", strconv.Itoa(Levels*120), 1) Xml = strings.Replace(Xml, " ", Link, 1) return Xml }写入文件、调取浏览
//...... for index, text := range texts { svgFile := "./biTree0" + strconv.Itoa(index+1) + ".svg" file, err1 = os.Create(svgFile) if err1 != nil { panic(err1) } _, err1 = io.WriteString(file, text) if err1 != nil { panic(err1) } file.Close() exec.Command("cmd", "/c", "start", svgFile).Start() //Linux 代码: //exec.Command("xdg-open", svgFile).Start() //Mac 代码: //exec.Command("open", svgFile).Start() } //......全部源代码
package main import ( "fmt" "io" "os" "os/exec" "strconv" "strings" ) type btNode struct { Data interface{} Lchild *btNode Rchild *btNode } type biTree struct { Root *btNode } func Build(data interface{}) *biTree { var list []interface{} if data == nil { return &biTree{} } switch data.(type) { case []interface{}: list = append(list, data.([]interface{})...) default: list = append(list, data) } if len(list) == 0 { return &biTree{} } node := &btNode{Data: list[0]} list = list[1:] Queue := []*btNode{node} for len(list) > 0 { if len(Queue) == 0 { //panic("Given array can not build binary tree.") return &biTree{Root: node} } cur := Queue[0] val := list[0] Queue = Queue[1:] if val != nil { cur.Lchild = &btNode{Data: val} if cur.Lchild != nil { Queue = append(Queue, cur.Lchild) } } list = list[1:] if len(list) > 0 { val := list[0] if val != nil { cur.Rchild = &btNode{Data: val} if cur.Rchild != nil { Queue = append(Queue, cur.Rchild) } } list = list[1:] } } return &biTree{Root: node} } func (bt *biTree) AppendNode(data interface{}) { root := bt.Root if root == nil { bt.Root = &btNode{Data: data} return } Queue := []*btNode{root} for len(Queue) > 0 { cur := Queue[0] Queue = Queue[1:] if cur.Lchild != nil { Queue = append(Queue, cur.Lchild) } else { cur.Lchild = &btNode
相关内容
点击排行
本栏推荐
