Discussion:
Drzewo zrównoważone
(Wiadomość utworzona zbyt dawno temu. Odpowiedź niemożliwa.)
Borneq
2014-10-28 16:49:29 UTC
Permalink
Jaka klasa odpowiada w standardzie c++ drzewu zrównoważonemu, tak jak do
listy stosuję vector<>
Potrzebna jest do implementacji wyszukiwania przecięcia odcinków metodą
zamiatania
Wojciech Muła
2014-10-28 17:25:18 UTC
Permalink
Post by Borneq
Jaka klasa odpowiada w standardzie c++ drzewu zrównoważonemu, tak jak do
listy stosuję vector<>
Zwykle std::map i std::set są oparte na drzewach czerowno-czarnych,
(ale standard tego nie gwarantuje). Chociaż nie słyszałem o implementacji
opartej na innych strukturach. Jak potrzebujesz drzew AVL, to są w boost
instrusive.

w.
Borneq
2014-10-28 17:30:57 UTC
Permalink
Post by Wojciech Muła
Zwykle std::map i std::set są oparte na drzewach czerowno-czarnych,
(ale standard tego nie gwarantuje). Chociaż nie słyszałem o implementacji
opartej na innych strukturach. Jak potrzebujesz drzew AVL, to są w boost
instrusive.
A czym się różnią? std::map to chyba mapowanie jednego obiektu w drugi,
dziwne że nie na hashach. Chyba std::set się nada, dzięki!
M.M.
2014-11-03 11:11:24 UTC
Permalink
Post by Wojciech Muła
Post by Borneq
Jaka klasa odpowiada w standardzie c++ drzewu zrównoważonemu, tak jak do
listy stosuję vector<>
Zwykle std::map i std::set są oparte na drzewach czerowno-czarnych,
(ale standard tego nie gwarantuje). Chociaż nie słyszałem o implementacji
opartej na innych strukturach. Jak potrzebujesz drzew AVL, to są w boost
instrusive.
w.
Odbiegajac od tematu, czy w std::set jest zaimplementowana funkcja next i
prev w kolejnosci sortowania? Jesli nie, to wykorzystanie drzew
zrownowazonych do implementacji zbioru wydaje sie kiepskim pomyslem.

Pozdrawiam
bartekltg
2014-11-03 11:46:24 UTC
Permalink
Post by M.M.
Post by Wojciech Muła
Post by Borneq
Jaka klasa odpowiada w standardzie c++ drzewu zrównoważonemu, tak jak do
listy stosuję vector<>
Zwykle std::map i std::set są oparte na drzewach czerowno-czarnych,
(ale standard tego nie gwarantuje). Chociaż nie słyszałem o implementacji
opartej na innych strukturach. Jak potrzebujesz drzew AVL, to są w boost
instrusive.
w.
Odbiegajac od tematu, czy w std::set jest zaimplementowana funkcja next i
prev w kolejnosci sortowania?
Operatory ++ i -- na iteratorze. W std::set chodzą one
w kolejności wyznaczonej przez porządek.
Od jakiegoś czasu dla wygody jest też next i prev:
http://en.cppreference.com/w/cpp/iterator/next
Post by M.M.
Jesli nie, to wykorzystanie drzew
zrownowazonych do implementacji zbioru wydaje sie kiepskim pomyslem.
?

