龙空技术网

搞懂二叉树的原理与实现,就可以举一反三,Golang实现二叉树!

大侠技术栈 174

前言:

今天小伙伴们对“java数组转化为二叉树”大约比较关切,咱们都想要学习一些“java数组转化为二叉树”的相关文章。那么小编同时在网摘上搜集了一些对于“java数组转化为二叉树””的相关文章,希望我们能喜欢,看官们快快来学习一下吧!

不要只收藏,还有别的事情可以做!不做自私的程序猿!

先来说说什么是树,生活中的树,就像下面这样,有根,有枝,有叶子。

通俗的讲,类比链表,数组,很明显,树不是线性的,而是左右这样延续下去的。

树是一种非线性的数据结构,相对于线性的数据结构(链表、数组)而言,树的平均运行时间更短(往往与树相关的排序时间复杂度都不会高)

前言

一般,我们分析树这种数据结构的时候,都会把树“倒过来”看。就如下图。

50节点,就是根节点,10节点,就是叶子节点。

二叉树的定义

二叉树是一种树形数据结构,它包含了n个有限元素的集合,其中每个元素都被称为节点。这些节点通过边(或链接)连接在一起,每个节点最多有两个子节点,分别称为左子树和右子树。树中的第一个节点被称为根节点,它是树的入口点。如果一个节点没有子节点,它被称为叶子节点。如果一个节点有子节点,它被称为内部节点。

二叉树的性质节点数和边数关系: 一个二叉树具有n个节点时,它必然有n-1条边。这是因为每个节点(除了根节点)都通过一条边与其他节点连接。高度和深度: 一个二叉树的高度(height)等于从根节点到最深叶子节点的最长路径上的节点数。根节点的深度(depth)为0,每向下一层,深度增加1。满二叉树: 如果每个节点都有0个或2个子节点,那么这棵二叉树称为满二叉树。在满二叉树中,除了叶子节点外,每个节点都有两个子节点。完全二叉树: 完全二叉树是指除了最后一层外,每一层都被充满节点,并且最后一层的节点从左到右依次填充,不留空缺。完全二叉树通常用于堆数据结构中。二叉搜索树(BST): 二叉搜索树是一种特殊的二叉树,其中每个节点的值大于其左子树中的所有节点的值,小于其右子树中的所有节点的值。这使得在BST中进行快速的搜索、插入和删除操作成为可能。平衡二叉树: 平衡二叉树是一种特殊的BST,其中左子树和右子树的高度之差不超过1。平衡二叉树的目标是确保树的高度相对较小,从而提高搜索和操作的性能。遍历方式: 二叉树可以通过不同的遍历方式进行遍历,包括前序遍历(preorder)、中序遍历(inorder)、后序遍历(postorder)和层序遍历(level order)。这些遍历方式用于按不同顺序访问树中的节点。高度平衡二叉树: 高度平衡二叉树(AVL树)是一种自平衡的BST,它通过在插入和删除操作时自动调整树的结构,以保持树的高度平衡,从而提供了稳定的性能。特点根节点:树的起始节点,所有其他节点都从根节点开始,通过边连接到根节点。子节点:每个节点最多有两个子节点,分别是左子树和右子树。叶子节点:没有子节点的节点称为叶子节点,它们是树的末端节点。内部节点:有至少一个子节点的节点称为内部节点。空二叉树:如果树中不包含任何节点,那么它被称为空二叉树。有序树:二叉树中的节点之间有顺序关系,即左子树和右子树之间的顺序。二叉树的存储

顺序存储

二叉树的顺序存储结构就是用一维数组存储二叉树中的结点,并且结点的存储位置,也就是数组的下标要能体现结点之间的逻辑关系,比如双亲与孩子的关系,左右兄弟的关系等。

满二叉树的顺序存储:

对于满二叉树,如果节点的下标为i(从0开始),则其左子节点的下标为2i+1,右子节点的下标为2i+2,父节点的下标为(i-1)/2。例如,数组 [1, 2, 3, 4, 5, 6, 7] 可以表示如下的满二叉树:

 1/ \2   3/ \ /4 5 6 7

完全二叉树的顺序存储:

对于完全二叉树,节点的存储也可以采用顺序方式,但不一定是满的。同样,节点的下标关系与满二叉树类似,但可能会有一些空洞。

二叉树的一般顺序存储:

对于一般的二叉树,顺序存储结构会有一些浪费空间,因为不是每个位置都有节点。通常,可以使用特殊的标记(如null或-1)来表示空节点。

这种顺序存储结构的优点包括对于某些操作的简单性,例如通过下标直接访问节点、节省存储空间等。但缺点是只适用于特定类型的二叉树,例如满二叉树或完全二叉树,并且在一般的二叉树中可能会浪费空间。在不同情况下,树的高度可能会影响到存储结构的效率。

链式储存

二叉树每个结点最多有两个孩子,所以为它设计一个数据域和两个指针域是比较自然的想法,我们称这样的链表叫做二叉链表。

Golang实现二叉树结构的定义

