Arbre binaire (1) -overview (avec implémentation d'arbre de recherche binaire)

Les arbres et les graphiques sont des structures de données non linéaires typiques

Définition de l'
arbre : Un arbre est un ensemble fini de n (n> = 0) nœuds. Lorsque n = 0, il devient un arbre vide. Dans tout arbre non vide, il présente les caractéristiques suivantes:

  1. Un seul nœud spécifique devient le nœud racine
  2. Lorsque n> 1, les nœuds restants peuvent être divisés en m (m> 0) ensembles finis non pertinents. Chaque ensemble est également un arbre et devient un sous-arbre de la racine.
树的最大层级数,称为树的高度或者深度

La définition d'un
arbre binaire : un arbre binaire fait référence à该树的每个节点最多有2个子节点,有可能时两个,也可能只有1个,或者是没有

Deux formes spéciales d'arbres binaires:

满二叉树:一个二叉树的所有非叶子节点都存在左孩子和右孩子,并且所有叶子节点都在同一层级上,这个树就是满二叉树
完全二叉树:一个二叉树的`最后一个节点之前`所有非叶子节点都存在左孩子和右孩子,并且所有叶子节点都在同一层级上

La structure de stockage physique de l'arbre binaire

1. Structure de stockage en chaîne

En utilisant la structure de stockage de la liste chaînée, chaque nœud de l'arborescence binaire contient 3 parties

  • Variable de données pour stocker des données
  • Pointeur gauche vers l'enfant gauche
  • Pointeur droit vers le bon enfant

2. Tableau

Lors de l'utilisation du stockage en matrice, les nœuds de l'arborescence binaire sont placés aux positions correspondantes dans le tableau selon l'ordre hiérarchique. Si l'enfant gauche ou droit d'un nœud est vacant, la position correspondante du tableau est également vide

Pourquoi est-il conçu comme ça? Parce que cela peut facilement localiser les nœuds enfants et les nœuds parents de l'arborescence binaire dans le tableau

En supposant que l'indice d'un nœud parent est parent, l'indice de son nœud enfant gauche est 2 parent + 1, et l'indice du nœud enfant droit est 2 parent + 2.

à son tour. Supposons que l'indice d'un nœud enfant gauche est leftchild, alors son indice de nœud parent est (leftchild-1) / 2

显然,对于一个稀疏的二叉树来说,用数组表示法是非常浪费空间的。
然而因为完全二叉树的特殊性,用数组来存储是非常合适的,比如二叉堆,一种特殊的完全二叉树

Application de l'arbre binaire

Il existe de nombreuses formes d'arbres binaires, en plus des arbres binaires généraux, à partir des arbres binaires complets mentionnés ci-dessus, des arbres binaires complets et des tas binaires, etc.

Alors, quelles sont les fonctions de tant de types d'arbres binaires?

  1. Utilisé pour les opérations de recherche
  2. Maintenir l'ordre relatif entre les éléments

Arbre de recherche binaire

Également connu sous le nom d'arbre de tri binaire, d'arbre de recherche binaire, etc. Comme son nom l'indique, les éléments de cet arbre binaire ont un certain ordre et sont faciles à trouver

définition:

  1. Si le sous-arbre de gauche n'est pas vide, alors左子树上所有节点的值均小于根节点的值
  2. Si le bon sous-arbre n'est pas vide, alors右子树上所有节点的值均大于根节点的值
  3. Le sous-arbre de gauche et le sous-arbre de droite sont également des arbres de recherche binaires
  4. 没有键值相等的结点

Ici, nous utilisons la définition 1. Il existe trois définitions ( arbre de recherche binaire Encyclopédie Baidu ) qui sont correctes et doivent être sélectionnées en fonction des différents besoins lors du développement.

Golang implémente un arbre de recherche binaire:

package main

import "fmt"

// 二叉树
type BinaryTree struct {
    
    
	HeadNode *TreeNode
}

//二叉树节点
type TreeNode struct {
    
    
	Data   int32     // 链表上的数据
	Left   *TreeNode // 指针指向左孩子节点
	Right  *TreeNode // 指针指向右孩子节点
}

// 判断二叉树是否为空树,只需要判断第一个元素是否是 nil
func (self *BinaryTree) IsEmpty() bool {
    
    
	if self.HeadNode == nil {
    
    
		return true
	} else {
    
    
		return false
	}
}

// 在二叉查找树里添加数据
func (self *BinaryTree) Add(value int32) bool {
    
    
	neWNode := &TreeNode{
    
    Data: value,}
	node := self.HeadNode
	if node == nil {
    
    
		self.HeadNode = neWNode
		return true
	}
	for node.Data!=value {
    
    
		if value < node.Data {
    
    
			if node.Left!=nil{
    
    
				node = node.Left
			}else {
    
    
				node.Left=neWNode
				return true
			}
		}
		if value > node.Data {
    
    
			if  node.Right!=nil{
    
    
				node = node.Right
			}else {
    
    
				node.Right=neWNode
				return true
			}
		}
	}
	return false
}

// 查找元素所在的节点
func (self *BinaryTree) Get(value int32) *TreeNode {
    
    
	node := self.HeadNode
	for node != nil {
    
    
		if value < node.Data {
    
    
			node = node.Left
		} else if value > node.Data {
    
    
			node = node.Right
		} else {
    
    
			return node
		}
	}
	return nil
}

func NewBinaryTree() BinaryTree {
    
    
	BinaryTree := BinaryTree{
    
    HeadNode: nil}
	return BinaryTree
}

func main() {
    
    
	binaryTree := NewBinaryTree()
	fmt.Println(binaryTree.IsEmpty())
	fmt.Println(binaryTree.Add(3))
	fmt.Println(binaryTree.Add(3))
	fmt.Println(binaryTree.Add(2))
	fmt.Println(binaryTree.Add(4))
	fmt.Println(binaryTree.HeadNode.Data)
	fmt.Println(binaryTree.HeadNode.Right.Data)
	fmt.Println(binaryTree.HeadNode.Left.Data)
	fmt.Println(binaryTree.Get(4).Data)
	fmt.Println(binaryTree.IsEmpty())
}

Complexité temporelle de l'arbre de recherche binaire:

Pour un arbre de recherche binaire avec une distribution de nœuds relativement équilibrée, si le nombre total de nœuds est n, la complexité temporelle de la recherche de nœuds est O (logn), ce qui correspond à la profondeur de l'arbre.
Cette méthode de recherche étape par étape en comparant la taille est très similaire à l'algorithme de recherche binaire

Mais pour les cas extrêmes (la taille des données est augmentée ou diminuée à chaque fois que les données sont insérées), il n'y a que la moitié de l'arbre en apparence, et la complexité du temps de recherche sera réduite à O (n)

Pour résoudre ce problème, il s'agit de l'auto-équilibrage de l'arbre binaire, qui sera présenté plus tard.

Je suppose que tu aimes

Origine blog.csdn.net/csdniter/article/details/109788469
conseillé
Classement