pzdr
bartekltg
M.M.
2014-11-03 13:00:04 UTC
Permalink
Post by bartekltg
Post by M.M.
Post by Wojciech Muła
Post by Borneq
Jaka klasa odpowiada w standardzie c++ drzewu zrównoważonemu, tak jak do
listy stosuję vector<>
Zwykle std::map i std::set są oparte na drzewach czerowno-czarnych,
(ale standard tego nie gwarantuje). Chociaż nie słyszałem o implementacji
opartej na innych strukturach. Jak potrzebujesz drzew AVL, to są w boost
instrusive.
w.
Odbiegajac od tematu, czy w std::set jest zaimplementowana funkcja next i
prev w kolejnosci sortowania?
Operatory ++ i -- na iteratorze. W std::set chodzą one
w kolejności wyznaczonej przez porządek.
http://en.cppreference.com/w/cpp/iterator/next
Post by M.M.
Jesli nie, to wykorzystanie drzew
zrownowazonych do implementacji zbioru wydaje sie kiepskim pomyslem.
?
Poniewaz wtedy hashtable jest lepsza. W QT zbior jest realizowany wlasnie
jako hashtable.
Pozdrawiam
bartekltg
2014-11-03 13:12:12 UTC
Permalink
Post by M.M.
Post by bartekltg
Post by M.M.
Post by Wojciech Muła
Post by Borneq
Jaka klasa odpowiada w standardzie c++ drzewu zrównoważonemu, tak jak do
listy stosuję vector<>
Zwykle std::map i std::set są oparte na drzewach czerowno-czarnych,
(ale standard tego nie gwarantuje). Chociaż nie słyszałem o implementacji
opartej na innych strukturach. Jak potrzebujesz drzew AVL, to są w boost
instrusive.
w.
Odbiegajac od tematu, czy w std::set jest zaimplementowana funkcja next i
prev w kolejnosci sortowania?
Operatory ++ i -- na iteratorze. W std::set chodzą one
w kolejności wyznaczonej przez porządek.
http://en.cppreference.com/w/cpp/iterator/next
Post by M.M.
Jesli nie, to wykorzystanie drzew
zrownowazonych do implementacji zbioru wydaje sie kiepskim pomyslem.
?
Poniewaz wtedy hashtable jest lepsza. W QT zbior jest realizowany wlasnie
jako hashtable.
std::unordered_set
Jest to tablica haszująca z listą jako rozwiązaniem kolizji
(co jako bonus daje stały czas operacji ++, kolejność
jest 'jakaś', ale nieraz chcemy zrobić jakąć operację
na każdym elemencie).

A na pytanie, co jest lepsze, odpowiedź jest tylko jedna:
Zależy, zmierz.
;-)

pzdr
bartekltg
M.M.
2014-11-03 13:58:11 UTC
Permalink
Post by bartekltg
std::unordered_set
Jest to tablica haszująca z listą jako rozwiązaniem kolizji
(co jako bonus daje stały czas operacji ++, kolejność
jest 'jakaś', ale nieraz chcemy zrobić jakąć operację
na każdym elemencie).
Jest pare odmian hashtable. Rzadko spotykalem sie z sytuacja, w
ktorej byla potrzebna pelna hashtable. Czesto potrzebowalem
hashtable bez mozliwosci usuwania elementow. Albo nawet takiej, ze
operacja wstawiania mogla sie z rzadka nie udac.
Post by bartekltg
Zależy, zmierz.
;-)
Gdy mierzylem, to zwykle najlepsza byla specjalistyczna, wlasnorecznie
skrojona na miare zadania hash-table.


Pozdrawiam
Wojciech Muła
2014-11-03 13:37:11 UTC
Permalink
Post by M.M.
Odbiegajac od tematu, czy w std::set jest zaimplementowana funkcja next i
prev w kolejnosci sortowania? Jesli nie, to wykorzystanie drzew
zrownowazonych do implementacji zbioru wydaje sie kiepskim pomyslem.
To zależy od scenariusza użycia. Jeśli masz coś w rodzaju: zbuduj raz,
sprawdzaj przynależność wiele razy, to rzeczywiście tablica mieszająca
będzie lepsza.

Ale jeśli chcesz wykonywać operacje na zbiorach (suma, różnica, przecięcie),
to drzewo jest lepsze, bo jesteś w stanie wykonać dowolną operację w czasie
O(n + k), zakładając że iteratory działają w czasie stałym. Dla hashy
masz pesymistycznie O(n * k).

w.
M.M.
2014-11-03 13:57:32 UTC
Permalink
Post by Wojciech Muła
Post by M.M.
Odbiegajac od tematu, czy w std::set jest zaimplementowana funkcja next i
prev w kolejnosci sortowania? Jesli nie, to wykorzystanie drzew
zrownowazonych do implementacji zbioru wydaje sie kiepskim pomyslem.
To zależy od scenariusza użycia. Jeśli masz coś w rodzaju: zbuduj raz,
sprawdzaj przynależność wiele razy, to rzeczywiście tablica mieszająca
będzie lepsza.
Jesli bez usuwania pojedynczych elememntow, to hash-table powinna byc
wielokrotnie lepsza, poniewaz algorytmy maja mniejszy narzut liniowy, a
pamiec lepiej sie cachuje.
Post by Wojciech Muła
Ale jeśli chcesz wykonywać operacje na zbiorach (suma, różnica, przecięcie),
to drzewo jest lepsze, bo jesteś w stanie wykonać dowolną operację w czasie
O(n + k), zakładając że iteratory działają w czasie stałym. Dla hashy
masz pesymistycznie O(n * k).
Pesymistycznie dla hashy to i wyszukiwanie trwa n. Sume na drzewach mozna
zrobic w czasie log(n), ale potem wywazanie drzewa troche trwa, za wyjatkiem
sytuacji gdy nie musimy wywazac, albo dopiero po kilku sumach bedziemy
wywazali.

