2019-07-17 22:01:31 +08:00
|
|
|
|
#Region "Microsoft.VisualBasic::81eec77cd0117693bed3fa2054025986, ComponentModel\Algorithm\BinaryTree\AVLTree.vb"
|
2018-11-08 20:21:25 +08:00
|
|
|
|
|
|
|
|
|
|
' Author:
|
|
|
|
|
|
'
|
|
|
|
|
|
' asuka (amethyst.asuka@gcmodeller.org)
|
|
|
|
|
|
' xie (genetics@smrucc.org)
|
|
|
|
|
|
' xieguigang (xie.guigang@live.com)
|
|
|
|
|
|
'
|
|
|
|
|
|
' Copyright (c) 2018 GPL3 Licensed
|
|
|
|
|
|
'
|
|
|
|
|
|
'
|
|
|
|
|
|
' GNU GENERAL PUBLIC LICENSE (GPL3)
|
|
|
|
|
|
'
|
|
|
|
|
|
'
|
|
|
|
|
|
' This program is free software: you can redistribute it and/or modify
|
|
|
|
|
|
' it under the terms of the GNU General Public License as published by
|
|
|
|
|
|
' the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
|
' (at your option) any later version.
|
|
|
|
|
|
'
|
|
|
|
|
|
' This program is distributed in the hope that it will be useful,
|
|
|
|
|
|
' but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
|
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
|
' GNU General Public License for more details.
|
|
|
|
|
|
'
|
|
|
|
|
|
' You should have received a copy of the GNU General Public License
|
|
|
|
|
|
' along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
' /********************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
' Summaries:
|
|
|
|
|
|
|
|
|
|
|
|
' Class AVLTree
|
|
|
|
|
|
'
|
2019-05-06 18:27:46 +08:00
|
|
|
|
' Constructor: (+2 Overloads) Sub New
|
2018-11-08 20:21:25 +08:00
|
|
|
|
'
|
2019-05-06 18:27:46 +08:00
|
|
|
|
' Function: Add, Find, Remove
|
2018-11-08 20:21:25 +08:00
|
|
|
|
'
|
|
|
|
|
|
' Sub: Add, appendLeft, appendRight, Remove, removeCurrent
|
|
|
|
|
|
' removeLeft, removeRight
|
|
|
|
|
|
'
|
|
|
|
|
|
'
|
|
|
|
|
|
' /********************************************************************************/
|
2018-08-02 20:14:48 +08:00
|
|
|
|
|
|
|
|
|
|
#End Region
|
|
|
|
|
|
|
|
|
|
|
|
Imports System.Runtime.CompilerServices
|
|
|
|
|
|
|
|
|
|
|
|
Namespace ComponentModel.Algorithm.BinaryTree
|
|
|
|
|
|
|
|
|
|
|
|
''' <summary>
|
|
|
|
|
|
''' The AVL binary tree operator.
|
|
|
|
|
|
''' </summary>
|
|
|
|
|
|
''' <typeparam name="K"></typeparam>
|
|
|
|
|
|
''' <typeparam name="V"></typeparam>
|
|
|
|
|
|
''' <remarks>
|
|
|
|
|
|
''' http://www.cnblogs.com/huangxincheng/archive/2012/07/22/2603956.html
|
|
|
|
|
|
''' </remarks>
|
2018-10-31 20:48:01 +08:00
|
|
|
|
Public Class AVLTree(Of K, V) : Inherits TreeBase(Of K, V)
|
2018-08-02 20:14:48 +08:00
|
|
|
|
|
2018-10-31 21:33:26 +08:00
|
|
|
|
''' <summary>
|
|
|
|
|
|
''' Create an instance of the AVL binary tree.
|
|
|
|
|
|
''' </summary>
|
2019-03-15 18:19:37 +08:00
|
|
|
|
''' <param name="compares">
|
|
|
|
|
|
''' Compare between two keys. This comparison function should returns:
|
|
|
|
|
|
'''
|
|
|
|
|
|
''' + 0, means two keys are equals.
|
|
|
|
|
|
''' + 1, means a is greater than b.
|
|
|
|
|
|
''' + -1, means a is smaller than b.
|
|
|
|
|
|
''' </param>
|
2018-10-31 21:33:26 +08:00
|
|
|
|
''' <param name="views">Display the key as string</param>
|
|
|
|
|
|
Sub New(compares As Comparison(Of K), Optional views As Func(Of K, String) = Nothing)
|
2018-10-31 20:48:01 +08:00
|
|
|
|
MyBase.New(compares, views)
|
2018-08-02 20:14:48 +08:00
|
|
|
|
End Sub
|
|
|
|
|
|
|
2019-04-08 19:41:19 +08:00
|
|
|
|
Sub New(compares As IComparer(Of K), Optional views As Func(Of K, String) = Nothing)
|
|
|
|
|
|
MyBase.New(AddressOf compares.Compare, views)
|
|
|
|
|
|
End Sub
|
|
|
|
|
|
|
2018-08-02 20:14:48 +08:00
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
|
|
|
|
Public Sub Add(key As K, value As V, Optional valueReplace As Boolean = True)
|
|
|
|
|
|
_root = Add(key, value, _root, valueReplace)
|
|
|
|
|
|
End Sub
|
|
|
|
|
|
|
|
|
|
|
|
Public Function Add(key As K, value As V, tree As BinaryTree(Of K, V), valueReplace As Boolean) As BinaryTree(Of K, V)
|
|
|
|
|
|
If tree Is Nothing Then
|
2018-10-31 20:40:37 +08:00
|
|
|
|
' 追加新的叶子节点
|
2018-10-31 21:33:26 +08:00
|
|
|
|
tree = New BinaryTree(Of K, V)(key, value, Nothing, views)
|
2018-10-31 20:40:37 +08:00
|
|
|
|
stack.Add(tree)
|
2019-03-15 18:19:37 +08:00
|
|
|
|
Else
|
|
|
|
|
|
Select Case compares(key, tree.Key)
|
|
|
|
|
|
Case < 0 : Call appendLeft(tree, key, value, valueReplace)
|
|
|
|
|
|
Case > 0 : Call appendRight(tree, key, value, valueReplace)
|
|
|
|
|
|
Case = 0
|
|
|
|
|
|
|
|
|
|
|
|
' 将value追加到附加值中(也可对应重复元素)
|
|
|
|
|
|
If valueReplace Then
|
|
|
|
|
|
tree.Value = value
|
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
|
|
' 2018.3.6
|
|
|
|
|
|
' 如果是需要使用二叉树进行聚类操作,那么等于零的值可能都是同一个簇之中的
|
|
|
|
|
|
' 在这里将这个member添加进来
|
|
|
|
|
|
Call DirectCast(tree!values, List(Of V)).Add(value)
|
|
|
|
|
|
|
|
|
|
|
|
Case Else
|
|
|
|
|
|
' This will never happend!
|
|
|
|
|
|
Throw New Exception("????")
|
|
|
|
|
|
End Select
|
2018-08-02 20:14:48 +08:00
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
|
|
tree.PutHeight
|
|
|
|
|
|
|
|
|
|
|
|
Return tree
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
Private Sub appendRight(ByRef tree As BinaryTree(Of K, V), key As K, value As V, replace As Boolean)
|
|
|
|
|
|
tree.Right = Add(key, value, tree.Right, replace)
|
|
|
|
|
|
|
|
|
|
|
|
If tree.Right.height - tree.Left.height = 2 Then
|
|
|
|
|
|
If compares(key, tree.Right.Key) > 0 Then
|
|
|
|
|
|
tree = tree.RotateRR
|
|
|
|
|
|
Else
|
|
|
|
|
|
tree = tree.RotateRL
|
|
|
|
|
|
End If
|
|
|
|
|
|
End If
|
|
|
|
|
|
End Sub
|
|
|
|
|
|
|
|
|
|
|
|
Private Sub appendLeft(ByRef tree As BinaryTree(Of K, V), key As K, value As V, replace As Boolean)
|
|
|
|
|
|
tree.Left = Add(key, value, tree.Left, replace)
|
|
|
|
|
|
|
|
|
|
|
|
If tree.Left.height - tree.Right.height = 2 Then
|
|
|
|
|
|
If compares(key, tree.Left.Key) < 0 Then
|
|
|
|
|
|
tree = tree.RotateLL
|
|
|
|
|
|
Else
|
|
|
|
|
|
tree = tree.RotateLR
|
|
|
|
|
|
End If
|
|
|
|
|
|
End If
|
|
|
|
|
|
End Sub
|
|
|
|
|
|
|
2019-04-23 20:31:20 +08:00
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
|
|
|
|
Public Function Find(term As K) As BinaryTree(Of K, V)
|
|
|
|
|
|
Return root.Find(key:=term, compares:=compares)
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
2018-08-02 20:14:48 +08:00
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
|
|
|
|
Public Sub Remove(key As K)
|
|
|
|
|
|
_root = Remove(key, _root)
|
|
|
|
|
|
End Sub
|
|
|
|
|
|
|
|
|
|
|
|
Public Function Remove(key As K, tree As BinaryTree(Of K, V)) As BinaryTree(Of K, V)
|
|
|
|
|
|
If tree Is Nothing Then
|
|
|
|
|
|
Return Nothing
|
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
|
|
Select Case compares(key, tree.Key)
|
|
|
|
|
|
Case < 0 : Call removeLeft(tree, key)
|
|
|
|
|
|
Case > 0 : Call removeRight(tree, key)
|
|
|
|
|
|
Case = 0 : Call removeCurrent(tree)
|
|
|
|
|
|
Case Else
|
|
|
|
|
|
' This will never happed!
|
|
|
|
|
|
Throw New Exception("This will never happed!")
|
|
|
|
|
|
End Select
|
|
|
|
|
|
|
|
|
|
|
|
If Not tree Is Nothing Then
|
|
|
|
|
|
Call tree.PutHeight
|
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
|
|
Return tree
|
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
|
|
Private Sub removeLeft(ByRef tree As BinaryTree(Of K, V), key As K)
|
|
|
|
|
|
tree.Left = Remove(key, tree.Left)
|
|
|
|
|
|
|
|
|
|
|
|
If tree.Left.height - tree.Right.height = 2 Then
|
|
|
|
|
|
If compares(key, tree.Left.Key) < 0 Then
|
|
|
|
|
|
tree = tree.RotateLL
|
|
|
|
|
|
Else
|
|
|
|
|
|
tree = tree.RotateLR
|
|
|
|
|
|
End If
|
|
|
|
|
|
End If
|
|
|
|
|
|
End Sub
|
|
|
|
|
|
|
|
|
|
|
|
Private Sub removeRight(ByRef tree As BinaryTree(Of K, V), key As K)
|
|
|
|
|
|
tree.Right = Remove(key, tree.Right)
|
|
|
|
|
|
|
|
|
|
|
|
If tree.Right.height - tree.Left.height = 2 Then
|
|
|
|
|
|
If compares(key, tree.Right.Key) > 0 Then
|
|
|
|
|
|
tree = tree.RotateRR
|
|
|
|
|
|
Else
|
|
|
|
|
|
tree = tree.RotateRL
|
|
|
|
|
|
End If
|
|
|
|
|
|
End If
|
|
|
|
|
|
End Sub
|
|
|
|
|
|
|
|
|
|
|
|
Private Sub removeCurrent(ByRef tree As BinaryTree(Of K, V))
|
|
|
|
|
|
If Not tree.Left Is Nothing AndAlso Not tree.Right Is Nothing Then
|
|
|
|
|
|
|
|
|
|
|
|
tree = New BinaryTree(Of K, V)(tree.Right.MinKey, tree.Value) With {
|
|
|
|
|
|
.Left = tree.Left,
|
|
|
|
|
|
.Right = tree.Right
|
|
|
|
|
|
}
|
|
|
|
|
|
tree.Right = Remove(tree.Key, tree.Right)
|
|
|
|
|
|
|
|
|
|
|
|
Else
|
|
|
|
|
|
tree = If(tree.Left Is Nothing, tree.Right, tree.Left)
|
|
|
|
|
|
|
|
|
|
|
|
If tree Is Nothing Then
|
|
|
|
|
|
tree = Nothing
|
|
|
|
|
|
End If
|
|
|
|
|
|
End If
|
|
|
|
|
|
End Sub
|
|
|
|
|
|
End Class
|
|
|
|
|
|
End Namespace
|