chciałbym przypuszczać, że lepsze wdrożenie byłoby O (log (n)) dla różnych operacji, wykorzystując drzewo zamiast kopii tabeli.
Tabele drzew i tabel mieszania mają bardzo różne wymagania i cechy wydajności.
- Drzewa wymagają zamówionego rodzaju.
- Drzewa wymagają porównywania zamówień, aby znaleźć obiekt. W przypadku niektórych obiektów, takich jak łańcuchy, zapobiega to niektórym znaczącym optymalizacjom: zawsze trzeba wykonać porównanie ciągów, które jest niedrogie. To sprawia, że stały współczynnik O (log n) jest dość wysoki.
- Tabele skrótów wymagają typu skrótów i można testować równość, ale nie wymagają one typu uporządkowanego.
- Testy na równość można znacznie zoptymalizować. Jeśli internowane są dwa ciągi, możesz sprawdzić, czy są one równe w O (1), porównując ich wskaźnik, a nie O (n), porównując cały ciąg. Jest to optymalizacja masywna: w każdym wyszukiwaniu
foo.bar
, które zostanie przetłumaczone na foo.__dict__["bar"]
, "bar"
jest internowanym ciągiem znaków.
- Tabele skrótu są w najgorszym przypadku O (n), ale sprawdzają, co prowadzi do najgorszego przypadku: bardzo kiepska implementacja tablicy mieszającej (np. Masz tylko jedną łyżkę) lub zepsuta funkcja skrótu, która zawsze zwraca to samo wartość. Kiedy masz odpowiednią funkcję mieszającą i odpowiedni algorytm fałszowania, wyszukiwania są bardzo tanie - bardzo często zbliżają się do stałego czasu.
Drzewa mają istotne zalety:
- Oni wydają się mieć mniejsze zapotrzebowanie na pamięć, ponieważ nie mają do przydzielenia wiadra.Najmniejsze drzewo może mieć 12 bajtów (wskaźnik węzłowy i dwa wskaźniki potomne), gdzie tablica skrótów ma zwykle 128 bajtów lub więcej - sys.getsizeof ({}) w moim systemie to 136.
- Umożliwiają one uporządkowane przemierzanie; niezwykle przydatna jest możliwość iteracji ponad [a, b) w uporządkowanym zestawie, którego tablice mieszania nie pozwalają.
ja uważam, że jest to wada, że Python nie posiada standardowego drzewa binarnego pojemnik, ale dla charakterystyk wymaganych przez rdzeń Pythona, jak __dict__
wyszukiwań, stolik hash ma więcej sensu.
Najgorszy przypadek złożoność nie jest jedynym czynnikiem, warto zoptymalizować dla. –
Liniowy re-hasz? – Pointy
"Zakładam, że lepszą implementacją będzie O (log (n)) dla różnych operacji," Dlaczego? Czy widziałeś jakieś testy porównawcze? Moje rozumienie jest "przypadkowe", a sondowanie jest w rzeczywistości najszybsze i prowadzi do O (n) jako najgorszego przypadku. Co zakładasz i jakie pomiary widziałeś? –