Pozdrawiam
Wojciech Muła
2014-11-03 20:01:51 UTC
Permalink
Post by M.M.
Post by Wojciech Muła
To zależy od scenariusza użycia. Jeśli masz coś w rodzaju: zbuduj raz,
sprawdzaj przynależność wiele razy, to rzeczywiście tablica mieszająca
będzie lepsza.
Jesli bez usuwania pojedynczych elememntow, to hash-table powinna byc
wielokrotnie lepsza, poniewaz algorytmy maja mniejszy narzut liniowy,
Oczywiście, pomiary to pokazują, std::set potrafi być kilka razy wolniejszy
od std::unordered_set. Dobrze o tym pamiętać.
Post by M.M.
a pamiec lepiej sie cachuje.
Raczej nie. Dobra funkcja mieszająca jest de facto pseudolosowa, a losowy
dostęp i cache są mocno niekompatybilne.
Post by M.M.
Post by Wojciech Muła
Ale jeśli chcesz wykonywać operacje na zbiorach (suma, różnica, przecięcie),
to drzewo jest lepsze, bo jesteś w stanie wykonać dowolną operację w czasie
O(n + k), zakładając że iteratory działają w czasie stałym. Dla hashy
masz pesymistycznie O(n * k).
Pesymistycznie dla hashy to i wyszukiwanie trwa n.
Właśnie, to też jest powód dla którego drzewa zrównoważone mogą być lepsze.
Np. nikt nie zrobi na nie ataku DOS, dlatego z linuksowego stosu TCP wyleciały
tablice mieszające, a wleciały drzewa AVL.
Post by M.M.
Sume na drzewach mozna zrobic w czasie log(n), ale potem wywazanie
drzewa troche trwa, za wyjatkiem sytuacji gdy nie musimy wywazac, albo
dopiero po kilku sumach bedziemy wywazali.
Złożoność jest niestety n log(n). A jeśli drzewo jest AVL lub czerwono-czarne,
to wyważanie jest "Wbudowane" w strukturę.

Natomiast ja się rąbnąłem. Ta ładna złożoność liniowa byłby, gdyby std::set
potrafił się zbudować z posortowanej listy w czasie log(n) - ale nie potrafi.
To jest np. powód, dla którego czasem trzeba grzecznie podziękować std
i zrobić lepiej. :)

w.
bartekltg
2014-11-03 21:36:47 UTC
Permalink
Post by Wojciech Muła
Natomiast ja się rąbnąłem. Ta ładna złożoność liniowa byłby, gdyby std::set
potrafił się zbudować z posortowanej listy w czasie log(n) - ale nie potrafi.
To jest np. powód, dla którego czasem trzeba grzecznie podziękować std
i zrobić lepiej. :)
Jeśli masz poprawnego 'hita' wstawienie elementu jest w czasie
(zamortyzowanym) stałym, a ładując go posortowanymi danymi, wiadomo,
co jest dobrym "hintem'. Skoro sam mogę napisać liniowe wstawianie
do zbioru, dziwne by było, jakby domyslnie to nie działało. I wygląda
na to, że działa.

http://en.cppreference.com/w/cpp/container/set/set
i dla konstruktora z istniejącego kontenera:

2) N log(N) where N = std::distance(first, last) in general, linear in N
if the range is already sorted by value_comp().

I w testach to wychodzi.

https://www.dropbox.com/sh/gh35ths4ozwtbco/AAD8SSpJQEku_Z7EPzBiLR9ra?dl=0

