Thread View: pl.comp.lang.c
3 messages
3 total messages
Started by M.M.
Fri, 11 Aug 2017 14:29
losowy element z QMap lub std:set
Author: M.M.
Date: Fri, 11 Aug 2017 14:29
Date: Fri, 11 Aug 2017 14:29
33 lines
2274 bytes
2274 bytes
Szukam efektywnej metody wybierania losowego elementu z takich struktur jak w tytule: 1) QMap 2) std::set Obie struktury mają to do siebie, że są zaimplementowane jako drzewa poszukiwań binarnych. Drzewka te maja mechanizm wyważania, zdaje się że są to drzewa czerwono czarne. Zatem struktury z bosta: boost::container::flat_set nie mogę użyć, bo wstawianie (o ile się nie mylę) jest w czasie O(N). W QT ze struktury QMap próbowałem wybierać losowy element mniej/więcej w taki sposób: map.constBegin() + random() % map.size(); W std tak: i = set.cbegin(); std::advanced( i , random() % set.size() ); Obie metody w są koszmarnie wolne, zdaje się, że iterują po drzewku, czyli czas działania jest liniowy względem numeru elementu i jeszcze trochę zależy od głębokości drzewka. Jak można to zrobić efektywniej? Trzeba zakodzić swoje drzewo czerwono czarne? Jakbym zakodził swoje, to bym miał od razu na kiedyś statystyki pozycyjne... Pozdrawiam
Re: losowy element z QMap lub std:set
Author: Wojciech Muła
Date: Sat, 12 Aug 2017 08:41
Date: Sat, 12 Aug 2017 08:41
37 lines
2705 bytes
2705 bytes
On Friday, August 11, 2017 at 4:29:38 PM UTC+2, M.M. wrote: > Szukam efektywnej metody wybierania losowego elementu z takich > struktur jak w tytule: > > 1) QMap > 2) std::set > > Obie struktury mają to do siebie, że są zaimplementowane jako > drzewa poszukiwań binarnych. Drzewka te maja mechanizm wyważania, > zdaje się że są to drzewa czerwono czarne. Zatem struktury z bosta: > > boost::container::flat_set > > nie mogę użyć, bo wstawianie (o ile się nie mylę) jest w czasie O(N). > > W QT ze struktury QMap próbowałem wybierać losowy element mniej/więcej w > taki sposób: > > map.constBegin() + random() % map.size(); > > W std tak: > > i = set.cbegin(); > std::advanced( i , random() % set.size() ); > > Obie metody w są koszmarnie wolne, zdaje się, że iterują po drzewku, > czyli czas działania jest liniowy względem numeru elementu i jeszcze > trochę zależy od głębokości drzewka. > > Jak można to zrobić efektywniej? Trzeba zakodzić swoje drzewo czerwono > czarne? Jakbym zakodził swoje, to bym miał od razu na kiedyś statystyki > pozycyjne... Wepnij własny alokator do std::map, niech on sobie trzyma liniową strukturę danych. I wtedy random robisz na tej strukturze. w.
Re: losowy element z QMap lub std:set
Author: M.M.
Date: Sat, 12 Aug 2017 10:15
Date: Sat, 12 Aug 2017 10:15
60 lines
4159 bytes
4159 bytes
On Saturday, August 12, 2017 at 10:41:12 AM UTC+2, Wojciech Muła wrote: > > Jak można to zrobić efektywniej? Trzeba zakodzić swoje drzewo czerwono > > czarne? Jakbym zakodził swoje, to bym miał od razu na kiedyś statystyki > > pozycyjne... > Wepnij własny alokator do std::map, niech on sobie trzyma liniową > strukturę danych. I wtedy random robisz na tej strukturze. Dziękuję za odpowiedź. To dobre rozwiązanie, chociaż nie mam doświadczenia z allocatorami, pewnie bym się namęczył zanim bym przebrnął przez to. Jeśli ktoś ma doświadczenie z allocatorami to zaproponowane przez Ciebie rozwiązanie chyba jest optymalne pod względem nakładu pracy. Po przemyśleniu doszedłem do ciut innego rozwiązania. Chciałem wyprowadzić klasę z QMap, a potem nadpisać wstawianie i usuwanie. W osobnej strukturze chciałem trzymać iteratory. Potem jednak zastanowiłem się dalej i napisałem swoją wersję drzewa czerwono czarnego. Nie używam (jawnie) allocacji. Całość oparłem o klasę QVector. Elementy drzewa nie mają wskaźników do rodzica i potomków, lecz mają indeksy w QVector. Uzyskałem w ten sposób szereg niezamierzonych i nieprzewidzianych efektów. Po pierwsze, gdy program mało robi poza operacjami na drzewie, to działa od 1.5 do nawet 2 razy szybciej niż QMap i std::set. Mam na myśli takie operacje jak wstawianie, przeszukiwanie z przodu do tyłu i z tylu do przodu, lower_bound, upper_bound, wyszukiwania i usuwania jeszcze nie sprawdzałem. Gdyby program tylko operował na drzewie, co jest niemożliwe, to pewnie wersja na QVectorze działałąby 3 razy szybciej. Drugi efekt, dane w qvector można posortować w czasie trochę ponad liniowym względem ilości danych. Gdy jest dużo wyszukiwania, to opłaca się posortować, a potem wyszukiwać binarnie na wektorze. Wyszukiwanie na wektorze jest znacznie szybsze niż na drzewie, może z 5 razy. Kolejny efekt, mogę zwracać z drzewa referencje do danych nie-const. Jeśli wiem że modyfikacja danych nie wpłynie na porządek w drzewie, to nie muszę robić czasochłonnych: remove modify insert Dalej, gdy chodzi o QMap, to niestety ten szablon działa tylko dla pary elementów, czyli trzeba zdefiniować pustą klasę Empty. Myslę, że kompilatory całkowicie nie potrafią wywalić operacji na pustej klasie i dodatkowo spowalniają cały kod. Najdziwniejsze jest że moja wersja działa szybciej. Nie wiem dlaczego. QMap nie jest thread-safety, std::set chyba też nie jest, więc żadnych istotnych różnic w funkcjonalności nie widzę. Czyżby implementacja na QVector dawała takie przyspieszenie? Pozdrawiam
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads