Удалить в бинарном дереве поиска?

голоса
0

Я читаю через бинарное дерево удалить алгоритм узла , используемый в книге алгоритмы и структуры данных: Аннотированный Справочник с примерами

на странице 34, 4 случая (Удалить узел, который имеет как правую и левую суб деревьев), следуя алгоритму, описанному в книге выглядит не работает, я, возможно, может быть неправильно кто-то может мне помочь, что мне не хватает.

//Case 4
get largestValue from nodeToRemove.Left
FindParent(largestValue).Right <- 0
nodeToRemove.Value<-largestValue.Value

Как следующая строка удаляет наибольшее значение из суб дерева FindParent(largestValue).Right <- 0

Задан 29/06/2010 в 21:09
источник пользователем
На других языках...                            


5 ответов

голоса
1

Идея заключается в том, чтобы просто взять значение от самого большого узла на левой стороне и переместить его в узел, который удаляемого, то есть не удалить узел вообще, просто замените его содержимое. Затем чернослив из узла со значением перемещен в «Удаленные» узел. Это поддерживает порядок дерева со значением каждого узла больше, чем все это остались дети и меньше, чем все его права детей.

Ответил 29/06/2010 в 21:16
источник пользователем

голоса
1

Если я понимаю, псевдо-код, он работает и в общем случае, но не в «одном узле в левом поддереве» случае. Хорошо поймал.

Она эффективно заменяет node_to_remove с largest_value от его левого поддерева (также обнуляет старый узел largest_value).

Обратите внимание, что в BST, левое поддерево node_to_remove будет все меньше, чем node_to_remove. Право поддерево node_to_remove будет все больше node_to_remove. Так что если вы берете большой узел в левом поддереве, она сохранит инвариант.