Czas w funkcji rozmiaru danych dla nieposortowanych
i posotrowanych danych, oraz wykres proporcji.
Przypomina nieco logarytm;-)


double glob=0;

void test_set(int N)
{
vector<float> data(N);

random_device rd;
mt19937 gen(rd());
uniform_real_distribution<float> dist(1.0f,10.0f);

for (auto &it :data)
{
it=dist(gen);
}

stoper st;

st.start();

set<float> s1(data.begin(),data.end());

st.stop();
cout<<N<<" "<<st.val()<<" ";

sort(data.begin(),data.end());

//shuffle(data.begin(),data.end(),gen);

st.start();
set<float> s2(data.begin(),data.end());
st.stop();
cout<<st.val()<<endl;

glob+=*(s1.begin());
glob+=*(s2.begin());

}

void main_test_set()
{

for (int n=100000;n<100000000;n=(n*5)/4)
test_set(n);
cout<<endl<<glob<<endl;
}


pzdr
bartekltg
M.M.
2014-11-03 23:13:03 UTC
Permalink
Post by bartekltg
set<float> s1(data.begin(),data.end());
QSet w ogole nie chce dzialac na float i double, w std widze ze
dziala. Set z std porownuje elemnty na ostro, czy ma jakies
epsilon?

Pozdrawiam
bartekltg
2014-11-04 00:07:33 UTC
Permalink
Post by M.M.
Post by bartekltg
set<float> s1(data.begin(),data.end());
QSet w ogole nie chce dzialac na float i double,
Hmm, ale jaja;]
Serio, to dziwne.
Post by M.M.
w std widze ze
dziala. Set z std porownuje elemnty na ostro, czy ma jakies
epsilon?
Nie ma żadnego epsylona. Porządkuje tak, jak wynika z relacji <.
Liczby zmiennoprzecinkowe mają bardzo dobrze zdefiniowane
pojęcia jak mniejszy, większy czy równy. Nie to jest przyczyną
tego, że == w kodzie z liczbami zmiennoprzecinkowymi to przwie
na pewno błąd.

Ściślej std::set używa tego, co jest pod std::less<T>, chyba, że
wsadzisz mu komparator ręcznie.

pzdr
bartekltg
Wojciech Muła
2014-11-04 17:07:56 UTC
Permalink
Post by bartekltg
Jeśli masz poprawnego 'hita' wstawienie elementu jest w czasie
(zamortyzowanym) stałym, a ładując go posortowanymi danymi, wiadomo,
co jest dobrym "hintem'. Skoro sam mogę napisać liniowe wstawianie
do zbioru, dziwne by było, jakby domyslnie to nie działało. I wygląda
na to, że działa.
http://en.cppreference.com/w/cpp/container/set/set
2) N log(N) where N = std::distance(first, last) in general, linear in N
if the range is already sorted by value_comp().
Czyli pomyliłem się w ocenie pomyłki. A jak mówię w pracy, że jestem
głupi, to nie wierzą. :)

w.
M.M.
2014-11-03 23:00:45 UTC
Permalink
Post by Wojciech Muła
Raczej nie. Dobra funkcja mieszająca jest de facto pseudolosowa, a losowy
dostęp i cache są mocno niekompatybilne.
W niektorych odmianach hash-table dostep losowy jest tylko do
'pierwszego' elementu, potem mozna przegladac sekwencyjnie. Chodzi o
pierwszy w sensie wyszukiwania, a nie o poczatkowy element w tablicy.
W duzych drzewach dostep do kazdego wezla jest 'niecachowany'.

Nie wiem czy opisalem zrozumiale, moze kawalek kodu:


