Go语言制作svg格式树形图的示例代码

目录
  • 什么是SVG
    • SVG定义
    • SVG优点
    • 预定义元素
    • 圆形 <circle>
    • 直线 <line>
    • 文字 <text>
  • 结点SVG格式
    • 根结点
    • 子树结点
    • 叶结点
  • 结点坐标
  • 结点文本
  • 二叉树转SVG
  • 全部源代码

最近一直在刷二叉树题目,但在要验证结果时,通常用中序遍历、层序遍历查看结果,验证起来没有画图来得直观,所有想到自己动手制作二叉树的树形图。 直接开干,先从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

预定义元素

  • 矩形 <rect>
  • 圆形 <circle>
  • 椭圆 <ellipse>
  • 直线 <line>
  • 文字 <text>
  • 路径 <path>
  • 折线 <polyline>
  • 多边形 <polygon>

制作二叉树的树形图,就使用圆形、直线、文字三种即可:

圆形 <circle>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <circle cx="150" cy="50" r="30" stroke="black" stroke-width="2" fill="red"/>
</svg>

cx和cy属性定义圆点的x和y坐标;r属性定义圆的半径

如果省略cx和cy,圆的中心会被设置为(0, 0)

直线 <line>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <line x1="50" y1="50" x2="200" y2="200" style="stroke:red;stroke-width:2"/>
</svg>

x1,y2 属性定义线条的起始端点坐标

x2,y2 属性定义线条的结束端点坐标

文字 <text>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <text x="30" y="150" fill="red">Welcome to Hann's HomePage</text>
</svg>

x,y 属性定义文字左对齐显示时的起始坐标(居中对齐则是文字中间点)

fill 属性定义文字的颜色

结点SVG格式

根结点

由<circle>和<text>组成,存放结点的数据域

    <g id="0,0">
    <circle cx="400" cy="50" r="30" stroke="black" stroke-width="2" fill="orange" />
    <text x="400" y="50" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">1</text>
    </g>

子树结点

比根结点多出<line>元素,用来表示父结点左或右指针的指向

    <g id="1,0">
    <circle cx="200" cy="170" r="30" stroke="black" stroke-width="2" fill="orange" />
    <text x="200" y="170" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">2</text>
    <line x1="200" y1="140" x2="379" y2="71" style="stroke:black;stroke-width:2"/>
    </g>

叶结点

与子树结点相同,为区别显示把<circle>填充色改为greenlight

    <g id="1,1">
    <circle cx="600" cy="170" r="30" stroke="black" stroke-width="2" fill="lightgreen" />
    <text x="600" y="170" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">3</text>
    <line x1="600" y1="140" x2="421" y2="71" style="stroke:black;stroke-width:2"/>
    </g>

结点坐标

坐标的确定

结点坐标确定,把二叉树还原成满二叉树,结点位置标记为:

[ [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 := `<Tab><g id="M,N">
    <circle cx="X" cy="Y" r="RC" stroke="black" stroke-width="2" fill="COLOR" />
    <text x="X" y="Y" fill="TextColor" font-size="20" text-anchor="middle"
        dominant-baseline="middle">DATA</text>
    <ROOT/>
    </g><CrLf>`
    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, "<CrLf>", "\n", -1)
    Node = strings.Replace(Node, "<Tab>", "\t", -1)
    Node = strings.Replace(Node, "\n\t\t", " ", -1)
    return Node
}

二叉树转SVG

遍历二叉树对应的满二叉树,读出数据域并计算坐标,转成svg格式:

格式转换

func (bt *biTree) Xml4Tree() string {
    var Xml, Node string
    Head := "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/" +
        "1999/xlink\" version=\"1.1\" width=\"Width\" height=\"Height\">\nCONTENT</svg>"
    Line := `<line x1="X1" y1="Y1" x2="X2" y2="Y2" style="stroke:black;stroke-width:2"/>`
    Link := `<a xlink:href="https://blog.csdn.net/boysoft2002" target="_blank">
    <text x="5" y="20" fill="blue">Hann's CSDN Homepage</text></a>`
    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, "<ROOT/>", 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, "<ROOT/>", 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{Data: data}
			return
		}
		if cur.Rchild != nil {
			Queue = append(Queue, cur.Rchild)
		} else {
			cur.Rchild = &btNode{Data: data}
			break
		}
	}
}