Если это «один узел в поддереве случае», он будет уничтожить правое поддерево вместо этого. Lame :(

Как Vivin указывает, что также не прикрепить левый детей largestNode.

Ответил 29/06/2010 в 21:16
источник пользователем

голоса
6

При удалении узла с двумя детьми, вы можете либо выбрать его в заказе преемник узел или его упорядоченная узел предшественника. В этом случае это найти наибольшее значение в левом поддереве (означает, что самый правый ребенок своего левого поддерева), что означает, что он находит упорядоченную узел предшественника узла.

После того, как вы нашли узел замены, вы на самом деле не удалить узел , который необходимо удалить. Вместо того, чтобы взять значение из узла преемника и сохранять это значение в узле , который требуется удалить. Затем удалить узел преемника. При этом вы сохраняете свойства бинарного поиска дерева , так как вы можете быть уверены в том , что узел выбран будет иметь значение, которое ниже , чем значения всех детей в левом поддереве исходного узла, и больше , что , чем значения всех детей в правом поддереве исходного узла.

РЕДАКТИРОВАТЬ

После прочтения вашего вопроса немного больше, я думаю, что я нашел эту проблему.

Как правило , то , что у вас есть в дополнении к deleteфункции является replaceфункцией , которая заменяет данный узел. Я думаю , что вам нужно изменить эту строку кода:

FindParent(largestValue).Right <- 0

чтобы:

FindParent(largestValue).Right <- largestValue.Left

Если largestValueузел не имеет левого ребенка, вы просто получите nullили 0. Если у него есть левый ребенок, что ребенок становится заменой largestValueузла. Так что вы правы; код не учитывает ситуацию , что largestValueузел может иметь левую ребенка.

Другой EDIT

Так как вы только отправил фрагмент кода, я не уверен , что контекст кода. Но сниппет , как писал, похоже, есть проблемы вы предлагаете (заменяющий неправильный узел). Как правило, есть три случая, но я заметил , что комментарий в вашем фрагменте кода говорит //Case 4(так может быть , есть какой - то другой контекст).

Ранее я ссылался на то , что deleteобычно приходит с replace. Так что если вы нашли largestValueузел, вы удалите его в соответствии с двумя простых случаях (узел без детей, и узел с одним ребенком). Так что если вы смотрите на псевдо-код для удаления узла с двумя детьми, это то , что вы будете делать:

get largestValue from nodeToRemove.Left
nodeToRemove.Value <- largestValue.Value

//now replace largestValue with largestValue.Left    

if largestValue = largestValue.Parent.Left then   
   largestValue.Parent.Left <- largestValue.Left //is largestValue a left child?
else //largestValue must be a right child
   largestValue.Parent.Right <- largestValue.Left

if largestValue.Left is not null then
   largestValue.Left.Parent <- largestValue.Parent

Я нахожу это странным, что структуры данных и алгоритмы книга будет оставить эту часть, поэтому я склонен думать, что книга имеет дополнительно дробить удаление в несколько больше случаев (так как есть три стандартных случаев), чтобы сделать его проще Понимаю.

Для того, чтобы доказать, что приведенный выше код работает, рассмотрим следующее дерево:

  8
 / \
7   9

Давайте предположим , что вы хотите удалить 8. Вы пытаетесь найти largestValueиз nodeToRemove.Left. Это дает вам , 7так как левый суб-дерево имеет только одного ребенка.

Тогда вы делаете:

nodeToRemove.Value <- largestValue.Value

Что значит:

8.value <- 7.Value

или

8.Value <- 7

Так что теперь ваше дерево выглядит следующим образом:

  7
 / \
7   9

Вы должны избавиться от узла замены , и поэтому вы собираетесь заменить largestValueс largestValue.Left(что null). Итак , сначала вы выяснить , какой ребенок 7является:

if largestValue = largestValue.Parent.Left then

Что значит:

if 7 = 7.Parent.Left then

или:

if 7 = 8.Left then

Так 7İŞ 8левого ребенка «ы, необходимо заменить 8.Leftс 7.Right( largestValue.Parent.Left <- largestValue.Left). Так как 7не имеет детей, 7.Leftявляется недействительным. Таким образом , largestValue.Parent.Leftполучает назначение на нуль (который эффективно удаляет его левую ребенка). Таким образом , это означает , что вы в конечном итоге с помощью следующего дерева:

  7
   \
    9
Ответил 29/06/2010 в 21:17
источник пользователем

голоса
0

Это может иметь больше смысла , когда вы смотрите на Википедии взять на себя ту часть алгоритма:

Удаление узла с двумя детьми : Вызов узел должен быть удален «N». Не удаляйте N. Вместо этого выберите либо его упорядоченную узел преемника или его упорядоченную узел - предшественник, «R». Заменить значение N со значением R, а затем удалить R. (Примечание: сам R имеет до одного ребенка.)

Следует отметить, что данный алгоритм выбирает узел предшественника в-порядка.

Edit: что, как представляется, отсутствует вероятность того, что R (использовать терминологию Википедии) имеет одного ребенка. Рекурсивный удалить может работать лучше.

Ответил 29/06/2010 в 21:20
источник пользователем

голоса
1

Я думаю, что вам, возможно, потребуется уточнить, что не работает.

Я попытаюсь объяснить концепцию удаления в бинарном дереве в случае, если это помогает.

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

Когда мы удаляем узел, мы должны прикрепить его зависимые узлы.

то есть. Когда мы удаляем б нам нужно прикрепить узлы г и д.

Мы знаем, что левые узлы меньше правильные узлы в ценностях и что родительские узлы между левым и правым узел с в стоимости. В этом случае г <Ь и Ь <е. Это часть определения бинарного дерева.

Что немного менее очевидным является то, что е <а. Таким образом, это означает, что мы можем заменить б с е. Теперь мы вернули обратно е нам нужно прикрепить д.

Как было сказано выше г <е, чтобы мы могли прикрепить е как левый узел е.

Удаление завершено.

(Кстати Процесс перемещения узла вверх по дереву и перегруппировкам зависимых узлов таким образом, что известен как продвижение узла. Кроме того, можно продвигать узел без удаления других узлов.)



         / \
       D C
         \ / \
          е е г

Обратите внимание, что существует еще один совершенно законный исход deleteing узел B. Если мы выбрали для продвижения узла д вместо узла е дерево будет выглядеть следующим образом.



         / \
       е с
     / / \
   д е г

Ответил 29/06/2010 в 21:44
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more