层序遍历重建二叉树,绘制二叉树图片

在力扣刷二叉树相关题目时,输入一般都是完全层序遍历,我习惯在自己电脑上调试代码,因此才编写下面代码将完全层序遍历数据重建二叉树对象。

生成的结果二叉树一般也只会给出完全层序遍历,无法直观的感受二叉树实际情况,因此我编写代码将二叉树对象生成svg图片,刷二叉树相关题目更清晰直观了。

力扣原题:https://leetcode.cn/problems/w6cpku/ ,效果图如下:

代码如下:

package main

import (
	"fmt"
	"math"
	"os"
	"strconv"
	"strings"
)

type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

// 根据完全层序遍历构建二叉树
func buildTree(s string) *TreeNode {
	nums := strings.Split(strings.ReplaceAll(s, " ", ""), ",")
	if len(nums) == 0 {
		return nil
	}

	n, err := strconv.Atoi(nums[0])
	if err != nil {
		return nil
	}

	var (
		root  = &TreeNode{Val: n}
		queue = []*TreeNode{root}
		i     = 1
	)
	for i < len(nums) {
		node := queue[0]
		queue = queue[1:]
		if n, err = strconv.Atoi(nums[i]); err == nil {
			node.Left = &TreeNode{Val: n}
			queue = append(queue, node.Left)
		}
		i++
		if i < len(nums) {
			if n, err = strconv.Atoi(nums[i]); err == nil {
				node.Right = &TreeNode{Val: n}
				queue = append(queue, node.Right)
			}
		}
		i++
	}
	return root
}

// 生成完全层序遍历
func levelOrder(root *TreeNode) string {
	if root == nil {
		return ""
	}
	var (
		result strings.Builder
		queue  = []*TreeNode{root}
	)
	for len(queue) != 0 {
		node := queue[0]
		queue = queue[1:]
		if node == nil {
			result.WriteString("null,")
		} else {
			result.WriteString(strconv.Itoa(node.Val))
			result.WriteByte(',')
			queue = append(queue, node.Left)
			queue = append(queue, node.Right)
		}
	}
	return strings.TrimRightFunc(result.String(), func(r rune) bool {
		return r == 'n' || r == 'u' || r == 'l' || r == ','
	})
}

// 生成二叉树的SVG图片
func generateSVG(root *TreeNode) string {
	var treeHeight func(*TreeNode) int
	treeHeight = func(root *TreeNode) int {
		if root == nil {
			return 0
		}
		return max(treeHeight(root.Left), treeHeight(root.Right)) + 1
	}

	var (
		height = treeHeight(root)
		width  = int(math.Pow(2, float64(height))) * 50

		draw func(node *TreeNode, x, y, level int)

		svg = &strings.Builder{}
	)
	fmt.Fprintf(svg, `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 %d %d">`, width, height*100)

	draw = func(node *TreeNode, x, y, level int) {
		if node == nil {
			return
		}

		nextLevel := level + 1
		offset := int(math.Pow(2, float64(height-nextLevel-1))) * 50

		if node.Left != nil {
			leftX := x - offset
			leftY := y + 100
			fmt.Fprintf(svg, `<line x1="%d" y1="%d" x2="%d" y2="%d" stroke="black" stroke-width="2" />`, x, y, leftX, leftY)
			draw(node.Left, leftX, leftY, nextLevel)
		}

		if node.Right != nil {
			rightX := x + offset
			rightY := y + 100
			fmt.Fprintf(svg, `<line x1="%d" y1="%d" x2="%d" y2="%d" stroke="black" stroke-width="2" />`, x, y, rightX, rightY)
			draw(node.Right, rightX, rightY, nextLevel)
		}

		fmt.Fprintf(svg, `<circle cx="%d" cy="%d" r="20" fill="lightblue" />`, x, y)
		fmt.Fprintf(svg, `<text x="%d" y="%d" text-anchor="middle" dominant-baseline="middle">%d</text>`, x, y, node.Val)
	}

	draw(root, width/2, 50, 0)
	svg.WriteString(`</svg>`)
	return svg.String()
}

func main() {
	root := buildTree("4,1,6,0,2,5,7,null,null,null,3,null,null,null,8")

	svg := generateSVG(root)

	err := os.WriteFile("binary_tree.svg", []byte(svg), 0666)
	if err != nil {
		fmt.Println("Error writing to file:", err)
		return
	}

	fmt.Println("SVG file created successfully!")
}

来源链接:https://www.cnblogs.com/janbar/p/18851553

© 版权声明
THE END
支持一下吧
点赞14 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容