Консультация № 169664
20.06.2009, 20:52
0.00 руб.
0 16 1
Доброго времени суток уважаемые эксперты. У меня такая проблема, мне необходимо вычислить максимальную глубину бинарного дерева. Само дерево и его визуализацию сделал а как глубину считать не знаю, помогите пожайлуста!

Обсуждение

Неизвестный
21.06.2009, 03:43
общий
это ответ
Здравствуйте, Ryufuz.

Рекурсивным обходом всего дерева. Иначе - только храня в каждом узле его глубину. И обновляя родителей при каждом добавении/удалении узла.

Приложение:
Function MaxDepth(N As Node) As Integer
Dim D1 As Integer, D2 As Integer

If Not N.Left Is Nothing Then
D1 = MaxDepth(N.Left)
End If

If Not N.Right Is Nothing Then
D2 = MaxDepth(N.Right)
End If

MaxDepth = IIf(D1 > D2, D1 + 1, D2 + 1)
End Function
5
Огромное спасибо за проделанный труд=)))
Неизвестный
21.06.2009, 03:55
общий
Можно еще ее хранить в объекте дерева. Если нужна только она. При обновлениях менять будет легко. Но полностью пересчитывать все равно придется при удалении самого глубокого элемента.
Неизвестный
21.06.2009, 14:50
общий
К сожалению возникли трудности (использую VB6) при попытке реализовать условие
If Not (t.LeftChild Is Nothing) Then
выдаёт ошибку 91

