首页 > 其他分享 >二叉树Golang

二叉树Golang

时间:2024-11-16 18:43:09浏览次数:3  
标签:node 遍历 TreeNode nil Golang Right 二叉树 root

二叉树

前言

  • 完全二叉树
    • 最底层节点按顺序从左到右排列。
  • 满二叉树
    • 一颗二叉树只有0度和2度的节点。
  • 二叉搜索树
    • 左子树上的所有节点的值均小于根节点的值。
    • 右子树上的所有节点的值均大于根节点的值。
  • 平衡二叉搜索树
    • 左右两个子树的高度差的绝对值不超过1 。

二叉树的存储方式有链式存储和数组存储。(线索二叉树、红黑树等)

1、链表存储方式

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

func NewTreeNode(val int) *TreeNode {
	return &TreeNode{Val: val}
}

2、数组存储方式

	// 完全二叉树:         1
	//                  /   \
	//                 2     3
	//                / \   / \
	//               4   5 6   7
	// 以下为前中后序遍历,以下例子也是这个结果
	//	1245367 
	//	4251637
	//	4526731

左子树:2 * i + 1

右子树:2 * i + 2

(i是数组的下标),元素值为arr[ 2 * i + 1 ]或arr[ 2 * i + 2 ]

接下来将讲解二叉树的几种遍历方式,我全篇使用链式存储结构。

一、深度优先遍历

1、前序遍历

1、递归遍历

// 前序遍历:根 -> 左 -> 右
func preorderTraversal(root *TreeNode) {
	if root != nil {
		fmt.Println(root.Val)         // 访问根节点
		preorderTraversal(root.Left)  // 递归遍历左子树
		preorderTraversal(root.Right) // 递归遍历右子树
	}
}

2、迭代遍历

深度优先遍历的递归版本都是简洁易读的,相较于迭代版本,更直观。迭代版本使用到了一种数据结构栈,以下我使用的栈是自己封装的库函数,如果有感兴趣的朋友,可以看shard库介绍,写shard库主要还是由于Golang没提供更多的数据结构模版。

// 前序遍历:根 -> 左 -> 右(迭代实现)
func preorderTraversal(root *TreeNode) {
	if root == nil {
		return
	}
	// 栈存放的全是 *TreeNode
	s := shard.NewStackArray[*TreeNode]()
	s.Push(root)
	for s.Len() > 0 {
		// 栈顶弹出并删除
		node, _ := s.Pop()
		fmt.Println(node.Val)
		// 先压右子节点,再压左子节点,因为栈是后进先出(LIFO)
		if node.Right != nil {
			s.Push(node.Right)
		}
		if node.Left != nil {
			s.Push(node.Left)
		}
	}
}

2、中序遍历

1、递归遍历

// 中序遍历:左 -> 根 -> 右
func inorderTraversal(root *TreeNode) {
	if root != nil {
		inorderTraversal(root.Left)  // 递归遍历左子树
		fmt.Println(root.Val)        // 访问根节点
		inorderTraversal(root.Right) // 递归遍历右子树
	}
}

2、迭代遍历

// 中序遍历:左 -> 根 -> 右(迭代实现)
func inorderTraversal(root *TreeNode) {
	if root == nil {
		return
	}
	// 栈存放的全是 *TreeNode
	s := shard.NewStackArray[*TreeNode]()
	cur := root
	for cur != nil || !s.IsEmpty() {
		for cur != nil {
			s.Push(cur)
			cur = cur.Left
		}
		node, _ := s.Pop()
		fmt.Println(node.Val)
		cur = node.Right
	}
}

3、后序遍历

1、递归遍历

// 后序遍历:左 -> 右 -> 根
func postorderTraversal(root *TreeNode) {
	if root != nil {
		postorderTraversal(root.Left)  // 递归遍历左子树
		postorderTraversal(root.Right) // 递归遍历右子树
		fmt.Println(root.Val)          // 访问根节点
	}
}

2、迭代遍历

// 后序遍历:左 -> 右 -> 根(迭代实现)
func postorderTraversal(root *TreeNode) {
	if root == nil {
		return
	}
	// 栈存放的全是 *TreeNode
	s1 := shard.NewStackArray[*TreeNode]()
	s1.Push(root)
	s2 := shard.NewStackArray[*TreeNode]()
	for !s1.IsEmpty() {
		node, _ := s1.Pop()
		s2.Push(node)
		if node.Left != nil {
			s1.Push(node.Left)
		}
		if node.Right != nil {
			s1.Push(node.Right)
		}
	}
	for !s2.IsEmpty() {
		node, _ := s2.Pop()
		fmt.Println(node.Val)
	}
}

