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

sorotowanie zbioru zbiorow

Ostatnio zmodyfikowano 2014-11-16 18:08
Autor Wiadomość
Adik80
Temat założony przez niniejszego użytkownika
sorotowanie zbioru zbiorow
» 2014-02-26 09:55:49
Witam,

Może ktoś ma pomysł na jakiś efektywny algorytm na sortowanie zbioru, składającego sie z podzbiorów?

Na przykładzie wygląda to tak, mamy klase X, mająca N (np. 10 rzędów):

C/C++
struct X
{
    int _a[ 10 ], _b[ 10 ], _c[ 10 ];
    int a( int i ) { return _a[ i ]; }
    int b( int i ) { return _b[ i ]; }
    int c( int i ) { return _c[ i ]; }
};

Oraz kilka funkcji sortujących. Przyjmuja jako parametr klase X (sort1(X& x)), i sortują 10 elementów używając funkcji swap:

C/C++
void X::swap( int l, int r )
{
    swap( _a[ l ], _a[ r ] );
    swap( _b[ l ], _b[ r ] );
    swap( _c[ l ], _c[ r ] );
}

Niestety wyszlo ze 10 rzedow to za malo, wiec dodano kontener, bedacy lista klas X:

C/C++
struct Y
{
    X _x[ 10 ];
    int a( int i ) { return _x[ i / 10 ].a( i % 10 ); }
    int b( int i ) { return _x[ i / 10 ].b( i % 10 ); }
    int c( int i ) { return _x[ i / 10 ].c( i % 10 ); }
};

I teraz pytanie, jak to efektywnie posortowac, gdy niema mozliwosci modyfikacji algorytmów sortowania?

Mozna posortowac kazdy podzbior, a nastepnie sciagac 1sze elementy zbioru do jakiegoś pomocniczego i sortować, wtedy 1szy w pomocniczy będzie na swoim miejscu, ale będzie to wymagało ~100 sortowań, wiec szukam jakiegoś bardziej efektywnego sposobu

P-105282
DejaVu
» 2014-02-26 10:02:09
Opisz lepiej swój problem. W każdym razie sortowanie nie wymaga żadnej filozofii:
C/C++
bool funkcja_sortujaca( const TYP_DANYCH & a, const TYP_DANYCH & b )
{
    return a < b; //tu możesz wcisnąć dowolne wyrażenie (operujące tylko i wyłącznie na elementach jakie trafią poprzez argument)
}
std::sort( kontener.begin(), kontener.end(), funkcja_sortujaca );
P-105283
Adik80
Temat założony przez niniejszego użytkownika
» 2014-02-26 11:41:37
OK,

Wiec w skrocie mam liste tablic. Zarowno lista jak i tablica sa owiniete w klase (W przykadzie z pierwszego postu lista to klasa Y, tablica to klasa X).

Sa tez gotowe funkcje do sortowania tablic, ale sortuja one tylko tablice X, a ja potrzebuje posortowac cala liste Y. (I nie mozna modyfikowac tych funkcji)

Czyli przykladowo mam:

{ {3, 1, 4}, {1, 9, 7}, {8, 2, 3} }

i moge wyolac sortowanie dla kazdego z podzbiorow:

{ {1, 3, 4}, {1, 7, 9}, {2, 3, 8} }

Ale poszukuje pomyslu na efektywny algorytm mieszania/sortowania podzbiorow by posortowac cala liste:

{ {1, 1, 2}, {3, 3, 4}, {7, 8, 9} }

Poniewaz funkcje sortujace nie sa trywialna, za optymalne uwazam wywolywanie funkcji jak najmniejsza ilosc razy.

Jakies pomysly?
P-105286
Marekszuwarek
» 2014-02-27 11:11:40
Załóżmy że mamy klasy X i Y najpierw klasa X potem klasa Y i sortujesz wynik tak jak np @up 2 tylko że
z mala zmianą:
C/C++
bool funkcja_sortujaca( const TYP_DANYCH & a )
{
    return x < y; // taki przyklad Może tu być inne wyrażnenie
}
std::sort( kontener.begin(), kontener.end(), funkcja_sortujaca );
P-105319
Adik80
Temat założony przez niniejszego użytkownika
» 2014-02-27 13:11:27
Jeszcze raz: Jest dostepna TYLKO funkcja sortujaca X (kilka bibliotek, kazda ma zdefiniowana funkcje sort(&X))

To jest zadanie typu: "Masz 100 kulek roznej wagi, oraz maszyne sortujaca do ktorej mozna polozyc 10 kulek. Podaj algorym posortowania wszystkich kulek uzywajac jak najmniejszej ilosci wazen".

P-105321
DejaVu
» 2014-02-27 15:00:30
W Twoim kodzie po pierwsze X nie jest funkcją sortującą, a po drugie zaimplementowane metody nie mają nic wspólnego z sortowaniem. Poza tym Twój przykład jest niemożliwy do realizacji używając przedstawionej przez Ciebie implementacji X::swap. Czytaj: nie istnieje taka sekwencja wywołań X::swap, która dałaby wynik:
{ {1, 3, 4}, {1, 7, 9}, {2, 3, 8} }
z postaci:
{ {3, 1, 4}, {1, 9, 7}, {8, 2, 3} }.


