最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言數(shù)據(jù)結(jié)構(gòu)之二叉樹可視化詳解

 更新時間:2022年09月18日 08:32:31   作者:Hann?Yang  
這篇文章主要為大家詳細(xì)介紹了Go語言數(shù)據(jù)結(jié)構(gòu)中二叉樹可視化的方法詳解,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

題目

以圖形展示任意二叉樹,如下圖,一個中綴表達(dá)式表示的二叉樹:3.14*r²*h/3

源代碼

package main
 
import (
    "fmt"
    "io"
    "os"
    "os/exec"
    "strconv"
    "strings"
)
 
type any = interface{}
 
type btNode struct {
    Data   any
    Lchild *btNode
    Rchild *btNode
}
 
type biTree struct {
    Root *btNode
    Info *biTreeInfo
}
 
type biTreeInfo struct {
    Data                []any
    DataLevel           [][]any
    L, R                []bool
    X, Y, W             []int
    Index, Nodes        int
    Width, Height       int
    MarginX, MarginY    int
    SpaceX, SpaceY      int
    SvgWidth, SvgHeight int
    SvgXml              string
}
 
func Build(Data ...any) *biTree {
    if len(Data) == 0 || Data[0] == nil {
        return &biTree{}
    }
    node := &btNode{Data: Data[0]}
    Queue := []*btNode{node}
    for lst := Data[1:]; len(lst) > 0 && len(Queue) > 0; {
        cur, val := Queue[0], lst[0]
        Queue, lst = Queue[1:], lst[1:]
        if val != nil {
            cur.Lchild = &btNode{Data: val}
            Queue = append(Queue, cur.Lchild)
        }
        if len(lst) > 0 {
            val, lst = lst[0], lst[1:]
            if val != nil {
                cur.Rchild = &btNode{Data: val}
                Queue = append(Queue, cur.Rchild)
            }
        }
    }
    return &biTree{Root: node}
}
 
func BuildFromList(List []any) *biTree {
    return Build(List...)
}
 
func AinArray(sub int, array []int) int {
    for idx, arr := range array {
        if sub == arr {
            return idx
        }
    }
    return -1
}
 
func Pow2(x int) int { //x>=0
    res := 1
    for i := 0; i < x; i++ {
        res *= 2
    }
    return res
}
 
func Max(L, R int) int {
    if L > R {
        return L
    } else {
        return R
    }
}
 
func (bt *btNode) MaxDepth() int {
    if bt == nil {
        return 0
    }
    Lmax := bt.Lchild.MaxDepth()
    Rmax := bt.Rchild.MaxDepth()
    return 1 + Max(Lmax, Rmax)
}
 
func (bt *btNode) Coordinate(x, y, w int) []any {
    var res []any
    if bt != nil {
        L, R := bt.Lchild != nil, bt.Rchild != nil
        res = append(res, []any{bt.Data, L, R, x, y, w})
        res = append(res, bt.Lchild.Coordinate(x-w, y+1, w/2)...)
        res = append(res, bt.Rchild.Coordinate(x+w, y+1, w/2)...)
    }
    return res
}
 
func (bt *biTree) NodeInfo() []any {
    return bt.Root.Coordinate(0, 0, Pow2(bt.Root.MaxDepth()-2))
}
 
func (bt *biTree) TreeInfo() {
    height := bt.Root.MaxDepth()
    width := Pow2(height - 1)
    lsInfo := bt.NodeInfo()
    btInfo := &biTreeInfo{
        Height: height,
        Width:  width,
        Nodes:  len(lsInfo),
    }
    for _, data := range lsInfo {
        for i, info := range data.([]any) {
            switch i {
            case 0:
                btInfo.Data = append(btInfo.Data, info.(any))
            case 1:
                btInfo.L = append(btInfo.L, info.(bool))
            case 2:
                btInfo.R = append(btInfo.R, info.(bool))
            case 3:
                btInfo.X = append(btInfo.X, info.(int))
            case 4:
                btInfo.Y = append(btInfo.Y, info.(int))
            case 5:
                btInfo.W = append(btInfo.W, info.(int))
            }
        }
    }
    for j, k := 0, width*2; j < height; j++ {
        DLevel := []any{}
        for i := k / 2; i < width*2; i += k {
            index := AinArray(i-width, btInfo.X)
            if index > -1 {
                DLevel = append(DLevel, btInfo.Data[index])
            } else {
                DLevel = append(DLevel, nil)
            }
            DLevel = append(DLevel, []int{i, j})
            if k/4 == 0 {
                DLevel = append(DLevel, []int{0, 0})
                DLevel = append(DLevel, []int{0, 0})
            } else {
                DLevel = append(DLevel, []int{i - k/4, j + 1})
                DLevel = append(DLevel, []int{i + k/4, j + 1})
            }
        }
        k /= 2
        btInfo.DataLevel = append(btInfo.DataLevel, DLevel)
    }
    bt.Info = btInfo
}
 
