Dyskusja:Sortowanie przez kopcowanie
Nie podoba mi się użyta terminologia :] Na przykład słowo liść - czy zostało użyte zgodnie z powszechnie przyjętym znaczeniem? Nie ma również chyba potrzeby robienia linka np. z tablicy wszędzie, gdzie wystąpi --severson 20:21, 2 lis 2004 (CET)
jest jeszcze
musi zaczynać się od indeksu równego 1 - nie 0, ze względu na poprawność działania wzorów)
co jest nieprawda (wystarczy zmienic wzory). nic nie trzeba zmieniac na kopiec itd. ogolnie mnostwo niedorobek. Kbsc 20:33, 2 lis 2004 (CET)
Zrobiłem od nowa opis działania (mam nadzieję, że teraz jest lepiej). Pozwoliłem sobie także zmienić knot
na node
w przykładowej implementacji. --filu 19:22, 21 maj 2005 (CEST)
Warto byłoby jeszcze wspomnieć o różnych usprawnieniach tego algorytmu, chociażby rozróżnić pokazaną tu metodę zstępującą od efektywniejszej wstępującej.
"a pamięciowa – O ( n ) , {\displaystyle \scriptstyle \mathrm {O} (n),} \scriptstyle \mathrm O(n), "
Tak rozumując to każdy algorytm będzie miał złożoność pamięciowa – O ( n )
i nie rozróżnia się wtedy tego że np standardowa implementacja sortowania przez podział potrzebuje O(n) dodatkowej pamięci na rekurencję lub stos
czy sortowania przez scalanie które w standardowej implementacji potrzebuje O(n) pamięci na scalanie Rekurencję w sortowaniu przez scalanie można usunąć bez stosu
W porównaniu z nimi sortowanie przez kopcowanie sortuje w miejscu
błąd w shift-down
[edytuj kod]Wydaje mi się, że w procedurze shift-down jest błąd.
shift-down (T[1..n], i) k ← i repeat j ← k if 2j <= n and T[2j] > T[k] k ← 2j if 2j+1 <= n and T[2j+1] > T[k] k ← 2j+1 swap (T[j], T[k]) until j = k
Procedura nie zapewnia przywrócenia własności kopca. Jeśli T[j]<T[2j+1]<T[2j] to k zostanie ustawione na 2j+1, w wyniku czego zostaną podmienione T[j] z T[2j+1], tak więc T[2j+1] znajdzie w T[j] mimo, że jest mniejsze od T[2j]. Problem można rozwiązać na co najmniej 2 sposoby:
shift-down (T[1..n], i) k ← i repeat j ← k if 2j <= n and T[2j] > T[k] k ← 2j if 2j+1 <= n and T[2j+1] > T[k] and T[2j+1] > T[2j] k ← 2j+1 swap (T[j], T[k]) until j = k
lub gdy priorytetem jest ograniczenie ilości porównań:
shift-down (T[1..n], i) k ← i repeat j ← k if 2j <= n and T[2j] > T[k] k ← 2j if 2j+1 <= n and T[2j+1] > T[2j] k ← 2j+1 else if 2j+1 <= n and T[2j+1] > T[k] and T[2j+1] > T[2j] k ← 2j+1 swap (T[j], T[k]) until j = k
co ogranicza liczbę porównań do 2 na jedną zamianę (zamiast 3 w pierwszym przypadku). Ze względu na czytelność pozwoliłem sobie umieścić pierwszą wersję na stronie.--Schizofrenikh (dyskusja) 19:40, 12 sie 2008 (CEST)
- wydaje mi się, że kolega Schizofrenikh się myli. Jeśli T[j] < T[2j+1] < T[2j], to w pierwszym if za k zostanie podstawione 2j, więc w drugim zostanie sprawdzony warunek T[2j+1] > T[k], czyli T[2j+1] > T[2j] (bo k jest teraz równe 2j, a nie j), co jest nieprawdą i zamienione zostaną poprawnie T[j] i T[2j].
- Można to zilustrować przyjmując, że T[j] to ojciec, T[2j] to lewy syn, a T[2j+1] to prawy syn. Mamy ojciec < prawy syn < lewy syn. T[k] ma wskazywać na najwyższego. Na początku k jest rowne j, czyli T[k] wskazuje na ojca. W pierwszym if sprawdzamy, czy lewy syn jest wyższy od ojca. Tak w rzeczywistości jest, zatem k jest teraz równe 2j i T[k] wskazuje na lewego syna. Ponieważ w kodzie są dwie instrukcje if, a nie instrukcja if-else, program przechodzi do sprawdzania warunków drugiego if. Po sprawdzeniu, czy prawy syn istnieje, program sprawdza, czy prawy syn, jest wyższy od T[k], które wskazuje teraz na lewego syna. Ponieważ prawy syn jest niższy, T[k] wskazuje wciąż na lewego syna.
- Mam nadzieję, że wyjaśniłem to jasno i nie popełniłem jakiegoś błędu. Myślę, że poprzedni kod był poprawny i dodatkowy warunek T[2j+1] > T[2j] jest niepotrzebny. Pozwoliłem sobie na edycję, osobę przeglądającą edycje proszę o weryfikację tego myślenia, nie chciałbym wprowadzać tysięcy studentów w błąd :P --jaczula (dyskusja) 19:08, 21 paź 2012 (CEST)
Wykonałem testy
[edytuj kod]Napisałem program w Pascalu. W obu przypadkach buduje kopiec dobrze, oznacza to że należy przyjąć prostszą i szybszą wersję bez dodatkowego warunku. Po przejrzeniu zatwierdziłem wersję Jaczuli. Borneq (dyskusja) 00:35, 30 paź 2012 (CET)