При удалении узла с двумя детьми, вы можете либо выбрать его в заказе преемник узел или его упорядоченная узел предшественника. В этом случае это найти наибольшее значение в левом поддереве (означает, что самый правый ребенок своего левого поддерева), что означает, что он находит упорядоченную узел предшественника узла.
После того, как вы нашли узел замены, вы на самом деле не удалить узел , который необходимо удалить. Вместо того, чтобы взять значение из узла преемника и сохранять это значение в узле , который требуется удалить. Затем удалить узел преемника. При этом вы сохраняете свойства бинарного поиска дерева , так как вы можете быть уверены в том , что узел выбран будет иметь значение, которое ниже , чем значения всех детей в левом поддереве исходного узла, и больше , что , чем значения всех детей в правом поддереве исходного узла.
РЕДАКТИРОВАТЬ
После прочтения вашего вопроса немного больше, я думаю, что я нашел эту проблему.
Как правило , то , что у вас есть в дополнении к 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