func (bt *biTree) Info2SVG(Margin ...int) string {
    var res, Line, Color string
    info := bt.Info
    MarginX, MarginY := 0, 10
    SpaceX, SpaceY := 40, 100
    switch len(Margin) {
    case 0:
        break
    case 1:
        MarginX = Margin[0]
    case 2:
        MarginX, MarginY = Margin[0], Margin[1]
    case 3:
        MarginX, MarginY, SpaceX = Margin[0], Margin[1], Margin[2]
    default:
        MarginX, MarginY = Margin[0], Margin[1]
        SpaceX, SpaceY = Margin[2], Margin[3]
    }
    info.MarginX, info.MarginY = MarginX, MarginY
    info.SpaceX, info.SpaceY = SpaceX, SpaceY
    info.SvgWidth = Pow2(info.Height)*info.SpaceX + info.SpaceX
    info.SvgHeight = info.Height * info.SpaceY
    for i, Data := range info.Data {
        Node := "\n\t<g id=\"INDEX,M,N\">\n\t<CIRCLE/>\n\t<TEXT/>\n\t<LEAF/>\n\t</g>"
        DataStr := ""
        switch Data.(type) {
        case int:
            DataStr = strconv.Itoa(Data.(int))
        case float64:
            DataStr = strconv.FormatFloat(Data.(float64), 'g', -1, 64)
        case string:
            DataStr = Data.(string)
        default:
            DataStr = "Error Type"
        }
        Node = strings.Replace(Node, "INDEX", strconv.Itoa(info.Index), 1)
        Node = strings.Replace(Node, "M", strconv.Itoa(info.X[i]), 1)
        Node = strings.Replace(Node, "N", strconv.Itoa(info.Y[i]), 1)
        x0, y0 := (info.X[i]+info.Width)*SpaceX+MarginX, 50+info.Y[i]*SpaceY+MarginY
        x1, y1 := x0-info.W[i]*SpaceX, y0+SpaceY-30
        x2, y2 := x0+info.W[i]*SpaceX, y0+SpaceY-30
        Color = "orange"
        if info.L[i] && info.R[i] {
            Line = XmlLine(x0-21, y0+21, x1, y1) + "\n\t" + XmlLine(x0+21, y0+21, x2, y2)
        } else if info.L[i] && !info.R[i] {
            Line = XmlLine(x0-21, y0+21, x1, y1)
        } else if !info.L[i] && info.R[i] {
            Line = XmlLine(x0+21, y0+21, x2, y2)
        } else {
            Color = "lightgreen"
        }
        Node = strings.Replace(Node, "<CIRCLE/>", XmlCircle(x0, y0, Color), 1)
        Node = strings.Replace(Node, "<TEXT/>", XmlText(x0, y0, DataStr), 1)
        if info.L[i] || info.R[i] {
            Node = strings.Replace(Node, "<LEAF/>", Line, 1)
        }
        res += Node
    }
    info.SvgXml = res
    return res
}
 
func XmlCircle(X, Y int, Color string) string {
    Radius := 30
    Circle := "<circle cx=\"" + strconv.Itoa(X) + "\" cy=\"" + strconv.Itoa(Y) +
        "\" r=\"" + strconv.Itoa(Radius) + "\" stroke=\"black\" stroke-width=" +
        "\"2\" fill=\"" + Color + "\" />"
    return Circle
}
 
func XmlText(X, Y int, DATA string) string {
    iFontSize, tColor := 20, "red"
    Text := "<text x=\"" + strconv.Itoa(X) + "\" y=\"" + strconv.Itoa(Y) +
        "\" fill=\"" + tColor + "\" font-size=\"" + strconv.Itoa(iFontSize) +
        "\" text-anchor=\"middle\" dominant-baseline=\"middle\">" + DATA + "</text>"
    return Text
}
 
func XmlLine(X1, Y1, X2, Y2 int) string {
    Line := "<line x1=\"" + strconv.Itoa(X1) + "\" y1=\"" + strconv.Itoa(Y1) +
        "\" x2=\"" + strconv.Itoa(X2) + "\" y2=\"" + strconv.Itoa(Y2) +
        "\" style=\"stroke:black;stroke-width:2\" />"
    return Line
}
 
