vb.net - AVL树如何在插入时平衡树
问题描述
我想为 avl 树创建一个插入函数。但是插入函数必须是递归的并且必须是平衡的。
我有一种将树向左旋转 PivoterAGauche 的方法和一种将树向右旋转 PivoterADroite 的方法。
'Pivot left
Private Function PivoterAGauche(leNoeud As NoeudAVL) As NoeudAVL
If leNoeud Is Nothing Then
Return Nothing
ElseIf leNoeud.FilsDroit Is Nothing AndAlso leNoeud.FilsGauche Is Nothing Then
Return leNoeud
ElseIf leNoeud.FilsDroit Is Nothing Then
Return leNoeud
' ElseIf leNoeud.FilsGauche Is Nothing Then
Else 'Le leNoeud.FilsGauche existe.
Dim pivot As NoeudAVL = leNoeud.FilsGauche
leNoeud.FilsGauche = pivot.FilsDroit
pivot.FilsDroit = leNoeud
leNoeud = pivot
Return leNoeud
End If
End Function
'pivot rigth
Private Function PivoterADroite(leNoeud As NoeudAVL) As NoeudAVL
If leNoeud Is Nothing Then
Return Nothing
ElseIf leNoeud.FilsDroit Is Nothing AndAlso leNoeud.FilsGauche Is Nothing Then
Return leNoeud
ElseIf leNoeud.FilsDroit Is Nothing Then
Return leNoeud
' ElseIf leNoeud.FilsGauche Is Nothing Then
Else 'Le leNoeud.FilsGauche existe.
Dim pivot As NoeudAVL = leNoeud.FilsDroit
leNoeud.FilsDroit = pivot.FilsGauche
pivot.FilsGauche = leNoeud
leNoeud = pivot
Return leNoeud
End If
End Function
这是我做的插入方法。我很确定何时使用左右枢轴。
Private Function Inserer(leElement As T, leNoeudCourant As NoeudAVL) As NoeudAVL
Dim intBalance As Integer
'If the node does not existes
If leNoeudCourant Is Nothing Then
m_blnOperationOK = True
Return New NoeudAVL(leElement)
'If the node already existes.
ElseIf leElement.CompareTo(leNoeudCourant.Element) = 0 Then
m_blnOperationOK = False
Return leNoeudCourant
ElseIf leElement.CompareTo(leNoeudCourant.Element) < 0 Then
intBalance = Hauteur(leNoeudCourant.FilsGauche) - Hauteur(leNoeudCourant.FilsDroit)
If (intBalance = 2) Then
leNoeudCourant = PivoterAGauche(leNoeudCourant)
End If
leNoeudCourant.FilsGauche = Inserer(leElement, leNoeudCourant.FilsGauche)
ElseIf leElement.CompareTo(leNoeudCourant.Element) > 0 Then
intBalance = Hauteur(leNoeudCourant.FilsGauche) - Hauteur(leNoeudCourant.FilsDroit)
If (intBalance = 2) Then
leNoeudCourant = PivoterADroite(leNoeudCourant)
End If
leNoeudCourant.FilsDroit = Inserer(leElement, leNoeudCourant.FilsDroit)
End If
'Return current node that will become the root.
Return leNoeudCourant
如果您有更多问题,我很乐意回答您的问题,感谢您的帮助。
解决方案
让我们记住一些非常基本的事情:在像二叉树这样的任务中使用递归时,您的工作区是一个节点。这意味着这个节点必须拥有完成您希望它完成的任务所需的一切。
您必须了解,从它自己的角度来看,每个节点都是它自己树的根,有点像整个二叉树是由许多较小的二叉树组成的。O 节点知道它是孩子,但不知道它是祖先。
为了能够构建平衡的二叉树,您的节点必须能够“知道”这些事情:
- 它们的高度(它们下面有多少个节点)。
- 如果他们变得不平衡(当在当前评估的节点下,两个孩子的高度差都高于 1 级)。
这里的魔力是强大的:一旦正确实施,二叉树将始终保持平衡,而无需完全重新评估自身。这是大脑的大时间。
首先,让我们做高度的事情:
每个节点都必须有一个高度值。该值必须作为模态变量存储在节点类中。使其成为公共属性,因为节点的父节点必须能够访问它。
Private _height As Integer = 0
Public ReadOnly Property Height As Integer
Get
Return _height
End Get
End Property
当您插入第一个节点(根)时,它的高度为零。下面什么都没有。对于您创建的每个新节点都是如此。
当您插入另一个节点时,您通常会将要插入的值“赋予”到根并让递归发挥作用。现在在此操作期间还有其他事情要考虑:更新高度,并纠正平衡。
Private Function insert(ByVal key As Integer, Optional node As Node = Nothing, ) As Node
'if you are creating the root, node is nothing
If (node Is Nothing) Then
Return New Node(key)
End If
'creating new nodes when needed
If (key < node.key) Then
node.FilGauche = insert(key, node.FilGauche)
ElseIf (key > node.key) Then
node.FilDroit = insert(key, node.FilDroit)
Else
Return node
End If
're-evaluating height (accounting for null pointers) and then balancing the tree
node._height = (1 + max(If(node.FilGauche.Height IsNot Nothing, node.FilGauche.Height, 0), node.FilDroit.Height IsNot Nothing, node.FilDroit.Height))
Dim balance As Integer = If(node.FilGauche.Height IsNot Nothing, node.FilGauche.Height, 0) - If(node.FilDroit.Height IsNot Nothing, node.FilDroit.Height, 0)
' If this node becomes unbalanced, then there
' are 4 cases Left Left Case
If ((balance > 1) AndAlso (key < node.FilGauche.key)) Then
Return rightRotate(node)
End If
' Right Right Case
If ((balance < -1) AndAlso (key > node.FilDroit.key)) Then
Return leftRotate(node)
End If
' Left Right Case
If ((balance > 1) AndAlso (key > node.FilGauche.key)) Then
node.FilGauche = leftRotate(node.FilGauche)
Return rightRotate(node)
End If
' Right Left Case
If ((balance < -1) AndAlso (key < node.FilDroit.key)) Then
node.FilDroit = rightRotate(node.FilDroit)
Return leftRotate(node)
End If
Return node
End Function
当然,您必须根据您的具体情况调整这些想法,但这不是唯一的事情:我正在使用另一种语言的引用并在 IDE 之外工作,所以我必须直接在浏览器中输入,这意味着我可能在写这篇文章时犯了一些错误。让我知道这是否没有意义,我会仔细检查更好的条件。祝你好运!
推荐阅读
- c# - 如何将存储在 SSIS 变量中的结果集插入到 SQL Server 的表中?
- clojure - 如何将文件保存在服务器中?
- node.js - “错误”:当我运行我正在使用 MERN 堆栈的代码时,邮递员中的“访问被拒绝”
- reactjs - 是否可以在带有 pug 的 React 中使用 Framer Motion
- elixir - 如何在使用 Elixir/Phoenix 进行编辑期间使文件上传字段保持一致?
- git-bash - gitbash 更改默认目录
- excel - 在excel中一次打开选定列中的所有超链接
- python - tqdm 进度条之间的空间太宽
- wordpress - 多文件上传字段的 GravityForm 预览缩略图
- ruby-on-rails - 运行 hotwire:install 后,无法推送到 Heroku