hash[size+max_search-1];
// wypelnienie hashy
start = element % size; // 'losowy' element
end = start + max_search;
while( start < end ) {
if( hash[start++] == element ) // przeszukiwanie sekwencyjne
return true;
}
return false;
Post by Wojciech Muła
Post by M.M.
Post by Wojciech Muła
Ale jeśli chcesz wykonywać operacje na zbiorach (suma, różnica, przecięcie),
to drzewo jest lepsze, bo jesteś w stanie wykonać dowolną operację w czasie
O(n + k), zakładając że iteratory działają w czasie stałym. Dla hashy
masz pesymistycznie O(n * k).
Pesymistycznie dla hashy to i wyszukiwanie trwa n.
Właśnie, to też jest powód dla którego drzewa zrównoważone mogą być lepsze.
Np. nikt nie zrobi na nie ataku DOS, dlatego z linuksowego stosu TCP wyleciały
tablice mieszające, a wleciały drzewa AVL.
Hmmm calkiem dobry powod. Nie wzialem pod uwagle, ze ktos moze zlosliwie
dobierac dane. W przypadku drzew zlosliwosc nic nie da.
Post by Wojciech Muła
Post by M.M.
Sume na drzewach mozna zrobic w czasie log(n), ale potem wywazanie
drzewa troche trwa, za wyjatkiem sytuacji gdy nie musimy wywazac, albo
dopiero po kilku sumach bedziemy wywazali.
Złożoność jest niestety n log(n). A jeśli drzewo jest AVL lub czerwono-czarne,
to wyważanie jest "Wbudowane" w strukturę.
O ile sie nie myle, operacja join na rb-tree zajmuje pesymistycznie
log(n+k), a na hashach min(n,k). Wiec zlaczanie dwoch zbiorow w
jeden bedzie wyraznie szybsze na drzewkach.
Post by Wojciech Muła
Natomiast ja się rąbnąłem. Ta ładna złożoność liniowa byłby, gdyby std::set
potrafił się zbudować z posortowanej listy w czasie log(n) - ale nie potrafi.
To jest np. powód, dla którego czasem trzeba grzecznie podziękować std
i zrobić lepiej. :)
I z kolei jesli mamy posortowana 'liste', to moze nie trzeba budowac drzewa
poszukiwan binarnych :)

Pozdrawiam
bartekltg
2014-11-04 00:27:15 UTC
Permalink
Post by M.M.
Post by Wojciech Muła
Raczej nie. Dobra funkcja mieszająca jest de facto pseudolosowa, a losowy
dostęp i cache są mocno niekompatybilne.
W niektorych odmianach hash-table dostep losowy jest tylko do
'pierwszego' elementu, potem mozna przegladac sekwencyjnie. Chodzi o
pierwszy w sensie wyszukiwania, a nie o poczatkowy element w tablicy.
W duzych drzewach dostep do kazdego wezla jest 'niecachowany'.
hash[size+max_search-1];
// wypelnienie hashy
start = element % size; // 'losowy' element
end = start + max_search;
while( start < end ) {
if( hash[start++] == element ) // przeszukiwanie sekwencyjne
return true;
}
return false;
Czyli złożoność sprawdzenia, czy element jest w tablicy gdy go nie ma
jest O(n)? Nie pesymistycznie przy złym hashu i przepełnieniu tablicy,
tylko zawsze?
Koszmarnie.

Jak odróżnisz, czy pod hash[x] jest element, czy niezainicjowana
losowa wartość? Typ elementu musi przewidywać nieużywaną kombinację
bitów, którą inicjalizujemy całą tablicę...
Post by M.M.
Post by Wojciech Muła
Post by M.M.
Sume na drzewach mozna zrobic w czasie log(n), ale potem wywazanie
drzewa troche trwa, za wyjatkiem sytuacji gdy nie musimy wywazac, albo
dopiero po kilku sumach bedziemy wywazali.
Złożoność jest niestety n log(n). A jeśli drzewo jest AVL lub czerwono-czarne,
to wyważanie jest "Wbudowane" w strukturę.
O ile sie nie myle, operacja join na rb-tree zajmuje pesymistycznie
log(n+k), a na hashach min(n,k). Wiec zlaczanie dwoch zbiorow w
jeden bedzie wyraznie szybsze na drzewkach.
http://stackoverflow.com/questions/3176863/concatenating-red-black-trees/3224033#3224033
Brrr.
STL takiej operacji nie udostępnia.