func (bt *biTree) ShowSVG(FileName ...string) {
    var file *os.File
    var err1 error
    Head := "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink" +
        "=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=" +
        "\"Width\" height=\"Height\">\nLINKCONTENT\n</svg>"
    Link := `<a xlink: target="_blank">
    <text x="5" y="20" fill="blue">Hann's CSDN Homepage</text></a>`
    Xml := strings.Replace(Head, "LINK", Link, 1)
    Xml = strings.Replace(Xml, "Width", strconv.Itoa(bt.Info.SvgWidth), 1)
    Xml = strings.Replace(Xml, "Height", strconv.Itoa(bt.Info.SvgHeight), 1)
    Xml = strings.Replace(Xml, "CONTENT", bt.Info.SvgXml, 1)
    svgFile := "biTree.svg"
    if len(FileName) > 0 {
        svgFile = FileName[0] + ".svg"
    }
    file, err1 = os.Create(svgFile)
    if err1 != nil {
        panic(err1)
    }
    _, err1 = io.WriteString(file, Xml)
    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()
}
 
func main() {
 
    list := []any{"*", "*", "*", "/", 5, "*", 3.14, 1, 3, nil, nil, 6, 6}
    tree := Build(list...)
    tree.TreeInfo()
    tree.Info2SVG()
    tree.ShowSVG()
 
    fmt.Println(tree.Info.Data)
    fmt.Println(tree.Info.DataLevel)
 
}

做題思路

增加一個結(jié)構(gòu)biTreeInfo,在遍歷二叉樹時把作圖要用的信息存入此結(jié)構(gòu)中,方便讀取信息。

type any = interface{}

type btNode struct {
    Data   any
    Lchild *btNode
    Rchild *btNode
}

type biTree struct {
    Root *btNode
    Info *biTreeInfo
}

type biTreeInfo struct {
    Data                []any
    DataLevel           [][]any
    L, R                []bool
    X, Y, W             []int
    Index, Nodes        int
    Width, Height       int
    MarginX, MarginY    int
    SpaceX, SpaceY      int
    SvgWidth, SvgHeight int
    SvgXml              string
}
//數(shù)據(jù)域類型用 type any = interface{} 自定義類型,模擬成any數(shù)據(jù)類型。

遍歷二叉樹獲取每個結(jié)點(diǎn)在svg圖形中的坐標(biāo),使用先序遞歸遍歷:

func (bt *btNode) Coordinate(x, y, w int) []any {
    var res []any
    if bt != nil {
        L, R := bt.Lchild != nil, bt.Rchild != nil
        res = append(res, []any{bt.Data, L, R, x, y, w})
        res = append(res, bt.Lchild.Coordinate(x-w, y+1, w/2)...)
        res = append(res, bt.Rchild.Coordinate(x+w, y+1, w/2)...)
    }
    return res
}

二叉樹的每個結(jié)點(diǎn),轉(zhuǎn)svg時有圓、文字、左或右直線(葉結(jié)點(diǎn)沒有真線)。

func XmlCircle(X, Y int, Color string) string {
    Radius := 30
    Circle := "<circle cx=\"" + strconv.Itoa(X) + "\" cy=\"" + strconv.Itoa(Y) +
        "\" r=\"" + strconv.Itoa(Radius) + "\" stroke=\"black\" stroke-width=" +
        "\"2\" fill=\"" + Color + "\" />"
    return Circle
}

func XmlText(X, Y int, DATA string) string {
    iFontSize, tColor := 20, "red"
    Text := "<text x=\"" + strconv.Itoa(X) + "\" y=\"" + strconv.Itoa(Y) +
        "\" fill=\"" + tColor + "\" font-size=\"" + strconv.Itoa(iFontSize) +
        "\" text-anchor=\"middle\" dominant-baseline=\"middle\">" + DATA + "</text>"
    return Text
}

func XmlLine(X1, Y1, X2, Y2 int) string {
    Line := "<line x1=\"" + strconv.Itoa(X1) + "\" y1=\"" + strconv.Itoa(Y1) +
        "\" x2=\"" + strconv.Itoa(X2) + "\" y2=\"" + strconv.Itoa(Y2) +
        "\" style=\"stroke:black;stroke-width:2\" />"
    return Line
}

TreeInfo()寫入二叉樹結(jié)點(diǎn)信息,其中DataLevel是層序遍歷的結(jié)果,也可以用它來作圖。