type TreeNode struct {	TreeNode  int           	Left   *TreeNode	Right  *TreeNode}
创建新的node
func NewTreeNode(value int) *TreeNode {    return &TreeNode{TreeNode: value}}
要查找二叉树中的节点,可以使用递归或迭代的方法进行查找。
package mainimport (	"fmt")type TreeNode struct {	Value  int	Left   *TreeNode	Right  *TreeNode}// 在二叉树中查找指定值的节点(递归方式)func FindNode(root *TreeNode, target int) *TreeNode {	if root == nil {		return nil // 如果树为空,则返回nil	}	if root.Value == target {		return root // 如果找到目标值,返回该节点	}	// 递归在左子树中查找	leftResult := FindNode(root.Left, target)	if leftResult != nil {		return leftResult	}	// 递归在右子树中查找	rightResult := FindNode(root.Right, target)	if rightResult != nil {		return rightResult	}	return nil // 如果左右子树都没有找到目标值,则返回nil}func main() {	// 创建一个示例二叉树	root := &TreeNode{		Value: 10,		Left: &TreeNode{			Value: 5,			Left: &TreeNode{				Value: 3,				Left:  nil,				Right: nil,			},			Right: &TreeNode{				Value: 7,				Left:  nil,				Right: nil,			},		},		Right: &TreeNode{			Value: 15,			Left: &TreeNode{				Value: 12,				Left:  nil,				Right: nil,			},			Right: &TreeNode{				Value: 18,				Left:  nil,				Right: nil,			},		},	}	// 查找值为12的节点	targetValue := 12	foundNode := FindNode(root, targetValue)	if foundNode != nil {		fmt.Printf("找到节点值为%d的节点\n", targetValue)	} else {		fmt.Printf("未找到节点值为%d的节点\n", targetValue)	}}
节点的插入
package mainimport (	"fmt")// TreeNode 表示二叉树节点的结构type TreeNode struct {	Val   int	Left  *TreeNode	Right *TreeNode}// InsertNode 插入一个新节点到二叉搜索树func InsertNode(root *TreeNode, val int) *TreeNode {	// 如果树为空,直接创建一个新节点作为根	if root == nil {		return &TreeNode{Val: val}	}	// 如果值小于当前节点的值,则插入左子树	if val < root.Val {		root.Left = InsertNode(root.Left, val)	} else if val > root.Val { // 如果值大于当前节点的值,则插入右子树		root.Right = InsertNode(root.Right, val)	}	return root}// 中序遍历二叉树(用于验证插入操作)func InOrderTraversal(root *TreeNode) {	if root == nil {		return	}	InOrderTraversal(root.Left)	fmt.Printf("%d ", root.Val)	InOrderTraversal(root.Right)}func main() {	// 创建一个简单的二叉搜索树	root := &TreeNode{Val: 10}	root = InsertNode(root, 5)	root = InsertNode(root, 15)	root = InsertNode(root, 3)	root = InsertNode(root, 7)	// 执行中序遍历,验证插入操作	fmt.Println("中序遍历结果:")	InOrderTraversal(root)}
节点的删除
package mainimport (	"fmt")// TreeNode 表示二叉树节点的结构type TreeNode struct {	Val   int	Left  *TreeNode	Right *TreeNode}// FindMinNode 找到二叉搜索树中最小的节点func FindMinNode(root *TreeNode) *TreeNode {	for root.Left != nil {		root = root.Left	}	return root}// DeleteNode 从二叉搜索树中删除节点func DeleteNode(root *TreeNode, key int) *TreeNode {	if root == nil {		return root	}	// 遍历树来找到要删除的节点	if key < root.Val {		root.Left = DeleteNode(root.Left, key)	} else if key > root.Val {		root.Right = DeleteNode(root.Right, key)	} else {		// 找到了要删除的节点		// 如果节点只有一个子节点或没有子节点		if root.Left == nil {			return root.Right		} else if root.Right == nil {			return root.Left		}		// 如果节点有两个子节点,找到右子树中的最小节点来替代当前节点		temp := FindMinNode(root.Right)		root.Val = temp.Val		root.Right = DeleteNode(root.Right, temp.Val)	}	return root}// 中序遍历二叉树(用于验证删除操作)func InOrderTraversal(root *TreeNode) {	if root == nil {		return	}	InOrderTraversal(root.Left)	fmt.Printf("%d ", root.Val)	InOrderTraversal(root.Right)}func main() {	// 创建一个简单的二叉搜索树	root := &TreeNode{Val: 10}	root.Left = &TreeNode{Val: 5}	root.Right = &TreeNode{Val: 15}	root.Left.Left = &TreeNode{Val: 3}	root.Left.Right = &TreeNode{Val: 7}	// 删除值为5的节点	keyToDelete := 5	root = DeleteNode(root, keyToDelete)	// 执行中序遍历,验证删除操作	fmt.Println("中序遍历结果:")	InOrderTraversal(root)}

标签: #java数组转化为二叉树 #计算二叉树高度的算法是什么