Процедура удаления бинарного дерева поиска

Рассмотрим процедуру удаления на BST, когда удаляемый узел имеет двух дочерних узлов. Скажем, я всегда заменяю его узлом, содержащим минимальный ключ в его правом поддереве.

Возникает вопрос: коммутативна ли эта процедура? То есть удаление x, а затем y имеет тот же результат, что и удаление сначала y, а затем x?

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

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

Может быть, я должен быть яснее.

Рассмотрим процедуру transplant(node x, node y): она заменяет x на y (и его поддерево). Итак, если я хочу удалить узел (скажем, x), у которого есть два дочерних элемента, я заменяю его узлом, содержащим минимальный ключ в его правом поддереве:

y = minimum(x.right)
transplant(y, y.right) // extracts the minimum (it doesn't have left child)
y.right = x.right
y.left = x.left
transplant(x,y)

Вопрос заключался в том, как доказать, что приведенная выше процедура не является коммутативной.


person Metz    schedule 07.06.2010    source источник


Ответы (4)


Удаление (вообще) не коммутативно. Вот контрпример:

    4
   / \
  3   7
     /
    6

Что, если мы удалим 4, а затем 3?

Когда мы удаляем 4, мы получаем 6 в качестве нового корня:

   6
  / \
 3   7

Удаление 3 не меняет дерево, но дает нам следующее:

  6
   \
    7

Что, если мы удалим 3, а затем 4?

Когда мы удаляем 3, дерево не меняется:

 4
  \
   7
  /
 6

Однако, когда мы теперь удаляем 4, новый корень становится 7:

  7
 /
6

Два получившихся дерева не совпадают, поэтому удаление не является коммутативным.

ОБНОВЛЕНИЕ

Я не читал ограничение, что это когда вы всегда удаляете узел с 2 дочерними элементами. Мое решение для общего случая. Я обновлю его, если/когда найду контрпример.

ДРУГОЕ ОБНОВЛЕНИЕ

У меня нет конкретных доказательств, но я рискну предположить:

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

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

Рассмотрим два узла A и B, где A является предком B. Затем вы можете дополнительно уточнить вопрос:

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

Когда вы удаляете узел (скажем, A), вы проходите по правому поддереву, чтобы найти минимальный элемент. Этот узел будет конечным узлом и никогда не может быть равен B (поскольку B имеет двух дочерних узлов и не может быть конечным узлом). Затем вы замените значение A значением этого листового узла. Это означает, что единственным структурным изменением дерева является замена значения A значением конечного узла и потеря конечного узла.

Тот же процесс используется для B. То есть вы заменяете значение узла и заменяете конечный узел. В целом, когда вы удаляете узел с двумя дочерними элементами, единственное структурное изменение — это изменение значения удаляемого узла и удаление конечного узла, значение которого вы используете в качестве замены .

Итак, вопрос уточняется:

Можете ли вы гарантировать, что вы всегда будете получать один и тот же заменяющий узел независимо от порядка удаления (когда вы всегда удаляете узел с двумя дочерними элементами)?