Info2XML()就是把上述方法所得信息,轉(zhuǎn)化成SVG的xml代碼;

ShowSVG()生成并顯示圖形,svg的xml如下:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="680" height="400">
<a xlink: target="_blank">
    <text x="5" y="20" fill="blue">Hann's CSDN Homepage</text></a>
    <g id="0,0,0">
    <circle cx="320" cy="60" r="30" stroke="black" stroke-width="2" fill="orange" />
    <text x="320" y="60" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">*</text>
    <line x1="299" y1="81" x2="160" y2="130" style="stroke:black;stroke-width:2" />
    <line x1="341" y1="81" x2="480" y2="130" style="stroke:black;stroke-width:2" />
    </g>
    <g id="0,-4,1">
    <circle cx="160" cy="160" r="30" stroke="black" stroke-width="2" fill="orange" />
    <text x="160" y="160" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">*</text>
    <line x1="139" y1="181" x2="80" y2="230" style="stroke:black;stroke-width:2" />
    <line x1="181" y1="181" x2="240" y2="230" style="stroke:black;stroke-width:2" />
    </g>
    <g id="0,-6,2">
    <circle cx="80" cy="260" r="30" stroke="black" stroke-width="2" fill="orange" />
    <text x="80" y="260" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">/</text>
    <line x1="59" y1="281" x2="40" y2="330" style="stroke:black;stroke-width:2" />
    <line x1="101" y1="281" x2="120" y2="330" style="stroke:black;stroke-width:2" />
    </g>
    <g id="0,-7,3">
    <circle cx="40" cy="360" r="30" stroke="black" stroke-width="2" fill="lightgreen" />
    <text x="40" y="360" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">1</text>
    <LEAF/>
    </g>
    <g id="0,-5,3">
    <circle cx="120" cy="360" r="30" stroke="black" stroke-width="2" fill="lightgreen" />
    <text x="120" y="360" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">3</text>
    <LEAF/>
    </g>
    <g id="0,-2,2">
    <circle cx="240" cy="260" r="30" stroke="black" stroke-width="2" fill="lightgreen" />
    <text x="240" y="260" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">5</text>
    <LEAF/>
    </g>
    <g id="0,4,1">
    <circle cx="480" cy="160" r="30" stroke="black" stroke-width="2" fill="orange" />
    <text x="480" y="160" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">*</text>
    <line x1="459" y1="181" x2="400" y2="230" style="stroke:black;stroke-width:2" />
    <line x1="501" y1="181" x2="560" y2="230" style="stroke:black;stroke-width:2" />
    </g>
    <g id="0,2,2">
    <circle cx="400" cy="260" r="30" stroke="black" stroke-width="2" fill="orange" />
    <text x="400" y="260" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">*</text>
    <line x1="379" y1="281" x2="360" y2="330" style="stroke:black;stroke-width:2" />
    <line x1="421" y1="281" x2="440" y2="330" style="stroke:black;stroke-width:2" />
    </g>
    <g id="0,1,3">
    <circle cx="360" cy="360" r="30" stroke="black" stroke-width="2" fill="lightgreen" />
    <text x="360" y="360" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">6</text>
    <LEAF/>
    </g>
    <g id="0,3,3">
    <circle cx="440" cy="360" r="30" stroke="black" stroke-width="2" fill="lightgreen" />
    <text x="440" y="360" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">6</text>
    <LEAF/>
    </g>
    <g id="0,6,2">
    <circle cx="560" cy="260" r="30" stroke="black" stroke-width="2" fill="lightgreen" />
    <text x="560" y="260" fill="red" font-size="20" text-anchor="middle" dominant-baseline="middle">3.14</text>
    <LEAF/>
    </g>
</svg>

擴(kuò)展

多棵二叉樹同時展示,Info2SVG()可以設(shè)置起始位置

左右并列展示

    tree2 := Build("*", "*", 3.14, 6, 6)
    tree2.TreeInfo()
    tree2.Info2SVG()
    tree2.ShowSVG("tree2")
 
    //左右并列展示
    tree2.Info2SVG(tree.Info.SvgWidth, tree.Info.SpaceY)
    tree.Info.SvgXml += tree2.Info.SvgXml
    tree.Info.SvgWidth += tree2.Info.SvgWidth
    tree.ShowSVG("tree12")
    tree.Info2SVG() //恢復(fù)tree原狀