二、广度优先遍历

1、层序遍历

// 层序遍历
func postorderTraversal(root *TreeNode) {
	if root == nil {
		return
	}
	q := shard.NewQueueArray[*TreeNode]()
	q.Enqueue(root)
	for !q.IsEmpty() {
		node, _ := q.Dequeue()
		fmt.Print(node.Val, " ")
		if node.Left != nil {
			q.Enqueue(node.Left)
		}
		if node.Right != nil {
			q.Enqueue(node.Right)
		}
	}
}

三、shard库介绍

GitHub链接:https://github.com/xzhHas/shard

shard库获取:

go get -u github.com/xzhHas/shard@latest

关于使用Golang写一个数据结构的库,目前只支持栈、队列、堆。

在这里插入图片描述

标签:node,遍历,TreeNode,nil,Golang,Right,二叉树,root
From: https://blog.csdn.net/m0_73337964/article/details/143789461

相关文章

  • golang: 在线上用nginx部署应用
    一,启动应用:1,编译程序$gobuild2,用nohup启动应用的二进制程序$nohup/data/goapp/industry/industry>>/data/logs/gologs/back.log2>&1&[1]48963,检查应用是否启动:$ss-lntp|grep3000LISTEN040960.0.0.0:30000.0.0.0:*users:(("......
  • 力扣 LeetCode 94. 二叉树的中序遍历(Day6:二叉树)
    解题思路:方法一:递归(左中右)classSolution{List<Integer>res=newArrayList<>();publicList<Integer>inorderTraversal(TreeNoderoot){recur(root);returnres;}publicvoidrecur(TreeNoderoot){if(......
  • 114. 二叉树展开为链表
    题目链接解题思路:对于这类递归问题,采用「宏观」思考模式。对于任意一个节点A,左子树先「展开为链表」,右子树再「展开为链表」,然后A节点,将左子树的结果,和右子树的结果,「串在一起」即可。左子树展开为链表,所以要返回两个节点,一个是链表的头,然后是链表的尾。代码/***......
  • 617. 合并二叉树
    题目链接解题思路分情况讨论即可两个头都是空,直接返回空若root1为空,直接返回root2若roo2为空,直接返回root1若都不空,则二者相加,得到一个新节点A,然后二者的左子树去合并,得到一个新左子树new_left,二者的右子树去合并,得到一个新右子树new_right,然后新节点的左儿子就是new_......
  • 104. 二叉树的最大深度
    题目链接解题思路普通的递归可能很简单,但是,现在要求,使用「二叉树递归套路」来思考问题每个节点需要什么信息?如果根节点,能够有一个「最大深度」的信息,那么直接返回就可以了。那么,这个信息可以通过左子树信息+右子树信息得到吗?max(左子树最大深度,右子树最大深度)+1......
  • 102. 二叉树的层序遍历
    题目链接解题思路层序遍历就是用队列,本题需要一层一层收集答案,所以我们可以用一个变量cur,表示该层还剩多少节点需要收集,同时,遇到一个节点,还要将其孩子节点放入队尾。那么我们怎么知道下一层的节点个数,所以还需要一个变量next,记录下一层的节点个数。总结一遍:每次从队头......
  • LeetCode654.最大二叉树
    LeetCode刷题记录文章目录......
  • 数据结构 ——— 利用前序序列重建链式二叉树
    目录题目要求链式二叉树示意图​编辑代码实现 题目要求读入用户输入的一串前序遍历的字符串,根据此字符串建立一个链式二叉树例如前序遍历的字符串为:ABC##DE#G##F###;其中"#"表示空树链式二叉树示意图以此图的链式二叉树为例子那么此链式二叉树前序遍历转换为字符......
  • CICD03 Jenkins对golang项目构建, 结合ansible, 构建通知, 自动化构建(定时,webhook),
    2.7.2基于Maven风格的任务构建基于WAR包运行Tomcat服务器JAVA项目maven配置繁琐,功能固定不灵活,不如自由风格好用,这里推荐用自由风格脚本实现更好目前最高依赖到tomcat9,更高版本的tomcat不支持2.7.2.2安装tomcat服务器和配置#在gitlab新建java项目(此项目使用JD......
  • 力扣—543.二叉树的直径
    543.二叉树的直径给你一棵二叉树的根节点,返回该树的 直径 。二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。两节点之间路径的 长度 由它们之间边数表示。示例1:输入:root=[1,2,3,4,5]输出:3解释:3,取......