Ответ (я думаю) да. Почему? Вот несколько наблюдений:

  • Допустим, вы сначала удаляете узел-потомок, а затем — узел-предок. Поддерево, которое было изменено при удалении узла-потомка, нет в левом поддереве правого дочернего узла-предка. Это означает, что это поддерево остается незатронутым. Это также означает, что независимо от порядка удаления изменяются два разных поддерева, и поэтому операция является коммутативной.
  • Опять же, предположим, что вы сначала удаляете узел-потомок, а затем — узел-предок. Поддерево, которое было изменено при удалении узла-потомка , находится в левом поддереве правого дочернего узла-предка. Но даже здесь нет совпадений. Причина в том, что когда вы сначала удаляете узел-потомок, вы просматриваете левое поддерево правого потомка узла-потомка. Когда вы затем удалите родительский узел, вы никогда не спуститесь вниз по этому поддереву, поскольку вы будете всегда двигаться влево после того, как вы войдете в правую часть родительского узла. поддерево. Итак, опять же, независимо от того, что вы удаляете первым, вы изменяете разные поддеревья, и поэтому кажется, что порядок не имеет значения.
  • Другой случай — если вы сначала удалите узел-предок и обнаружите, что минимальный узел является дочерним по отношению к узлу-потомку. Это означает, что узел-потомок будет иметь один дочерний узел, и удаление одного дочернего узла является тривиальным. Теперь рассмотрим случай, когда в этом сценарии вы сначала удалили дочерний узел. Затем вы замените значение узла-потомка его правым дочерним элементом, а затем удалите правильный дочерний элемент. Затем, когда вы удаляете узел-предок, вы в конечном итоге находите такой же минимальный узел (левый дочерний элемент старого удаленного узла, который также является левым дочерним элементом замененного узла). В любом случае вы получите одну и ту же структуру.

Это не строгое доказательство; это всего лишь некоторые наблюдения, которые я сделал. В любом случае, не стесняйтесь протыкать дыры!

person Vivin Paliath    schedule 07.06.2010
comment
о, да, это было довольно просто. Спасибо! - person Metz; 07.06.2010
comment
Как новый корень стал 7 во 2-м случае после удаления 4-го? Разве не должно быть 6? После удаления 4 следующим минимальным элементом в правом поддереве 4 будет 6, поэтому корень изменится на 6? В приведенном выше, например. удаление 3 и 4 или удаление 4 и 3 дает тот же результат. Однако я не уверен, работает ли это как общее правило. - person srikanta; 07.06.2010
comment
Во втором случае вы удаляете 4. 4 — это узел с одним потомком. Когда вы удаляете узел с одним дочерним элементом (нет необходимости искать правильный узел, так как вы можете быть уверены, что единственный дочерний элемент меньше или больше в зависимости от того, является ли он правым или левым дочерним элементом), вы можете заменить узел его ребенок. Дополнительная информация здесь: en.wikipedia.org/wiki/Binary_search_tree#Deletion - person Vivin Paliath; 07.06.2010
comment
Как сказал @Vivin, это не соответствует ограничению, согласно которому вы никогда не удаляете узел с менее чем двумя дочерними элементами. - person IVlad; 07.06.2010
comment
Ммм, Мэд прав, это было просто, потому что у второго узла нет двух детей. я снимаю галочку с ответа Вивина. Прошу прощения за свою невнимательность. - person Metz; 07.06.2010
comment
@Metz, прошу прощения за мою невнимательность - не прочитал ограничение, что это для двоих детей. Я думал, что это общий случай. :) - person Vivin Paliath; 08.06.2010
comment
@VivinPaliath Если вы придерживаетесь одного и того же правила в обоих случаях, которое всегда выбирает либо самое большое в левом поддереве, либо выбирает наименьшее в правом поддереве для замены ... это будет коммутативным - person cbinder; 12.06.2014

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

But it can also be eliminated if we discard what appears to be one of Vivin's premises, which is that we should traverse the right subtree as little as possible to find any acceptable successor. If, instead, we always promote the smallest node in the right subtree as the successor, regardless of how far away it turns out to be located, then even if we relax the restriction on deleting nodes with fewer than two children, Vivin's result

    7
   /
  6
is never reached if we start at

    4
   / \
  3   7
     /
    6

Instead, we would first delete 3 (without successor) and then delete 4 (with 6 as successor), yielding

    6
     \
      7

то же самое, как если бы порядок удаления был обратным.

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