上下并列展示

    //上下并列展示
    tree2.Info2SVG(tree.Info.SvgWidth-tree2.Info.SvgWidth, tree.Info.SvgHeight)
    tree.Info.SvgXml += tree2.Info.SvgXml
    tree.Info.SvgHeight += tree2.Info.SvgHeight
    tree.ShowSVG("tree123")
    tree.Info2SVG() //恢復(fù)tree原狀

以上2段代碼放在前文源代碼的main()函數(shù)中測試。

總結(jié)回顧

結(jié)點(diǎn)顯示的代碼固定了文字和圓形的大小顏色,如果讀者愿意自己動手的話,可以嘗試把這些要素設(shè)成參數(shù)或者增加biTreeInfo結(jié)構(gòu)的屬性。

到此這篇關(guān)于Go語言數(shù)據(jù)結(jié)構(gòu)之二叉樹可視化詳解的文章就介紹到這了,更多相關(guān)Go語言 二叉樹可視化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一百行Golang代碼實(shí)現(xiàn)簡單并發(fā)聊天室

    一百行Golang代碼實(shí)現(xiàn)簡單并發(fā)聊天室

    這篇文章主要為大家詳細(xì)介紹了一百行Golang代碼如何實(shí)現(xiàn)簡單并發(fā)聊天室,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • Golang中函數(shù)的使用方法詳解

    Golang中函數(shù)的使用方法詳解

    這篇文章主要詳細(xì)介紹了Golang中函數(shù)的使用方法,文中有詳細(xì)的示例代碼,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-05-05
  • 詳解Go語言中配置文件使用與日志配置

    詳解Go語言中配置文件使用與日志配置

    這篇文章主要為大家詳細(xì)講解一下Go語言中調(diào)整項(xiàng)目目錄結(jié)構(gòu)、增加配置文件使用和增加日志配置的方法,文中示例代碼講解詳細(xì),需要的可以參考一下
    2022-06-06
  • Go框架自動化工具Beego使用詳解

    Go框架自動化工具Beego使用詳解

    這篇文章主要為大家介紹了Go框架自動化工具Beego使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Go語言編程入門超級指南

    Go語言編程入門超級指南

    這篇文章主要介紹了Go語言編程的入門指南,包括對Go的變量及函數(shù)的基本介紹,需要的朋友可以參考下
    2016-01-01
  • golang讀取yaml配置文件的示例代碼

    golang讀取yaml配置文件的示例代碼

    在項(xiàng)目開發(fā)中,經(jīng)常需要把一些配置文件常量提取到統(tǒng)一配置文件進(jìn)行維護(hù),go項(xiàng)目在開發(fā)中常常把需要維護(hù)的常量或者配置提取到y(tǒng)aml文件,所以本文主要來為大家介紹一下golang如何讀取yaml配置文件吧
    2023-11-11
  • Go語言如何在Web服務(wù)中實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)

    Go語言如何在Web服務(wù)中實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)

    在這篇文章中,我們將通過一個簡單的例子來演示如何在 Go 語言中使用 Gin 框架實(shí)現(xiàn)優(yōu)雅關(guān)機(jī),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • go內(nèi)存緩存BigCache實(shí)現(xiàn)BytesQueue源碼解讀

    go內(nèi)存緩存BigCache實(shí)現(xiàn)BytesQueue源碼解讀

    這篇文章主要為大家介紹了go內(nèi)存緩存BigCache實(shí)現(xiàn)BytesQueue源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Go語言開發(fā)代碼自測絕佳go?fuzzing用法詳解

    Go語言開發(fā)代碼自測絕佳go?fuzzing用法詳解

    這篇文章主要為大家介紹了Go語言開發(fā)代碼自測絕佳go?fuzzing用法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • go實(shí)現(xiàn)一個內(nèi)存緩存系統(tǒng)的示例代碼

    go實(shí)現(xiàn)一個內(nèi)存緩存系統(tǒng)的示例代碼

    本文主要介紹了go實(shí)現(xiàn)一個內(nèi)存緩存系統(tǒng)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10

最新評論

三门峡市| 利津县| 大连市| 三江| 军事| 株洲市| 湟源县| 淮安市| 若尔盖县| 九寨沟县| 怀集县| 麻江县| 元朗区| 名山县| 阆中市| 讷河市| 武山县| 大同县| 辉县市| 会理县| 峨边| 宁陵县| 曲周县| 东山县| 长子县| 赤壁市| 安岳县| 德昌县| 邢台县| 益阳市| 天全县| 舞钢市| 福贡县| 高要市| 三亚市| 抚顺县| 禄劝| 新宁县| 石屏县| 营口市| 卢龙县|