A Standard Library a reverse fuggvenyt csak BidirectionalIterator es RandomAccessIterator -ra tartalmazza. Van-e valakinek otlete, hogyan lehet megoldani a feladatot ForwardIterator-okra minnel gyorsabban.
En egy nem tul szep rekurziv megoldast talaltam ~2N muveletigennyel.
template<class ForwardIterator>
void reverse(ForwardIterator first,ForwardIterator last);
Tehat a feladat : helyben forditas, Forward bejarokkal. Nem hazi. :)
gabor
- 5788 megtekintés
Hozzászólások
Kódot nem tudok, de algoritmikusan a reverse iterátor létrehozásakor be kell járnod az egész forward iterátort, el kell tenni mindent egy listába, és onnan olvasni visszafele, ha lép a reverse iterátor.
- A hozzászóláshoz be kell jelentkezni
Szerintem itt nem tudsz hasznalni reverse iterator-t.
- A hozzászóláshoz be kell jelentkezni
STL-hez nem értek, C#-ból indultam ki. Ott az iterálás egy interfésszel megy (IEnumerable), vagyis az iterátor egy osztály példány. Ennek a konstruktorában lehet felépíteni a teljes listát, aztán a MoveNext metódusban visszafele lépegetni.
De nem is kell osztályt csinálni, elég egy segédfüggvény, ami beolvas egy iterátort egy listába, és visszaadja annak a reverse iterátorát.
- A hozzászóláshoz be kell jelentkezni
Egy forward iteratornak nincs reverse iterator-ra. Hogyha csinalsz egy listat akkor mar nem helyben forditas. Persze ugy lehetne.
- A hozzászóláshoz be kell jelentkezni
Na de hogy tudsz helyben megfordítani valamit, aminek nem is tudod, hol a vége? Így lehetetlent kérsz. Írhatok egy iterátort, ami random mennyiségű X betűt állít elő, muszáj végigolvasnod, hogy meg tudd fordítani. Ha egy iterátor csak egyirányú, akkor jó esetben okkal az.
- A hozzászóláshoz be kell jelentkezni
Gondolj egy sima egyiranyu lancolt listara, de ugy hogy nem ismered a szerkezetet. Tehat altalanosan kell megoldanod azzal a felulettel amit az ForwardIterator-on keresztul elersz.
- A hozzászóláshoz be kell jelentkezni
Csakhogy egy adatszerkezet lehet vegtelen is, es letezhet hozza ForwardIterator. (Mint az emlitett egyiranyu lancolt lista, ahol az utolso elem nem NULL-ra mutat, hanem a lista valamely masik elemere)
A helyes valasz, hogy altalanos esetben a ForwardIterator-t nem lehet megforditani. A "helyben" valo megforditashoz meg a vegessegen kivul kell egy random access mutator is (ami pl. read only adatszerkezeteknel nincsen).
- A hozzászóláshoz be kell jelentkezni
Nem hazi. :)
Attól még elég hülye feladat :)
- A hozzászóláshoz be kell jelentkezni
Szia,
Egy hülye kérdés: Mennyire kell helyben? Egy ideiglenes listát nem tudsz generálni, és oda felépíteni a fordított sorrendet? (lista alatt az Iteratorral bejárt objektumra gondolok....)
Mert akkor könnyít, ha elkezded az első elem _elé_ beszúrni a többi elemet, félig kártyarendezésként megoldva :)
Utána pedig visszapakolhatod természetesen az eredeti listába...
Ennél gyorsabb sajnos nincs, és per pill a végig járogatáson túl nem látok "gyorsabbat"...
Üdv,
LuiseX
- A hozzászóláshoz be kell jelentkezni
Altalanos stl jellegu algoritmusrol van szo. Tehat low-level szinten. Nem hasznalhatsz tarolokat, iteratorokkal dolgozol es azok alapmuveleteivel, ++, *, =.
- A hozzászóláshoz be kell jelentkezni
Szia,
Akkor sajnos nem tudok rá optimálisat, sajnos az iterátor műveletek eléggé szegényesek... Esetleg egy "kiherélt egyszerű cserés rendezés" szerűséget lehet, de az sem a legjobb...
Amire gondolok, az az, hogy végig lépkedsz az első, és utolsó elem között, második, és utolsó előttit tárolod, majd felcseréled az érintett két elemet, és kijelölöd elsőnek, illetve utolsónak a két korábban tárolt elemet...
Ugyanezt játszod végig, amíg "középre nem érsz"... Ebből ha jól gondolom elsőre két lehetőséged van: a két iterátor megegyezik --> páratlan számosságú elemhalmazod volt, illetve ha az első elem utáni pont az utolsó elem... Ekkor természetesen még cserélni kell, de fontos, hogy ezt a végpontot is figyeld (sajnos könnyen lehet reverse-elni az eddigi munkát, ha nem veszed számításba, és egy bájos exception fog megállítani legfeljebb :D :D )
Így kapásból erre tudok még gondolni, de itt is "alkalmazol tárolót"...
Am. ha perverziód a rekurzió, ez az algoritmus úgyis könnyen implementálható, de ciklusban is, amelyik szimpatikusabb :)
Üdv,
LuiseX
- A hozzászóláshoz be kell jelentkezni
En 2 megoldast talaltam a feladatra.
Az egyik ami O(n*n) es alul a kollega is leirt, hogy mindig ellepkedunk az n, n-1 ... elemekre es kicsereljuk az 1, 2, ... elemekkel.
A masik 2n-es, de stack gyilkos :
template<class Iterator>
bool Reverse_helper_forward(Iterator &first,Iterator last,Iterator end)
{
if (++last==end) return true;
if (Reverse_helper_forward(first,last,end))
{
if (first==last) return false;
std::iter_swap(first,last);
if (++first!=last) return true;
}
return false;
}
template<class Iterator>
void Reverse(Iterator first,Iterator last)
{
if (first==last) return;
Reverse_helper_forward(first,first,last);
}
De akkor valsz a 2 kozott nincs atmenet. :)
- A hozzászóláshoz be kell jelentkezni
Szia,
Végig gondoltam a második megoldásod, és, hogy őszinte legyek, nagyon szép... Legalábbis nekem tetszik :)
Bár tény, tényleg stack gyilkos :D
Üdv,
LuiseX
- A hozzászóláshoz be kell jelentkezni
Köszönöm.
Egyébbként Prolog az egész világ. :)
- A hozzászóláshoz be kell jelentkezni