Usuń w binarne drzewo poszukiwań?

głosy
0

Czytam poprzez drzewa binarnego usuwać węzła algorytm używany w książce struktur danych i algorytmów: Reference uwagami z Przykładów

na stronie 34, w przypadku 4 (Usuń węzeł, który ma zarówno prawo i lewo sub drzew), następujący algorytm opisany w książce wygląda nie działa, prawdopodobnie może się mylę może ktoś mi pomóc, co mi brakuje.

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

W jaki sposób następujący wiersz usuwa największą wartość z pod drzewa FindParent(largestValue).Right <- 0

Utwórz 29/06/2010 o 21:09
źródło użytkownik
W innych językach...                            


5 odpowiedzi

głosy
1

Chodzi o to, aby po prostu przyjmują wartość od największego węzła po stronie lewej i przenieść go do węzła, który jest usunięty, to znaczy, nie należy usuwać węzeł w ogóle, po prostu zastąpić jego zawartość. Następnie należy przycinać na węzeł z wartością ty przeniesione do „usunięty” węzła. Ten zachowuje kolejność drzewo z wartością każdego węzła jest większa niż wszystko to co pozostało dzieci i mniejszy niż wszystko to tuż dzieci.

Odpowiedział 29/06/2010 o 21:16
źródło użytkownik

głosy
1

Jeśli rozumiem pseudo-kod, to działa w przypadku ogólnym, ale nie w „jeden węzeł w lewym poddrzewie” sprawy. Dobry chwyt.

Skutecznie zastępuje node_to_remove z largest_value od lewej to poddrzewo (również null stary węzeł largest_value).

Zauważ, że w BST, lewe poddrzewo z node_to_remove będzie wszystko być mniejsza niż node_to_remove. Prawo poddrzewo z node_to_remove wszystko będzie większa niż node_to_remove. Więc jeśli wziąć największy węzeł w lewym poddrzewie, to zachować niezmienny.