PS. Nie istnieje szybszy algorytm niż counting-sort, który ma złożoność O(n).
PSS. Nie posortujesz danych w czasie szybszym niż O(n*log(n)) jeżeli zbiór wartości występujących w zbiorze nie będzie z góry określony (czego wymaga counting-sort).
PSSS. Jedyne co możesz osiągnąć dzieląc zbiory na podzbiory to gorszą złożoność obliczeniową sortowania.
PSSSS. Struktura Y jest bezsensowna - tworzysz 'dzięki' niej 30 tablic 10-elementowych.
P-105328
Adik80
Temat założony przez niniejszego użytkownika
» 2014-02-27 16:28:49
Prawdziwy kod jest ciut bardziej skomplikowany, stad ten przykladu z X. Fakt, X nie jest funkcja sortujaca tylko klasa posiadajaca w interfejsie funkcje swap uzywana przez funkcje sortujace:

C/C++
class XInterface
{
    virtual void swap( int l, int r ) = 0; // zamien miejscami wartosci w rzedach l i r
};

class X
    : XInterface
{
    CRow _row[ 10 ]; // klasa ma jakas tabelke powiedzmy z 10 rzedami,
    void swap( int l, int r ) { CRow temp = _row[ l ]; _row[ l ] = _row[ r ]; _row[ r ] = temp; }
};

void sort( X & x ) // <- PRZYKLADOWY SORT POKAZUJACY UZYCIE SWAP
{
    for( int i = 0; i < 9; ++i )
    for( j = i + 1; j < 10; ++j )
    if( jakas_logika( x._row[ i ], x._row[ j ] ) )
         x.swap( i, j );
   
}

Klasa Y ma liste X i mapowanie indexow (w przykladzie uzylem tablicy by uproscic zapis). Generalnie Y sluzy do mapowania indexow do klas X:
C/C++
class Y
{
    std::vector < X *> _listaXow;
    std::map < int, std::pair < int, int > > _indexy;
    int _rzedy;
    add( X * x )
    {
        for( int i = 0; i < x.ileMaRzedow(); ++i )
        {
            ++_rzedy;
            _indexy.push_back( std::make_pair( _listaXow.size(), i ) );
        }
        _listaXow.push_back( x );
    }
}

Dziala to tak ze majac 100 klas X, kazda ma tablice z 10 elementami, dodaje sie ja do Y i uzywa jakby to byla jedna tabelka z 1000 elementow:

C/C++
X x1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
X x2 = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
x1[ 11 ] <- poza zakresem
Y y = x1 + x2;
y[ 11 ] <- zwroci 11

To wszystko jest przykladowy kod. Problem jest przy sortowaniu, funkcja sortujaca przyjmuje X, i ma zahardcodowane sortowanie tablicy 10 elementowej. wiec potrzebuje zaimplementowac algorym ktory posortuje liste X (kazdy X sortuje osobno, ztad przyklad:

{ {1, 3, 4}, {1, 7, 9}, {2, 3, 8} }
// wolanie sort 3 razy dla: X={1, 3, 4}, X={1, 7, 9} X={2, 3, 8}
{ {3, 1, 4}, {1, 9, 7}, {8, 2, 3} }.

nastepnie podzieli wszystkie X, zbuduje nowy X i posortuje (np nastepnym krokiem moze byc: "wez 1sze elementy z kazdego X'a i posrtuje"):
{ {3, 1, 4}, {1, 9, 7}, {8, 2, 3} }.  <- 1sze elementy do temp'a X={3,1,8} -> sortowanie -> {1,3,8} -> wstaw spowrotem -> { {1,1,4}, {3,9,7}, {8,2,3}}

Czyli:
1) Nie szukam poprawek do klas X i Y, to sa tylko przyklady.
2) Nie da rady porownac w prosty sposob 2 elementow (mozna przekazujac X z 2ma elemntami, ale to najgorsze rozwiazanie)
3) Zaden algorym counting-sort nie wchodzi w gre. Mozna uzywac tylko funkcji sort, czyli to typowy divide & conquer
4) Ja nie podzielime zbioru na podzbiory tylko chce je polaczyc (jako Y)
5) Nie dam rady wkleic calego kodu (jest go za duzo) i nie szukam implementacji tylko algorytmu.

Na chwile obecna mam algorytm oparty na drzewach. Buduje z X'ow drzewa, gdzie wezel jest lepszy od potomkow, a nastepnie w kolejnych iteracjach merguje drzewa (do sortowania wezly z iloscia dzieci >1). Po N iteracjach dostaje 1 drzewo, gdzie kazdy wezel ma dokladnie 1 dziecko (liste), ale zastanawiam sie czy jest to optymalne rozwiazanie.
P-105334
DejaVu
» 2014-02-27 16:57:42
W takim razie nie masz możliwości użycia std::sort w swoim problemie, ponieważ:
1. Nie masz swobodnego dostępu do danych poprzez referencję.
2. Musisz wykorzystywać metodę X::swap, co już się z definicji kłóci z ideą std::sort.

Zaimplementuj więc samodzielnie algorytm QuickSort-a, który będzie używał tych funkcji.
P-105335
« 1 » 2
  Strona 1 z 2 Następna strona