reemplaza.cpp
// $Id$
/*
COMIENZO DE DESCRIPCION
Dada una lista de enteros {\tt L} y dos listas {\tt SEQ} y
{\tt REEMP} escribir una funci\'on {\tt
void reemplaza (list<int> &L, list<int> &SEQ, list<int> &REEMP)}
que busca todas las secuencias de {\tt SEQ} en {\tt L} y las
reemplaza por {\tt REEMP}. Por ejemplo, si
L=(1 2 3 4 5 1 2 3 4 5 1 2 3 4 5), SEQ=(4 5 1) y REEMP=(9 7 3),
entonces despues de llamar a {\tt reemplaza} debe quedar
L=(1 2 3 9 7 3 2 3 9 7 3 2 3 4 5). Este procedimiento tiene
un efecto equivalente a la funci\'on {\tt reemplazar} de los
editores de texto.
[Tomado el 1er parcial, 16 abril 2002]
keywords: lista
FIN DE DESCRIPCION
*/
// -----------------------------------------------------------------
/* SOlUCION:
Se sugiere el siguiente algoritmo. Recorrer la lista L con la
posicion P y la SEQ con la posicion Q, hasta que P llegue al fin
de L. En todo momento se mantiene una cola C con los ultimos
elementos de L que coinciden con los de SEQ. En el siguiente
paso se pueden dar tres posibilidades:
1) Si llegamos al fin de SEQ, entonces toda la lista SEQ estaba
en L y, por lo tanto, insertamos la lista REEMP en la posicion
P de L. Tambien vaciamos la cola C;
2) Si el elemento en Q es igual al que esta en P entonces
suprimimos el elemento de L y lo ponemos en la cola C.
Tambien avanzamos la posicion Q en REEMP;
3) Si el elemento en Q no es igual al que esta en P, entonces
insertamos toda la cola C en la lista L en la posicion P y
reseteamos la posicion Q al principio de SEQ.
*/
// -----------------------------------------------------------------
#include <list>
#include <queue>
#include <iostream>
#include "./util.h"
using namespace std;
// -----------------------------------------------------------------
void reemplaza1 (list <int> & L,
list <int> & SEQ,
list <int> & REEMP) {
queue<int> C ;
list<int> :: iterator p, q, r;
list<int> H ;
// copia REEMP en la lista auxiliar H
H.clear ();
r = REEMP.begin () ;
while (r != REEMP.end () ) { H.insert (H.begin (),*r) ; r++ ; }
// Inicializa posiciones
p = L.begin ();
q = SEQ.begin ();
// recorre lista L
while ( p != L.end() ) {
if ( q == SEQ.end () ) {
// 1) llegamos al fin de SEQ pues todo SEQ esta en la lista L
// vaciamos la cola C
while ( !C.empty () ) C.pop ();
// insertamos REEMP en la lista L
r = H.begin () ;
while (r != H.end () ) { p = L.insert (p++,*r); r++ ; }
// reseteamos la posicion Q en la lista SEQ
q = SEQ.begin (); }
else if (*p == *q) {
// 2) Hay otro elemento en la lista L igual al de SEQ
// por lo que lo ponemos en la cola C
C.push (*p) ;
// lo suprimimos en L y avanzamos en SEQ
p = L.erase (p);
q++ ; }
else {
// 3) los elementos no son iguales
while ( !C.empty () ) {
p = L.insert ( p, C.front () );
C.pop ();
p++;
} // end while
p++;
} // end if
} // while
while ( !C.empty() ) {
p = L.insert ( p, C.front () );
C.pop ();
p++;
} // end while
}
// -----------------------------------------------------------------
// Variante sin el uso de una cola
// Pero, como siempre, sin usar el operador "--"
//
// Se recorre mientras no sea fin de la lista L con el iterador P y,
// cada vez que aparezca el primer elemento de SEQ, se la registra
// con la posicion auxiliar Q. Luego copiamos P en T, y vamos
// avanzando T y Q simultaneamente mientras, o bien no lleguemos
// al final de L o de SEQ, o bien cuando no esta todo SEQ en el
// tramo analizado. Si toda la secuencia SEQ se encontro en ese
// tramo, entonces inicializamos T en Q (en donde empezaba SEQ)
// y R en comienzo de REEMP. Vamos suprimiendo el elemento de L
// apuntado por T, insertamos el apuntado por R y avanzamos T y R.
// Finalmente actualizamos P (el cual recorre L actual) y seguimos
// explorando.
void reemplaza2 ( list <int> & L,
list <int> & SEQ,
list <int> & REEMP){
list <int> :: iterator p, q, r, t;
bool esta ;
p = L.begin ();
while ( p != L.end () ) {
r = SEQ.begin () ;
q = p ; // recordamos donde empezaria (quizas) SEQ en L
t = p ; // inicializamos T en P
esta = true ; // somos optimistas
while ( r != SEQ.end () && t != L.end () ) {
if ( *r == *t ) { // seguimos encontrando SEQ en L
r++ ;
t++ ; }
else {
esta = false ; // la secuencia SEQ es incompleta
break ;
} // end if
} // end while
if (esta == true) {
r = REEMP.begin ();
t = q ; // inicia en el lugar donde empezo SEQ
while ( r != REEMP.end () ) { // borra e inserta
t = L.erase (t) ; // suprimimos y actualizamos
L.insert (t, *r) ; // inserta un elemento de SEQ en L
r++ ; // avanzo en SEQ
} // end while
p = t ; // actualizo iterador del lazo principal
} // end if
p++ ; // avanzo
} // end while
} // end void
// -----------------------------------------------------------------
int main () {
list<int> L, SEQ, REEMP;
int v [] = {8,4,5,1,2,3,4,5,9,1,-1};
int s [] = {4,5,1,-1};
int r [] = {9,7,3,-1};
// 1ra variante
cout << endl ;
cout << "1ra variante: usando una cola auxiliar" << endl ;
L.clear(); insertl (L, v, -1);
SEQ.clear(); insertl(SEQ, s, -1);
REEMP.clear(); insertl(REEMP, r ,-1);
cout << "L : "; printl (L);
cout << "SEQ : "; printl (SEQ);
cout << "REEMP: "; printl (REEMP);
reemplaza1 (L, SEQ, REEMP);
cout << "reemplaza1: "; printl (L);
// 2da variante
cout << endl ;
cout << "2da variante: recordando donde empieza SEQ " << endl ;
L.clear(); insertl(L, v, -1);
SEQ.clear(); insertl(SEQ, s, -1);
REEMP.clear (); insertl (REEMP, r ,-1);
cout << "L : "; printl (L);
cout << "SEQ : "; printl (SEQ);
cout << "REEMP: "; printl (REEMP);
reemplaza2 (L, SEQ, REEMP);
cout << "reemplaza2: "; printl (L);
cout << endl ;
return 0 ;
} // end main
// -----------------------------------------------------------------
Generated by GNU Enscript 1.6.6.