Jeśli jest to „jeden węzeł w przypadku poddrzewa”, to będzie zniszczyć właściwą poddrzewa zamiast. lame :(

Jak Vivin zwraca uwagę, że również nie załóż lewy dzieci largestNode.

Odpowiedział 29/06/2010 o 21:16
źródło użytkownik

głosy
6

Podczas usuwania węzła z dwojgiem dzieci, można wybrać jego następcę na zamówienie lub jego węzeł węzeł poprzednik zamówienie. W tym przypadku jest to znalezienie największej wartości w lewym sub-tree (czyli najbardziej po prawej dziecko swojego lewego sub-tree), co oznacza, że ​​jest znalezienie węzła węzła w zamówienie poprzednika.

Po znalezieniu zastępczego węzła, w rzeczywistości nie usunąć węzeł który ma zostać usunięty. Zamiast wziąć wartość z węzłem następcy i przechowywać tę wartość w węźle, który chcesz usunąć. Następnie należy usunąć węzeł następcy. W ten sposób możesz zachować binarną Szukaj nieruchomości drzewo skoro można mieć pewność, że węzeł został wybrany będzie miał wartość, która jest niższa od wartości wszystkich dzieci w lewym sub-tree oryginalnego węzła, a większa, że od wartości wszystkich dzieci w odpowiednim sub-tree oryginalnego węzła.

EDYTOWAĆ

Po przeczytaniu pytanie trochę więcej, myślę, że znalazłem problem.

Zazwyczaj co masz oprócz deletefunkcji jest replacefunkcja, która zastępuje węzeł w pytaniu. Myślę, że trzeba zmienić ten wiersz kodu:

FindParent(largestValue).Right <- 0

do:

FindParent(largestValue).Right <- largestValue.Left

Jeśli largestValuewęzeł nie posiada lewy dziecko, po prostu dostać nulllub 0. Jeśli to ma lewy dziecka, że dziecko staje się zamiennikiem dla largestValuewęzła. Tak masz rację; kod nie bierze pod uwagę scenariusz, że largestValuewęzeł może mieć lewy dziecko.

Innym EDIT

Odkąd pisał tylko fragment, nie jestem pewien, co kontekst kodu jest. Ale jak pisał fragment wydaje się mieć problem proponujesz (zastąpił zły węzeł). Zazwyczaj istnieją trzy przypadki, ale zauważam, że komentarz w swoim fragmencie mówi //Case 4(więc może jest jakiś inny kontekst).

Wcześniej wspomniałem na fakt, że deletezazwyczaj pochodzi z replace. Więc jeśli znajdziesz largestValuewęzeł, należy go usunąć według dwóch prostych przypadkach (węzła bez dzieci i węzła z jednym dzieckiem). Więc jeśli szukasz w pseudo-kodu, aby usunąć węzeł z dwójką dzieci, to co zrobisz:

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

Uważam, że to dziwne, że struktury danych i algorytmy książka będzie opuścić tę część, więc jestem skłonny sądzić, że książka ma dodatkowo podzielone usunięcie na kilka więcej przypadków (ponieważ istnieją trzy standardowe przypadki), aby ułatwić Rozumiesz.

Aby udowodnić, że powyższy kod działa, należy rozważyć następujące drzewa:

  8
 / \
7   9

Załóżmy, że chcesz usunąć 8. Starasz się znaleźć largestValueod nodeToRemove.Left. Daje to 7od lewa sub-drzewo ma tylko jedno dziecko.

Następnie należy zrobić:

nodeToRemove.Value <- largestValue.Value

Co znaczy:

8.value <- 7.Value

lub

8.Value <- 7

Więc teraz drzewo wygląda następująco:

  7
 / \
7   9

Trzeba pozbyć węzła zastępczego i tak masz zamiar wymienić largestValuez largestValue.Left(co jest null). Więc najpierw dowiedzieć się, jakie dziecko 7jest:

if largestValue = largestValue.Parent.Left then

Co znaczy:

if 7 = 7.Parent.Left then

lub:

if 7 = 8.Left then

Od 7JEST 8lewej dziecka, trzeba wymienić 8.Leftz 7.Right( largestValue.Parent.Left <- largestValue.Left). Ponieważ 7nie ma dzieci, 7.Leftjest nieważna. Więc largestValue.Parent.Leftzostaje przydzielony na null (co skutecznie usuwa jego lewy dziecko). Więc oznacza to, że możesz skończyć z poniższego drzewa:

  7
   \
    9
Odpowiedział 29/06/2010 o 21:17
źródło użytkownik

głosy
0

Może to więcej sensu, jeśli spojrzeć na Wikipedii wziąć na tej części algorytmu:

Usuwanie węzła z dwójką dzieci : Call węzeł zostać usunięte „N”. Nie usuwaj N. Zamiast wybrać albo jego następca węzeł zamówienie lub jego węzeł zamówienie poprzednika, „R”. Zastąpienie wartości N o wartości R, a następnie usunąć R. (Uwaga: Sam R ma do jednego dziecka).

Zauważ, że dany algorytm wybiera węzeł poprzednik zamówienie.

Edit: to, co wydaje się być brak możliwości, że R (używając terminologii Wikipedii) ma jedno dziecko. Rekurencyjna usuwać może działać lepiej.

Odpowiedział 29/06/2010 o 21:20
źródło użytkownik

głosy
1

Myślę, że być może trzeba wyjaśnić, co nie działa.

Postaram się wyjaśnić pojęcie delecji w binarnym drzewie w przypadku to pomaga.

Załóżmy, że masz węzeł w drzewie, który ma dwa węzły potomne, które chcesz usunąć. w drzewie poniżej powiedzmy, że chcesz usunąć węzeł B
           a
         / \
       b c
     / \ / \
   D E F G

Kiedy usunąć węzeł musimy załóż swoje zależnych węzłów.

to znaczy. Gdy usuwamy b musimy ponownie podłączyć węzłów D i E.

Wiemy, że lewa węzły są mniej niż prawo węzłów wartości i że węzły nadrzędne są między lewej i prawej stronie węzła s wartości. W tym przypadku, d <bib <E. Jest to część definicji binarnego drzewa.

Co jest nieco mniej oczywiste jest to, że e <a. Więc to oznacza, że ​​możemy zastąpić B z e. Teraz mamy reattached e musimy załóż d.

Jak stwierdzono wcześniej d <e więc możemy dołączyć e jako lewym węźle e.

Skreślenie jest zakończona.

(Btw Proces przenoszenia węzeł górę drzewa i rozmieszczanie węzłów zależnych w ten sposób jest znany jako promowanie węzła. Można również promować węzeł bez usuwania innych węzłów).



         / \
       d c
         \ / \
          e f g

Zauważ, że nie ma innej w pełni uzasadnione wynik deleteing węzeł B. Jeśli zdecydowaliśmy się promować węzeł D zamiast węzła e drzewo może wyglądać następująco.



         / \
       e c
     / / \
   d F G

Odpowiedział 29/06/2010 o 21:44
źródło użytkownik

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