func Copy(bt *biTree) *biTree {
	root := bt.Root
	if root == nil {
		return &biTree{}
	}
	node := &btNode{Data: root.Data}
	Queue1, Queue2 := []*btNode{root}, []*btNode{node}
	for len(Queue1) > 0 {
		p1, p2 := Queue1[0], Queue2[0]
		Queue1, Queue2 = Queue1[1:], Queue2[1:]
		if p1.Lchild != nil {
			Node := &btNode{Data: p1.Lchild.Data}
			p2.Lchild = Node
			Queue1 = append(Queue1, p1.Lchild)
			Queue2 = append(Queue2, Node)
		}
		if p1.Rchild != nil {
			Node := &btNode{Data: p1.Rchild.Data}
			p2.Rchild = Node
			Queue1 = append(Queue1, p1.Rchild)
			Queue2 = append(Queue2, Node)
		}
	}
	return &biTree{Root: node}
}

func Mirror(bt *biTree) *biTree {
	root := bt.Root
	if root == nil {
		return &biTree{}
	}
	node := &btNode{Data: root.Data}
	Queue1, Queue2 := []*btNode{root}, []*btNode{node}
	for len(Queue1) > 0 {
		p1, p2 := Queue1[0], Queue2[0]
		Queue1, Queue2 = Queue1[1:], Queue2[1:]
		if p1.Lchild != nil {
			Node := &btNode{Data: p1.Lchild.Data}
			p2.Rchild = Node
			Queue1 = append(Queue1, p1.Lchild)
			Queue2 = append(Queue2, Node)
		}
		if p1.Rchild != nil {
			Node := &btNode{Data: p1.Rchild.Data}
			p2.Lchild = Node
			Queue1 = append(Queue1, p1.Rchild)
			Queue2 = append(Queue2, Node)
		}
	}
	return &biTree{Root: node}
}

func (bt *biTree) BForder2D() [][]interface{} {
	var res [][]interface{}
	root := bt.Root
	if root == nil {
		return res
	}
	Queue := []*btNode{root}
	for len(Queue) > 0 {
		Nodes := []interface{}{}
		Levels := len(Queue)
		for Levels > 0 {
			cur := Queue[0]
			Queue = Queue[1:]
			Nodes = append(Nodes, cur.Data)
			Levels--
			if cur.Lchild != nil {
				Queue = append(Queue, cur.Lchild)
			}
			if cur.Rchild != nil {
				Queue = append(Queue, cur.Rchild)
			}
		}
		res = append(res, Nodes)
	}
	return res
}

func (bt *biTree) LevelNullwith(Fills ...interface{}) [][]interface{} {
	var Nodes [][]interface{}
	var Fill0 interface{}
	if len(Fills) == 0 {
		Fill0 = nil
	} else if len(Fills) == 1 {
		Fill0 = Fills[0]
	} else {
		panic("Error: number of parameters is greater than 1")
	}
	root := bt.Root
	if root == nil {
		return Nodes
	}
	Count := 0
	Queue := []*btNode{root}
	for len(Queue) > 0 {
		nodes := []interface{}{}
		Level := len(Queue)
		for Level > 0 {
			cur := Queue[0]
			Queue = Queue[1:]
			nodes = append(nodes, cur.Data)
			Count++
			Level--
			if cur.Lchild != nil {
				Queue = append(Queue, cur.Lchild)
			}
			if cur.Rchild != nil {
				Queue = append(Queue, cur.Rchild)
			}
		}
		Nodes = append(Nodes, nodes)
	}
	newbiTree := Copy(bt)
	for i := 1; i < Pow2(len(Nodes))-Count; i++ {
		newbiTree.AppendNode(Fill0)
	}
	return newbiTree.BForder2D()
}

func XmlNode(M, N, X, Y int, Data string, Color ...string) string {
	var cColor, tColor string
	R := 30
	Node := `<Tab><g id="M,N">
	<circle cx="X" cy="Y" r="RC" stroke="black" stroke-width="2" fill="COLOR" />
	<text x="X" y="Y" fill="TextColor" font-size="20" text-anchor="middle"
		dominant-baseline="middle">DATA</text>
	<ROOT/>
	</g><CrLf>`
	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, "<CrLf>", "\n", -1)
	Node = strings.Replace(Node, "<Tab>", "\t", -1)
	Node = strings.Replace(Node, "\n\t\t", " ", -1)
	return Node
}