pzdr
bartekltg
M.M.
2014-11-04 09:31:02 UTC
Permalink
Post by bartekltg
Post by M.M.
Post by Wojciech Muła
Raczej nie. Dobra funkcja mieszająca jest de facto pseudolosowa, a losowy
dostęp i cache są mocno niekompatybilne.
W niektorych odmianach hash-table dostep losowy jest tylko do
'pierwszego' elementu, potem mozna przegladac sekwencyjnie. Chodzi o
pierwszy w sensie wyszukiwania, a nie o poczatkowy element w tablicy.
W duzych drzewach dostep do kazdego wezla jest 'niecachowany'.
hash[size+max_search-1];
// wypelnienie hashy
start = element % size; // 'losowy' element
end = start + max_search;
while( start < end ) {
if( hash[start++] == element ) // przeszukiwanie sekwencyjne
return true;
}
return false;
Czyli złożoność sprawdzenia, czy element jest w tablicy gdy go nie ma
jest O(n)? Nie pesymistycznie przy złym hashu i przepełnieniu tablicy,
tylko zawsze?
Koszmarnie.
Szczegoły zależą od procesora. W przybliżeniu: jeden strzał w niecachoaną pamięć
RAM i max_search petli po cachowanej pamięci.
Post by bartekltg
Jak odróżnisz, czy pod hash[x] jest element, czy niezainicjowana
losowa wartość? Typ elementu musi przewidywać nieużywaną kombinację
bitów, którą inicjalizujemy całą tablicę...
Trzeba to jakos rozwiązać. Gdy używam tego do szachów, to mam zapamiętany
klucz równy zero - oczywiście taki klucz teoretycznie może się pojawić w
trakcie pracy programu, ale to nie stanowi problemu. Gdy używam do
bufora danych dyskowych, to mam licznik użyć równy zero. W szachach
max_search mam równe 4, w buforach dyskowych mam równe od 15 do 60.


Mozna tez tak:
hash[size+max_search-1];
start = element % size; // 'losowy' element
end = start + max_search;
while( start < end ) {
if( hash[start] == NULL ) return false;
if( hash[start] == element ) return true;
}
return false;


Albo tak:
hash[size];
i = element % size;
while( hash[i] != NULL && hash[i] != element )
i = (i+1) % size;
return hash[i] != NULL;
Post by bartekltg
http://stackoverflow.com/questions/3176863/concatenating-red-black-trees/3224033#3224033
Brrr.
Nom sieczka.
Post by bartekltg
STL takiej operacji nie udostępnia.
Hmmmm dziwne, uznali że to jest mało potrzebna operacja?


Pozdrawiam
Wojciech Muła
2014-11-04 17:13:27 UTC
Permalink
Post by M.M.
Post by Wojciech Muła
Raczej nie. Dobra funkcja mieszająca jest de facto pseudolosowa, a losowy
dostęp i cache są mocno niekompatybilne.
W niektorych odmianach hash-table dostep losowy jest tylko do
'pierwszego' elementu, potem mozna przegladac sekwencyjnie. Chodzi o
pierwszy w sensie wyszukiwania, a nie o poczatkowy element w tablicy.
Tak wiem, mnie chodziło mi o ten pierwszy dostęp. Jak masz fill-factor sensowny, to listy powinny być krótkie.
Post by M.M.
W duzych drzewach dostep do kazdego wezla jest 'niecachowany'.
No tak, dla dużych danych struktury wiązane to problem.
Post by M.M.
O ile sie nie myle, operacja join na rb-tree zajmuje pesymistycznie
log(n+k), a na hashach min(n,k). Wiec zlaczanie dwoch zbiorow w
jeden bedzie wyraznie szybsze na drzewkach.
Tego o rb nie wiedziałem, dzięki.
Post by M.M.
I z kolei jesli mamy posortowana 'liste', to moze nie trzeba budowac drzewa
poszukiwan binarnych :)
:)

w.

bartekltg
2014-10-28 19:31:56 UTC
Permalink
Post by Borneq
Jaka klasa odpowiada w standardzie c++ drzewu zrównoważonemu, tak jak do
listy stosuję vector<>
Potrzebna jest do implementacji wyszukiwania przecięcia odcinków metodą
zamiatania
Jesteś pewien, że potrzebujesz _drzewa_, a nie kontenera
o określonych niskich zamortyzowanych czasach operacji
i który zna kolejność/umie wyszukiwać?

Drzewa jako takiego potrzebujesz dopiero, jak np w każdym
węźle masz jakaś informację i musisz ją uaktualniać
po równoważeniu drzewa. W większośći przypadków
(i imho do zmiatania prawie na pewno) wystarczą
stlowe kontenery jak wspomniany set.