пытался соорудить нечто своё но ничего не вышло.... сейчас обход выглядит так(ошибок не выдаёт, но работать нехочет(((((

Private Sub Obhod(t As SortNode, s As Integer)
Dim tl As SortNode
Dim tr As SortNode
Dim d1 As Integer
Dim d2 As Integer
If Not (t Is Nothing) Then
Set tl = t.LeftChild
Set tr = t.RightChild
Obhod tl, d1
Obhod tr, d2
s = IIf(d1 > d2, d1 + 1, d2 + 1)
End If
End Sub
Неизвестный
21.06.2009, 18:43
общий
У меня нормально отрабатывает. Вот недостающие части. Класс Node:
Код:
Option Explicit
Public Left As Node
Public Right As Node


И загрузка формы:
Код:
Private Sub Form_Load()
Dim N As New Node
Set N.Left = New Node
Set N.Right = New Node
Set N.Right.Left = New Node

MsgBox MaxDepth(N)
End Sub


Показывает 3.
Если реализация дерева совсем другая - покажите свою, надо будет к ней приспособить.
Неизвестный
21.06.2009, 18:49
общий
В Вашем коде значение s копируется в функцию. И функция работает уже с копией, так что результат Вы не получаете. Надо либо объявить передачу s по ссылке (byref s as integer), либо писать функцию как у меня. Функция в данном случае красивше.Процедуры с такими параметрами делают только если надо вернуть несколько параметров.
Неизвестный
22.06.2009, 17:17
общий
Спасибо, прога начинает оживать ..... только она что не введи показывает что глубина 3
Неизвестный
22.06.2009, 19:19
общий
Дерево у меня создается в Sub Form_Load(). Если добавить строчку
Set N.Right.Left.Left = New Node
, то покажет 4.
Неизвестный
23.06.2009, 11:00
общий
не ну это то понятно, мне просто хотелось всётаки что б отбражалась реальная глубина заданного дерева=(
Неизвестный
23.06.2009, 11:35
общий
Ryufuz:
Так это и есть реальная глубина. Глубина дерева - глубина самого дальнего потомка. Если глубину корня считать за 0, а не 1, то надо вычесть из результата 1. Тут глубина действительно на 1 больше, чем во многих учебниках. Или добавлять единицу не в конце, а тут:
If Not N.Left Is Nothing Then
D1 = MaxDepth(N.Left) + 1
End If
Неизвестный
23.06.2009, 11:52
общий
хм странно я чето думал что глубина пустого дерева = 0 а не 3м
Неизвестный
23.06.2009, 12:02
общий
Ryufuz:
Так это значит функции передается то дерево, которое я нарисовал, а не рабочее. Код покажите. Как дерево реализованно, и где моя функция запускается.
Неизвестный
23.06.2009, 12:46
общий
Ну собственно вот это детище))




Const XGAP = 60
Const YGAP = 120

Dim Wid As Single
Dim Hgt As Single


Dim Root As SortNode


Dim MaxBox As Integer



Private Sub InsertItem(node As SortNode, new_value As Integer)
Dim child As SortNode

If node Is Nothing Then

Set node = New SortNode
node.Value = new_value
MaxBox = MaxBox + 1
Load NodeLabel(MaxBox)
Set node.Box = NodeLabel(MaxBox)
With NodeLabel(MaxBox)
.Caption = Format$(new_value)
.Visible = True
End With
ElseIf new_value <= node.Value Then
' Branch left.
Set child = node.LeftChild
InsertItem child, new_value
Set node.LeftChild = child
Else
' Branch right.
Set child = node.RightChild
InsertItem child, new_value
Set node.RightChild = child
End If
End Sub

Private Sub DeleteItem(node As SortNode, target_value As Integer)
Dim target As SortNode
Dim child As SortNode
If node Is Nothing Then
Beep
MsgBox "Item " & Format$(target_value) & _
" is not in the tree."
Exit Sub
End If

If target_value < node.Value Then

Set child = node.LeftChild
DeleteItem child, target_value
Set node.LeftChild = child
ElseIf target_value > node.Value Then

Set child = node.RightChild
DeleteItem child, target_value
Set node.RightChild = child
Else
' This is the target.
Set target = node
If target.LeftChild Is Nothing Then
' Replace target with its right child.
Set node = node.RightChild
ElseIf target.RightChild Is Nothing Then
' Replace target with its left child.
Set node = node.LeftChild
Else
'
Set child = node.LeftChild
ReplaceRightmost node, child
Set node.LeftChild = child
End If
End If
End Sub


Private Sub ReplaceRightmost(target As SortNode, repl As SortNode)
Dim old_repl As SortNode
Dim child As SortNode

If Not (repl.RightChild Is Nothing) Then
' Move farther down to the right.
Set child = repl.RightChild
ReplaceRightmost target, child
Set repl.RightChild = child
Else

Set old_repl = repl


Set repl = repl.LeftChild


Set old_repl.LeftChild = target.LeftChild
Set old_repl.RightChild = target.RightChild
Set target = old_repl
End If
End Sub

Private Sub CmdAdd_Click()
Dim new_value As Integer
Dim g As Integer

new_value = CInt(ValueText.Text)
InsertItem Root, new_value
DisplayTree
ValueText.Text = ""
ValueText.SetFocus
End Sub

Private Sub CmdRemove_Click()
Dim target_value As Integer

target_value = CInt(ValueText.Text)
DeleteItem Root, target_value
11
ValueText.Text = ""
ValueText.SetFocus
End Sub


Private Sub DisplayNode(node As SortNode, xmin As Single, ByVal y As Single)
Dim x1 As Single
Dim y1 As Single
Dim child As SortNode

If node Is Nothing Then Exit Sub


y1 = y + Hgt + YGAP
x1 = xmin
Set child = node.LeftChild
If child Is Nothing Then
x1 = x1 + Wid
Else
DisplayNode child, x1, y1
End If

Set child = node.RightChild
If child Is Nothing Then
If Not (node.LeftChild Is Nothing) _
Then x1 = x1 + Wid + XGAP
Else
x1 = x1 + XGAP
DisplayNode child, x1, y1
End If


node.Box.Move (xmin + x1) / 2 - Wid / 2, y
node.Box.Visible = True
xmin = x1
End Sub


Private Sub DisplayTree()
Dim xmin As Single

xmin = 0
DisplayNode Root, xmin, NodeLabel(0).Top
Refresh
End Sub


Private Sub DrawLines(node As SortNode)
Dim x As Single
Dim y As Single
Dim child As SortNode

If node Is Nothing Then Exit Sub

x = node.Box.Left + node.Box.Width / 2
y = node.Box.Top + node.Box.Height / 2

DrawLines node.LeftChild
DrawLines node.RightChild


Set child = node.LeftChild
If Not (child Is Nothing) Then _
Line (x, y)- _
(child.Box.Left + child.Box.Width / 2, _
child.Box.Top + child.Box.Height / 2)

Set child = node.RightChild
If Not (child Is Nothing) Then _
Line (x, y)-( _
child.Box.Left + child.Box.Width / 2, _
child.Box.Top + child.Box.Height / 2)
End Sub
Function MaxDepth(t As SortNode) As Integer
Dim D1 As Integer, D2 As Integer

If Not t.LeftChild Is Nothing Then
D1 = MaxDepth(t.LeftChild)
End If

If Not t.RightChild Is Nothing Then
D2 = MaxDepth(t.RightChild)
End If

MaxDepth = IIf(D1 > D2, D1 + 1, D2 + 1)
End Function


Private Sub Command1_Click()
Dim t As New SortNode
Set t.LeftChild = New SortNode
Set t.RightChild = New SortNode
Set t.RightChild.LeftChild = New SortNode

MsgBox MaxDepth(t)
End Sub

Private Sub Form_Load()
Wid = NodeLabel(0).Width
Hgt = NodeLabel(0).Height

DisplayTree
End Sub

Private Sub Form_Paint()
DrawLines Root
End Sub


Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Set Root = Nothing
Unload Me
End Sub

Private Sub mnuFileExit_Click()
Set Root = Nothing
Unload Me
End Sub

Private Sub mnuHelpAbout_Click()
Dim txt As String

txt = "This program allows you to manipulate a sorted binary tree." & vbCrLf & vbCrLf
txt = txt & "Enter a number and click the Add button to add an item to the tree." & vbCrLf & vbCrLf
txt = txt & "Enter a number and click the Remove button to remove an item from the tree."

MsgBox txt, vbOKOnly, "Help About ... Treesort"
End Sub

Private Sub ValueText_Change()
CmdAdd.Enabled = (ValueText.Text <> "")
CmdRemove.Enabled = CmdAdd.Enabled
End Sub





и вот класс:


Option Explicit

Public LeftChild As SortNode
Public RightChild As SortNode
Public Value As Integer
Public inf As Integer
Public z_next As SortNode
Public Box As Label

Public Function DeleteDescendant(target As SortNode) As Boolean
If LeftChild Is target Then
Set LeftChild = Nothing
DeleteDescendant = True
Exit Function
End If
If RightChild Is target Then
Set RightChild = Nothing
DeleteDescendant = True
Exit Function
End If

If Not (LeftChild Is Nothing) Then
If LeftChild.DeleteDescendant(target) Then
DeleteDescendant = True
Exit Function
End If
End If
If Not (RightChild Is Nothing) Then
If RightChild.DeleteDescendant(target) Then
DeleteDescendant = True
Exit Function
End If
End If
End Function

Public Function FindNode(ctl As Label) As SortNode
Dim node As SortNode


If ctl = Box Then
Set FindNode = Me
Exit Function
End If


If Not LeftChild Is Nothing Then
Set node = LeftChild.FindNode(ctl)
If Not (node Is Nothing) Then
Set FindNode = node
Exit Function
End If
End If


If Not (RightChild Is Nothing) Then
Set node = RightChild.FindNode(ctl)
If Not (node Is Nothing) Then
Set FindNode = node
Exit Function
End If
End If

Set FindNode = Nothing
End Function


'Private Sub Class_Terminate()
' Unload Box
'End Sub

Неизвестный
23.06.2009, 14:36
общий
Ryufuz:
Я вижу только ее использование в Command1_Click. Там создается дерево, и передается этой функции. Если нужно показать глубину дерева Root, то Root и надо передавать. :)
Судя по названию, дерево должно быть отсортированным. Тогда в классе узла надо этим пользоваться. Сейчас просто тупо обегается все дерево.
В таких конструкциях желательно искать не узел, а ключ. Если дерево отсортированно по Value, то его и надо передавать, а не узел.

Мне не совсем ясна судьба добавляемых узлов дерева в процедуре "Private Sub InsertItem(node As SortNode, new_value As Integer)". Навскидку кажется, что создается узел, для него создается контрол, но в дерево узел не добавится. Попробуйте тогда написать byref node as sortnode.

Set child = node.RightChild
InsertItem child, new_value
Set node.RightChild = child
Проще записать как
InsertItem node.RightChild, new_value

Да и вообще, передача в такие процедуры Nothing... Не красиво так. Надо решать на шаг раньше. Чтобы параметрами были только объекты.

Поскольку там используются контролы, я у себя это дело запустить не смогу. В VB нужны все файлы формы.
Неизвестный
23.06.2009, 23:40
общий
делов том что если заменить на InsertItem node.RightChild, new_value то в вводе элементов на поле отображается только первый элемент(((

мдя сегодня на меня препад смотрела с глазами на выкат...... оказалось, что дерево по условию было ПОЛНЫМ и достаточно было посчитать в k количество элементов а дальше по формуле

k = k + 1
k = k ^ (1 / 2)
MsgBox (k)

я плакаль


ну все равно спасибо за помощь, извиняюсь за зря потраченное время)))
Неизвестный
27.06.2009, 01:48
общий
Почему же зря? Учебные задания не для оценки даются, а для такого ковыряния. Наоборот полезней. :)
Неизвестный
02.07.2009, 00:48
общий
не ну ну я не спорю... после такого я в деревьях шарю как ни знаю кто=))) просто шо моя невнимательность меня же в очередной и подвела)))))))
Форма ответа