func Pow2(x int) int { //x>=0
	res := 1
	for i := 0; i < x; i++ {
		res *= 2
	}
	return res
}

func Xml4Full(Levels int) string {
	var Xml, Node string
	Head := "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/" +
		"1999/xlink\" version=\"1.1\" width=\"Width\" height=\"Height\">\nCONTENT</svg>"
	Line := `<line x1="X1" y1="Y1" x2="X2" y2="Y2" style="stroke:black;stroke-width:2"/>`
	Link := `<a xlink:href="https://blog.csdn.net/boysoft2002" rel="external nofollow"  rel="external nofollow"  target="_blank">
	<text x="5" y="20" fill="blue">Hann's CSDN Homepage</text></a>`
	for i := 0; i < Levels; i++ {
		negative := -1
		for j := 0; j < Pow2(i); j++ {
			t := Pow2(Levels - i - 1)
			x, y := 50*(2*t*j+t), 120*i+50
			if Levels != 1 && i == Levels-1 {
				Xml = XmlNode(i, j, x, y, strconv.Itoa(Pow2(i)+j), "lightgreen")
			} else {
				Xml = XmlNode(i, j, x, y, strconv.Itoa(Pow2(i)+j))
			}
			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
				//过连线起始端的半径与纵轴线夹角取45度时x,y坐标修正值21,21[30/1.414]
				//取30度时 x0,y0:= 15,30-26;取60度时 x0,y0:= 26[15*1.732],15
				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, "<ROOT/>", line1, 1)
			}
			Node += Xml
		}
	}
	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, "<ROOT/>", Link, 1)
	return Xml
}

func (bt *biTree) Xml4Tree() string {
	var Xml, Node string
	Head := "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/" +
		"1999/xlink\" version=\"1.1\" width=\"Width\" height=\"Height\">\nCONTENT</svg>"
	Line := `<line x1="X1" y1="Y1" x2="X2" y2="Y2" style="stroke:black;stroke-width:2"/>`
	Link := `<a xlink:href="https://blog.csdn.net/boysoft2002" rel="external nofollow"  rel="external nofollow"  target="_blank">
	<text x="5" y="20" fill="blue">Hann's CSDN Homepage</text></a>`
	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, "<ROOT/>", 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, "<ROOT/>", Link, 1)
	return Xml
}

func main() {

	var file *os.File
	var err1 error

	list1 := []interface{}{"-", "*", 6, "+", 3, nil, nil, 2, 8}
	list2 := []interface{}{1, 2, 3, 4, 5, nil, 6, 7, 8}
	tree1 := Build(list1)
	tree2 := Build(list2)
	tree3 := Mirror(tree2)
	texts := []string{tree1.Xml4Tree(), tree2.Xml4Tree(), tree3.Xml4Tree(), Xml4Full(4)}

	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()
	}

	fmt.Println("Welcome to my homepage: https://blog.csdn.net/boysoft2002")
	exec.Command("cmd", "/c", "start", "https://blog.csdn.net/boysoft2002").Start()

}

至此,已达成自己的预想结果,算法实在有点笨拙,但总算成功了。

