1. I/O
En C++, la biblioteca que maneja la entrada y salida es iostream. Sin em-
bargo, siempre es posible usar la biblioteca de C cstdio para realizar tales tareas.
Es importante saber en qué se diferencian y cuándo debemos usar una y no otra.
La biblioteca iostream de C++ nos permite realizar lecturas/escrituras de
forma más versátil, pues no es necesario espeficar el tipo de dato al momento
de hacer la lectura o escritura.
Por ejemplo, para leer cualquier variable de tipo T, se puede usar el siguiente
código:
T x;
c i n >> x ;
T x = T( ) ;
c o u t << x ;
1
int x ;
s c a n f ( ” %d” , &x ) ;
%d para int
%f para float
%s para char * o char[ ]
%lf para double
%c para char
Algo que se debe considerar al momento de escoger usar uno u otro método
para leer y escribir es la velocidad. En este sentido, la biblioteca de C otorga
mucho mejor rendimiento en tiempo que la de C++, siendo, en algunos casos,
la diferencia entre un problema aceptado y uno rechazado por exceso de tiempo.
2. STL
Un maratón donde no se use STL, es un maratón donde se pierde MUCHO
tiempo. Existen varias estructuras y algoritmos de la STL que son especialmente
útiles en un maratón. A continuación, algunas de ellas.
2.1. sort
Disponible a partir de la biblioteca algorithm, esta función realiza ordena-
ción sobre contenedores de acceso aleatorio (vectores, arreglos, strings) usando
quicksort con tiempo promedio de O(NlogN).
El siguiente es un ejemplo de su uso, tanto en estructuras con iteradores,
como en estructuras si ellos.
s t r i n g s t r = ” Navi e s t a en p e l i g r o ! ” ;
s o r t ( s t r . b e g i n ( ) , s t r . end ( ) ) ;
2
int a r r [ 6 ] = {8 , 2 , 4 , 1 , 3 , 6 } ;
s o r t ( a r r , a r r +6) ;
Por defecto, sort ordena de menor a mayor, pero se puede usar para que lo
haga de forma distinta. Por ejemplo:
s t r i n g s t r = ” Navi e s t a en p e l i g r o ! ” ;
s o r t ( s t r . r b e g i n ( ) , s t r . rend ( ) ) ; // ordena de mayor a menor
int a r r [ 6 ] = {8 , 2 , 4 , 1 , 3 , 6 } ;
s o r t ( a r r , a r r +6 , g r e a t e r <int >() ) ; // ordena de mayor a menor
2.2. vector
Pocas estructuras son tan útiles como vector<T>, pues ofrece las ventajas
del dinamismo de las listas y del acceso aleatorio y veloz de los arreglos estáti-
cos. Un vector<T> es un arreglo dinámico que pudiera crecer dependiendo de
las necesidades del programador. Al igual que todas las estructuras en C++,
vector<T> es una plantilla (template).
El siguiente es un ejemplo de cómo usarlo, tanto en el caso que no se conozca
el tamaño de antemano, como en caso que sı́.
v e c t o r <int> v1 ;
int next ;
// l e e r e n t e r o s h a s t a que n e x t s e a d i s t i n t o de 0
while ( s c a n f ( ” %d” , &n e x t ) !=EOF && n e x t ) {
v1 . p u s h b a c k ( n e x t ) ;
}
int n ;
c i n >> n ;
v e c t o r <s t r i n g > v2 ( n ) ; // c r e a un v e c t o r de n p o s i c i o n e s
f o r ( i n t i =0; i <v2 . s i z e ( ) ; ++i ) {
// l e o n v e c e s c o l o c a n d o e l r e s u l t a d o en e l a r r e g l o
c i n >> v2 [ i ] ;
}
2.3. map
map<K, T> es un arreglo asociativo implementado con árboles rojo-negro.
En pocas palabras: permite almacenar objetos cuyas claves no son enteras.
Un uso común de esta estructura es un diccionario. Por ejemplo:
map<s t r i n g , s t r i n g > z D i c t ;
3
z D i c t [ ”Deku Tree ” ] = ” V e n e r a b l e a r b o l l o c a l i z a d o en K o k i r i ” ;
z D i c t [ ”Ganon” ] = ” Bicho malo que hay que matar ” ;
z D i c t [ ” Z e l d a ” ] = ” P r i n c e s a que hay que r e s c a t a r ” ;
z D i c t [ ” Link ” ] = ” Heroe d e l tiempo ” ;
Hay que tener cuidado con el uso de la estructura map<K, T>, porque crea
las entradas aún cuando sólo estemos consultando su existencia.
El siguiente ejemplo ejemplificará este caso:
map<s t r i n g , s t r i n g > z D i c t ;
// l o l l e n a m o s con t e r m i n o s a p a r e n t e m e n t e a l e a t o r i o s . . .
// MAL
i f ( z D i c t [ ” Mickey Mouse” ] == ” ” ) { // e x i s t e Mickey en e l z D i c t ?
c o u t << ” El r a t o n no e s t a en c a s a ” << e n d l ;
}
// BIEN
i f ( z D i c t . count ( ” Mickey Mouse” ) == 0 ) {
c o u t << ” El r a t o n no e s t a en c a s a ” << e n d l ;
}
Por último, es importante saber que dado que map<K, T> es una estructura
que usa un árbol binario balanceado para realizar las asociaciones, las claves
(K) que se usen deben poder tener una relación de orden. En caso que no la
tengan, siempre es posible sobrecargar el operador menor que para que exista
una relación de orden.
Por ejemplo, supongamos que queremos indexar personas, y de ellas tenemos
su nombre y edad, la sobrecarga se realizarı́a de la siguiente forma:
class persona {
public :
s t r i n g nombre ;
i n t edad ;
p e r s o n a ( ) {}
// s o b r e c a r g a
bool operator <(const p e r s o n a& o t h e r ) const {
i f ( nombre == o t h e r . nombre )
return edad < o t h e r . edad ;
return nombre < o t h e r . nombre ;
}
};
Esta sobrecarga también es útil cuando deseamos hacer sort o usar la clase
set<T>.
4
2.4. Pilas y colas
Aún cuando las pilas y las colas pueden ser simuladas con listas enlazadas o
arreglos, la STL provee su propia implementación de ellas optimizada para las
situaciones tı́picas de éstas.
Apilar
Ver el tope
Desapilar
¿Está vacı́a?
Por otro lado, queue<T> representa una cola. Tiene cuatro operaciones
básicas:
Encolar
Ver el frente
Desencolar
¿Está vacı́a?
// V o l t e a r una p i l a s i n u s a r e s t r u c t u r a s a u x i l i a r e s
#i n c l u d e <i o s t r e a m >
#i n c l u d e <s t a c k >
#i n c l u d e < s t d l i b . h>
using namespace s t d ;
// L l e n a r l a p i l a l a p i l a con e n t e r o s a l e a t o r i o s
void l l e n a r ( s t a c k <int> &s t , i n t n ) {
f o r ( i n t i =0; i <n ; ++i )
s t . push ( rand ( ) ) ;
}
// V o l t e a r l a p i l a
void v o l t e a r ( s t a c k <int> &s t ) {
f o r ( i n t i=s t . s i z e ( ) −1; i >1; −−i ) {
i n t t o p e = s t . top ( ) ;
s t . pop ( ) ; // OJO, s i e m p r e h a c e r POP a l d e s a p i l a r !
m a n d a r a l f o n d o ( tope , s t , i ) ;
}
5
}
// Manda n p o s i c i o n e s a l f o n d o un e l e m e n t o
void m a n d a r a l f o n d o ( i n t e , s t a c k <int> &s t , i n t n ) {
i f ( n==0)
s t . push ( e ) ;
else {
i n t aux = s t . top ( ) ; s t . pop ( ) ;
m a n d a r a l f o n d o ( e , s t , n−1) ;
s t . push ( aux ) ;
}
}
void m o s t r a r ( s t a c k <int> s t ) {
while ( ! s t . empty ( ) ) {
c o u t << s t . top ( ) << e n d l ;
s t . pop ( ) ;
}
c o u t << ”−−−−” << e n d l ;
}
i n t main ( ) {
s t a c k <int> s t ;
l l e n a r ( st , 10) ;
mostrar ( s t ) ;
voltear ( st ) ;
mostrar ( s t ) ;
return 0 ;
}
const i n t MAXV = 5 0 0 ;
bool m a t r i z [MAXV] [MAXV] ;
6
}
// Declaramos y l l e n a m o s e l v e c t o r de e n t e r o s
v e c t o r <int> v ( 1 0 ) ;
f o r ( i n t i =0; i <v . s i z e ( ) ; ++i ) {
v [ i ] = rand ( ) ;
// . . . y l o imprimimos
c o u t << v [ i ] << e n d l ;
}
// Un s e p a r a d o r
c o u t << ”−−−−−” << e n d l ;
// Declraramos y l l e n a m o s l a c o l a de p r i o r i d a d
p r i o r i t y q u e u e <int> pq ;
f o r ( i n t i =0; i <v . s i z e ( ) ; ++i )
pq . push ( v [ i ] ) ;
// Ahora vaciamos l a c o l a de p r i o r i d a d
f o r ( i n t i =0; ! pq . empty ( ) ; ++i ) {
v [ i ] = pq . top ( ) ;
c o u t << v [ i ] << e n d l ;
pq . pop ( ) ;
}
2.6. Iteradores
A excepción de vector<T> y string, la mayorı́a de las estructuras contene-
doras en C++ deben ser recorridas con iteradores.
Usar iteradores es más sencillo de lo que parece. Tengamos por ejemplo, un
set de enteros:
7
s e t <int> s ; // p a r e c i d o a map , p e r o K = T
// l o l l e n a m o s con c o s a s a l e a t o r i a s
f o r ( i n t i =0; i <100; ++i )
s . i n s e r t ( rand ( ) ) ;
// ahora l o r e c o r r e m o s
f o r ( s e t <int > : : i t e r a t o r i t e r = s . b e g i n ( ) ; i t e r != s . end ( ) ; i t e r ++)
c o u t << ∗ i t e r << e n d l ;
2.7. ¡Importante!
Para usar cada una de estas estructuras, es necesario incluir la biblioteca
adecuada, i.e., el nombre de la estructura. Por ejemplo:
8
3.2. Depurar el programa
En caso que falle el programa, siempre se tiene la opción de depurarlo con
gdb. Para ello se escribe en consola:
gdb programa
run input.in
continue
where
break 35
Podemos seguir paso a paso el curso del programa con el comando step e
imprimir el estado de las variables con print.
Typesed in LATEX