Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Szybkie dodawanie i wyszukiwanie elementów

Ostatnio zmodyfikowano 2012-01-09 22:26
Autor Wiadomość
DejaVu
» 2012-01-09 20:04:36
@ison: To nie są równoważne algorytmy.

C/C++
#include <vector>
#include <set>
#include <iostream>
#include <algorithm>
#include <Tools/Time.hpp>

void test1( const std::vector < int >& dane, const std::vector < int >& szukane )
{
    std::vector < int > v;
    v.reserve( dane.size() );
    for( int i = 0; i < dane.size(); ++i )
    {
        if( v.empty() || !std::binary_search( & v[ 0 ], & v[ 0 ] + v.size(), dane[ i ] ) )
        {
            v.push_back( dane[ i ] );
            std::inplace_merge( v.begin(), v.begin() + v.size() - 1, v.end() );
        } //if
        bool bFound = std::binary_search( & v[ 0 ], & v[ 0 ] + v.size(), szukane[ i ] );
    }
}

void test2( const std::vector < int >& dane, const std::vector < int >& szukane )
{
    std::set < int > v;
    for( int i = 0; i < dane.size(); ++i )
    {
        v.insert( dane[ i ] );
        bool bFound = v.find( szukane[ i ] ) != v.end();
    }
}
int main()
{
    std::vector < int > dane;
    std::vector < int > szukane;
    for( int i = 0; i < 1000000; ++i )
    {
        dane.push_back( rand() % 1000 );
        szukane.push_back( rand() % 1000 );
    }
    std::cout << "Dane gotowe." << std::endl;
   
    std::cout << "std::vector + inplace_merge: ";
    tools::CTime stoper;
    stoper.Set( 0 );
    test1( dane, szukane );
    std::cout.setf( std::ios::showpoint );
    std::cout.setf( std::ios::fixed );
    std::cout.precision( 4 );
    stoper.Update();
    std::cout << "  Czas = " << stoper.Get() << "s" << std::endl;
   
    std::cout << "std::set: ";
    stoper.Set( 0 );
    test2( dane, szukane );
    std::cout.setf( std::ios::showpoint );
    std::cout.setf( std::ios::fixed );
    std::cout.precision( 4 );
    stoper.Update();
    std::cout << "  Czas = " << stoper.Get() << "s" << std::endl;
    return 0;
}
Results:
Dane gotowe.
std::vector + inplace_merge:   Czas = 0.1326s
std::set:   Czas = 0.1692s
P-47762
DejaVu
» 2012-01-09 20:10:12
Dodam jeszcze, że jakby porządnie przygotować się do tej operacji i zrobić odpowiednią klasę to w każdym przypadku std::vector będzie lepszy.

PS. Dla testu który przygotowałeś równie dobrze można zrobić algorytm O(1) dodawania i wyszukiwania :p
P-47764
ison
» 2012-01-09 20:38:54
Ciekawy sposób :) Traktowanie vectora jako set, całkiem fajne. Stlowy set jest dosyć wolny więc jak widać nawet fakt, że dodawanie elementu do środka vectora jest w czasie liniowym nie wpływa jakoś rażąco. Ten kod w sumie obrazuje różnicę między dużą stałą w stlowym secie w zamian za wolne dodawanie elementu do środka vectora, ale rozwiązanie mi się podoba :)

nie zawsze vector jednak będzie lepszy
C/C++
for( int i = 0; i < 1000000; ++i )
{
    dane.push_back( rand() % 2000000000 );
    szukane.push_back( rand() % 2000000000 );
}
std::vector + inplace_merge: 722 ms
std::set: 340 ms

//edit
aa, zapomniałem, że rand() zwraca short int :D

C/C++
for( int i = 0; i < 100000; ++i )
{
    dane.push_back( rand() * rand() );
    szukane.push_back( rand() * rand() );
}
wynik:
std::vector + inplace_merge: 4878 ms
std::set: 63 ms
:)

//edit
(ok, zwraca do RAND_MAX ;))
w każdym razie dla dużej ilości różnych liczb set zdecydowanie wygra pojedynek z vectorem
P-47771
DejaVu
» 2012-01-09 21:50:05
Mimo wszystko std::vector jest lepszym rozwiązaniem dla zbiorów nieprzekraczających 200-250 elementów :) Siła std::set to zrównoważone drzewo binarne, którego efekty widać dopiero przy dużej ilości danych w kontenerze. Jeżeli pracujemy na dużej liczbie małych zbiorów to std::set będzie tylko zarzynał proca :)
P-47779
ison
» 2012-01-09 22:05:55
zgadza się, dlatego właśnie przed wyborem algorytmu/czy czegokolwiek tam innego trzeba wziąć pod uwagę wszystkie tego typu czynniki i nie można mówić, że coś jest bezwzględnie lepsze od czegoś innego, takie podsumowanie :D
P-47781
pekfos
» 2012-01-09 22:14:52
Jak wie że nic nie było dodane, to może raz posortować i przeszukać binarnie :P
dodaj do list element
sprawdź czy element+1 występuje na liście
sprawdź czy element-1 występuje na liście
sprawdź czy element+x występuje na liście
sprawdź czy element-x występuje na liście
... ;)
No to raz posortuje i 4 razy sprawdzi a nie za każdym razem :P
P-47782
ison
» 2012-01-09 22:21:27
@up no tak :P ale on tego (te 5 operacji) nie robi raz tylko n razy, i wtedy bardziej opłaca się trzymać cały czas posortowany ciąg tak jak to zaprezentował DejaVu albo wrzucać elementy do seta, który zrobi to za Ciebie
P-47784
DejaVu
» 2012-01-09 22:26:30
Dobra, styka tych wywodów :P myślę, że wyczerpaliśmy temat więc pozwolę sobie go zamknąć.

Wnioski końcowe tego tematu: mamy braki w dokumentacji w standardowych algorytmach C++ ;p
P-47785
1 2 « 3 »
Poprzednia strona Strona 3 z 3