到此这篇关于Go语言制作svg格式树形图的示例代码的文章就介绍到这了,更多相关Go语言树形图内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 利用go语言实现查找二叉树中的最大宽度

    目录 介绍 流程 代码 二叉树结构体 测试代码 查找二叉树最大宽度的代码 代码解读 介绍 这道题是这样的,有一个二叉树,让求出这颗Bt树里面最大的宽度是有几个节点,同时还要求出最大宽度的这些节点在第几层? 比如:下面这颗树,它每层最大的宽度是3,所在的层数是在第3层 流程 这个题主要是使用队列的方式来存储需要遍历的节点 同时还需要几个变量来存储最大的宽度(maxWidth).每层有几个节点(count).最大宽度所在的层(maxInrow).当前层最后一个节点(currentRowEndNode

  • go语言实现二叉树的序例化与反序列化

    目录 二叉树的反序列化 反序列化 解题思路 TreeNode结构体 反序列化方法 代码解读 二叉树的序列化 介绍 解题思路 代码 代码解读 运行结果 二叉树的反序列化 反序列化 树的反序列化故名知意就是将一个序列化成字符串或者其它形式的数据重新的生成一颗二叉树,如下这颗二叉树将它序列化成字符串后的结果[5,4,null,null,3,2,1],而现在要做的是要将这个字符串重新的生成一颗二叉树(生成下面这颗树,因为这个字符串就是通过这颗树序列化来的). 解题思路 首先,应该先拿到一个序列化后数据,

  • Go 数据结构之二叉树详情

    目录 Go 语言实现二叉树 定义二叉树的结构 二叉树遍历 创建二叉树 插入值 测试 前言: 树可以有许多不同的形状,并且它们可以在每个节点允许的子节点数量或它们在节点内组织数据值的方式上有所不同. 而在其中最常用的树之一是二叉树. 二叉树是一棵树,其中每个节点最多可以有两个孩子. 一个孩子被识别为左孩子,另一个孩子被识别为右孩子. 二叉树是一种数据结构,在每个节点下面最多存在两个其他节点.即一个节点要么连接至一个.两个节点或不连接其他节点. 树形结构的深度(也被称作高度)则被定义为根节点为根节点

  • 详解Go语言如何实现二叉树遍历

    目录 1. 二叉树的定义 2. 前序遍历 3. 中序遍历 4. 后序遍历 1. 二叉树的定义 二叉树需满足的条件 ① 本身是有序树 ② 树中包含的各个节点的长度不能超过2,即只能是0.1或者2 2. 前序遍历 前序遍历二叉树的顺序:根——>左——>右 package main import "fmt" //定义结构体 type Student struct { Name string Age int Score float32 left *Student //左子树指针 r

  • 利用go语言判断是否是完全二叉树

    目录 一.什么是完全二叉树? 二.流程 三.代码 1.树节点 2.测试代码 3.判断树是否为完全二叉树代码 4.代码解读 5.运行结果 一.什么是完全二叉树? 先看如下这一张图: 这个一颗二叉树,如何区分该树是不是完全二叉树呢? 当一个节点存在右子节点但是不存在左子节点这颗树视为非完全二叉树 当一个节点的左子节点存在但是右子节点不存在视为完全二叉树 如果没有子节点,那也是要在左侧开始到右侧依次没有子节点才视为完全二叉树,就像上图2中 而上面第一张图这颗二叉树很明显是一颗非完全二叉树,因为在第三层

  • Go语言数据结构之二叉树必会知识点总结

    目录 前言 二叉树概念 二叉树的性质 创建二叉树 树的遍历 前序遍历(V-L-R) 中序遍历(L-V-R) 后序遍历(L-R-V) 前言 如果你是一个开发人员,或多或少对树型结构都有一定的认识,我个人对树型数据结构是又爱又恨.二叉树作为树的一种,是一种重要的数据结构,也是面试官经常考的东西.这篇文章主要分享下关于二叉树相关的知识点,并用go语言实现一个二叉树和对二叉树进行遍历. 二叉树概念 二叉树是具有两个节点的树形结构,通常左边的子树被称为左子树,右边的子树称为右子树,图示如下: 在代码中我们

  • Go语言制作svg格式树形图的示例代码

    目录 什么是SVG SVG定义 SVG优点 预定义元素 圆形 <circle> 直线 <line> 文字 <text> 结点SVG格式 根结点 子树结点 叶结点 结点坐标 结点文本 二叉树转SVG 全部源代码 最近一直在刷二叉树题目,但在要验证结果时,通常用中序遍历.层序遍历查看结果,验证起来没有画图来得直观,所有想到自己动手制作二叉树的树形图. 直接开干,先从svg入手: 什么是SVG SVG定义 SVG是可伸缩矢量图形 (Scalable Vector Graphi

  • 基于Python制作AI聊天软件的示例代码

    目录 效果图 需要用到的库 窗体设计 函数 为粉丝们额外添加的功能 完整代码 效果图 先看一下效果图 就当是女友无聊的时候自己抽不出时间的小分身吧! 需要用到的库 tkinter.time.urllib.requests tkinter负责窗体.time显示时间.urllib和requests负责请求 窗体设计 from tkinter import * win1 = Tk() win1.geometry('400x644+100+100') win1.title('xxx男神的AI分身') L

  • C语言实现职工工资管理系统的示例代码

    目录 一.需求分析 二.项目环境 2.1.项目创建过程 2.2.向项目添加头文件与源文件 三.职工工资管理系统模块功能 3.1.系统总体设计框图 3.2.系统模块总体设计 3.3.设计系统菜单功能 3.4.设计系统输入模块 3.5.设计系统查询模块 3.6.设计系统修改模块 3.7.设计系统删除模块 3.8.设计系统统计模块 3.9.设计系统输出模块 3.10.设计系统追加模块 3.11.设计系统退出模块 总结 一.需求分析 1.随着计算机的飞速发展,它的应用已经十分广泛,它在人们的生产.生活.

  • Go语言实现Sm2加解密的示例代码

    在 Go 语言中,可以使用 github.com/tjfoc/gmsm/sm2 包来实现 SM2 加密和解密. 示例代码如下: package main import (     "fmt"     "crypto/rand"     "encoding/hex"     "github.com/tjfoc/gmsm/sm2" ) func main() {     // 生成密钥对     priKey, err := sm

  • go语言实现并发网络爬虫的示例代码

    go语言做爬虫也是很少尝试,首先我的思路是看一下爬虫的串行实现,然后通过两个并发实现:一个使用锁,另一个使用通道 这里不涉及从页面中提取URL的逻辑(请查看Go框架colly的内容).网络抓取只是作为一个例子来考察Go的并发性. 我们想从我们的起始页中提取所有的URL,将这些URL保存到一个列表中,然后对列表中的每个URL做同样的处理.页面的图很可能是循环的,所以我们需要记住哪些页面已经经历了这个过程(或者在使用并发时,处于这个过程的中间). 串行爬虫首先检查我们是否已经在获取地图中获取了该页面

  • java导出json格式文件的示例代码

    本文介绍了java导出json格式文件的示例代码,分享给大家,具体如下: 生成json文件代码: import java.io.File; import java.io.FileWriter; import java.io.Writer; public class CreateFileUtil { /** * 生成.json格式文件 */ public static boolean createJsonFile(String jsonString, String filePath, String

  • Python中xml和dict格式转换的示例代码

    在做接口自动化的时候,请求数据之前都是JSON格式的,Python有自带的包来解决.最近在做APP的接口,遇到XML格式的请求数据,费了很大劲来解决,解决方式是:接口文档拿到的是XML,在线转化为json格式(目的是拿到xml数据的模板),存放到json文件中,根据接口名去提取. github原文介绍:使用XML的Python模块感觉就像您在使用JSON 链接:https://github.com/martinblech/xmltodict 下载xmltodict(pip install xml

  • Python 保存加载mat格式文件的示例代码

    mat为matlab常用存储数据的文件格式,python的scipy.io模块中包含保存和加载mat格式文件的API,使用极其简单,不再赘述:另附简易示例如下: # -*- coding: utf-8 -*- import numpy as np import scipy.io as scio # data data = np.array([1,2,3]) data2 = np.array([4,5,6]) # save mat (data format: dict) scio.savemat(

  • vue制作抓娃娃机的示例代码

    去年为联通制作双十一活动,做四个小游戏:'配对消消乐'.移动拼图.抓娃娃.倒计时. 现在先做来分享一下制作抓娃娃游戏时的经验 先上效果图 游戏规则:在指定时间内抓到上图四张卡片为挑战成功. 现在直接说游戏主要内容:娃娃滚动.爪子向下抓取.抓到卡片 废话不多说直接上代码!(此样式是根据需求而定) <!--布局样式--> <div class="game"> <!--爪子--> <div class="paw"> <

  • C语言实现无头单向链表的示例代码

    目录 一.易错的接口实现 1.1 新节点开辟函数 1.2 尾插 1.3 尾删 二.常见简单接口 2.1 打印链表 2.2 节点计数器 2.3 判断是否为空链表 2.4 通过值查找节点 2.5 头插 2.6 头删 2.7 在任意节点后插入节点 2.8 在任意节点后删除节点 2.9 销毁链表 三.头文件相关内容 3.1 引用的库函数 3.2 结构体声明 一.易错的接口实现 1.1 新节点开辟函数 由于创建一个新节点是频繁的操作,所以封装为一个接口最佳. 链表节点的属性有:(1)数值.(2)指向下一个

随机推荐