pzdr
bartekltg
Borneq
2014-10-28 20:10:27 UTC
Permalink
Post by bartekltg
Jesteś pewien, że potrzebujesz _drzewa_, a nie kontenera
o określonych niskich zamortyzowanych czasach operacji
i który zna kolejność/umie wyszukiwać?
Drzewa jako takiego potrzebujesz dopiero, jak np w każdym
węźle masz jakaś informację i musisz ją uaktualniać
po równoważeniu drzewa. W większośći przypadków
(i imho do zmiatania prawie na pewno) wystarczą
stlowe kontenery jak wspomniany set.
Musi być posortowane wg kolejności, czyli mapowanie obiekt->obiekt
odpada. A czy set nie jest na drzewie?
bartekltg
2014-10-28 20:36:42 UTC
Permalink
Post by Borneq
Post by bartekltg
Jesteś pewien, że potrzebujesz _drzewa_, a nie kontenera
o określonych niskich zamortyzowanych czasach operacji
i który zna kolejność/umie wyszukiwać?
Drzewa jako takiego potrzebujesz dopiero, jak np w każdym
węźle masz jakaś informację i musisz ją uaktualniać
po równoważeniu drzewa. W większośći przypadków
(i imho do zmiatania prawie na pewno) wystarczą
stlowe kontenery jak wspomniany set.
Musi być posortowane wg kolejności, czyli mapowanie obiekt->obiekt
odpada.
Czy ja cokolwiek mówiłem o std::map?
Post by Borneq
A czy set nie jest na drzewie?
Jest... prawdopodobnie, Wojciech już to opisał. Ale nie masz dostępu
do drzewa. Nie zbudujesz algorytmów potrzebujących _drzewa_.
Np. dynamicznego drzewa pozycyjnego czy drzewa przedziałowego.

Zbudujesz algorytmu potrzebujące wstawiania, wyszukiwania (także
elementów z przedziału), usuwania, brania następnika/poprzednika...
w czasie logarytmicznym.

pzdr
bartekltg
Borneq
2014-10-28 20:42:30 UTC
Permalink
Post by bartekltg
Zbudujesz algorytmu potrzebujące wstawiania, wyszukiwania (także
elementów z przedziału), usuwania, brania następnika/poprzednika...
w czasie logarytmicznym.
Chyba dla zamiatania powinno to wystarczyć
Post by bartekltg
do drzewa. Nie zbudujesz algorytmów potrzebujących _drzewa_.
Np. dynamicznego drzewa pozycyjnego czy drzewa przedziałowego.
A dynamiczne drzew pozycyjne to nie wstawianie i wyszukiwanie rekordów?
bartekltg
2014-10-28 22:44:01 UTC
Permalink
Post by Borneq
Post by bartekltg
Zbudujesz algorytmu potrzebujące wstawiania, wyszukiwania (także
elementów z przedziału), usuwania, brania następnika/poprzednika...
w czasie logarytmicznym.
Chyba dla zamiatania powinno to wystarczyć
Post by bartekltg
do drzewa. Nie zbudujesz algorytmów potrzebujących _drzewa_.
Np. dynamicznego drzewa pozycyjnego czy drzewa przedziałowego.
A dynamiczne drzew pozycyjne to nie wstawianie i wyszukiwanie rekordów?
Ale nie tylko.
Chcesz na przykład zbudować strukturę danych, która działa
jak słownik (szybkie wstawiani, usuwanie, wyszukiwanie),
a do tego potrafi szybko odpowiedzieć na pytanie, którym
w kolejności elementem jest wyszukany element oraz znaleść
element, który jest k-ty w kolejności. std::set tgo nie potrafi.

Robisz to np drzewem, które przechowuje ilość elementów
w poddrzewie, którego jest korzeniem. Wtedy możesz znaleźć
w czasie logarytmicznym numer, jeśli masz element, i element,
jeśli masz numer. Najczęściej zaglądając na wielkość prawego
poddrzewa.

Jeśli równoważyłeś drzewo (choćby rotacjami) musisz odtworzyć
te dodatkowe informacje w ruszanych wierzchołkach (a nieraz
i na całej drodze do korzenia). Standardowe kontenery tego nie
umożliwiają.
Tak naprawdę nic nie wiesz o ich wewnętrznej strukturze,
nie możesz jej więc wykorzystać.

pzdr
bartekltg
Loading...