У меня нет формального доказательства, я просто перечисляю случаи:

  1. Если два удаляемых узла находятся в разных поддеревьях, то удаление одного не влияет на другой. Только когда они находятся на одном пути, порядок удаления может повлиять на результат.

    Таким образом, любое влияние на коммутативность может произойти только тогда, когда удаляются узел-предок и один из его потомков. Теперь, как их вертикальные отношения влияют на коммутативность?

  2. Потомок в левом поддереве предка. Эта ситуация не повлияет на коммутативность, поскольку потомок происходит из правого поддерева и вообще не может влиять на левое поддерево.

  3. Потомок в правом поддереве предка. Если преемник предка всегда является наименьшим узлом в правом поддереве, то порядок удаления не может изменить выбор преемника, независимо от того, какой потомок удаляется до или после предок. Даже если преемник предка оказывается узлом-потомком, который также должен быть удален, этот потомок также заменяется следующим по величине узлом к ​​нему, и у этого потомка не может оставаться своего собственного левого поддерева, с которым нужно работать. . Таким образом, удаление предка и любого потомка правого поддерева всегда будет коммутативным.

person brannerchinese    schedule 06.04.2011
comment
Пример некоммутативности, который я привел, основан на стандартном алгоритме удаления; когда у узла есть только один дочерний узел, его можно удалить и заменить этим дочерним узлом. В моем случае 4 имеет только одного дочернего элемента (7), поэтому его можно заменить этим дочерним элементом. Это связано с тем, что нам на самом деле не нужно проходить всю высоту поддерева (что в худшем случае стоит O(log n)), если только у узла нет двух дочерних элементов. Но с вашей предпосылкой верно, что удаление будет коммутативным, но с повышенными затратами на производительность. - person Vivin Paliath; 28.02.2013

Я думаю, что есть два одинаково жизнеспособных способа удалить узел, когда у него есть 2 дочерних элемента:
ПРОПУСТИТЬ К СЛУЧАЮ 4...

Случай 1. : удалить 3 (конечный узел)
2 3
/ \ --> / \
1 3 1


Вариант 2: удалить 2 (левый дочерний узел)
2 3
/ \ --> / \
1 3 1


Вариант 3: удалить 2 (правый дочерний узел)
2 2
/ \ --> / \
1 3 3

______________________________________________________________________
Случай 4: удалить 2 (левый и правый дочерние узлы)
2 2 3
/ \ --> / \ или / \
1 3 1 3
ОБА РАБОТАЮТ и имеют разные результирующие деревья :) ______________________________________________________________________
Алгоритм объяснен здесь: http://www.mathcs.emory.edu/~cheung/Courses/323/Syllabus/Trees/AVL-delete.html Deleting a node with 2 children nodes: 1) Replace the (to-delete) node with its in-order predecessor or in-order successor 2) Then delete the in-order predecessor or in-order successor

person Jason    schedule 10.10.2016

Я отвечаю здесь на второе обновление Вивина.

Я думаю, что это хорошая переработка вопроса:

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

но это смелое предложение ниже не соответствует действительности:

Когда вы удаляете узел (скажем, A), вы проходите по правому поддереву, чтобы найти минимальный элемент. Этот узел будет конечным узлом и никогда не может быть равен B

поскольку минимальный элемент в правом поддереве A может иметь правого дочернего элемента. Значит, это не лист. Назовем минимальный элемент в правом поддереве A successor(A). Верно, что B не может быть successor(A), но может находиться в своем правом поддереве. Итак, это беспорядок.

Я пытаюсь обобщить.

Гипотеза:

  1. У А и В по двое детей.
  2. A и B находятся в одном поддереве.

Другие вещи, которые мы можем вывести из гипотезы:

  1. B не successor(A), ни A не successor(B).

Теперь, учитывая это, я думаю, что есть 4 разных случая (как обычно, пусть A предок B):

  1. B находится в левом поддереве A
  2. B является предком successor(A)
  3. successor(A) является предком B
  4. B и преемник (A) не имеют никаких отношений. (они находятся в разных поддеревьях A)

Я думаю (но, конечно, не могу этого доказать), что случаи 1, 2 и 4 не имеют значения. Таким образом, только в случае, когда successor(A) является предком B, процедура удаления не может быть коммутативной. Или может?

Я передаю мяч :)

С Уважением.

person Metz    schedule 11.06.2010