PDF(handout) - Universidad de Buenos Aires

Anuncio
Menú del dı́a
Resolviendo problemas del TP
1
Lenguaje
C++ STL
C++ STL - Pilas y Colas
C++ STL - Conjuntos y Diccionarios
Trucos y Tips
2
Mediciones
3
Gráficos
Laboratorio de Algoritmos y Estructuras de Datos III
Departamento de Computación
Facultad de Ciencias Exactas y Naturales
Universidad de Buenos Aires
27 de Agosto de 2010
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Lenguaje
27 de Agosto de 2010
1 / 56
Labo de Algo III (Sabi)
C++ STL
Resolviendo problemas del TP
Lenguaje
C++ STL
27 de Agosto de 2010
2 / 56
C++ STL
C++ STL - Estructuras de datos
Estructuras de datos:
Arrays dimensionables (de longitud variable) (vector)
Pilas (stack)
La Standard Template Library es un conjunto de estructuras y
algoritmos comunes, que ya están hechos.
Colas (queue)
Documentación: http://www.sgi.com/tech/stl/,
http://www.cppreference.com/.
Conjunto y Diccionario (sobre árbol, sobre hash) (set, map,
hash set, hash map)
Conjunto sobre bits (bitset)
Multiconjuntos y Multidiccionarios. (multiset, multimap,
hash multiset, hash multimap)
Listas enlazadas (doble y simplemente enlazadas) (list y slist)
Heap o parva (priority queue)
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
3 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
4 / 56
Lenguaje
C++ STL
Lenguaje
C++ STL
C++ STL - Algoritmos
Importante
Algoritmos:
Ordenamiento (sort, merge, make heap, sort heap, etc)
Mirar la documentación
Para buscar la especificación de las operaciones
Búsqueda secuencial o binaria (find, binary search, lower bound,
upper bound)
Para buscar la complejidad de las operaciones
Reduce (min element, max element)
Para ver si está implementada la operación que necesitamos de la
estructura (o un conjuntito que lo realice).
Permutaciones (next permutation, prev permutation,
accumulate)
Otros: reverse, rotate, unique
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Lenguaje
27 de Agosto de 2010
5 / 56
Labo de Algo III (Sabi)
C++ STL - Pilas y Colas
Resolviendo problemas del TP
Lenguaje
27 de Agosto de 2010
6 / 56
C++ STL - Pilas y Colas
Pilas
Colas
Una pila es una colección de elementos con orden con estas operaciones:
Una cola es una colección de elementos con orden con estas operaciones:
push: Agrega un elemento encima de todos los demás.
push: Agrega un elemento detrás de todos los demás.
pop: Retira el elemento de arriba de todo.
pop: Retira el elemento de adelante.
top: Devuelve el elemento de arriba de todo.
front: Devuelve el elemento de adelante.
empty: Dice si la pila está vacı́a.
empty: Dice si la cola está vacı́a.
En C++:
En C++:
stack<int> s:
s.push(3); s.push(1); s.push(2);
while(!s.empty()) {
cout << s.top() << " ";
s.pop();
}
queue<int> q:
q.push(3); q.push(1); q.push(2);
while(!q.empty()) {
cout << q.front() << " ";
q.pop();
}
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
7 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
8 / 56
Lenguaje
C++ STL - Conjuntos y Diccionarios
Lenguaje
Conjuntos
C++ STL - Conjuntos y Diccionarios
C++ STL con pretenciones
Un conjunto es una colección de elementos distintos y sin orden con
estas operaciones:
insert: Agrega un elemento al conjunto (si no está).
Magia oculta
find: Devuelve un iterador al elemento buscado.
¡Los conjuntos no sólo sirven para insertar y preguntar pertenece!
erase: Elimina un elemento del conjunto.
¡Los iteradores no sólo sirven para iterar!
empty: Dice si el conjunto está vacı́o.
Los algoritmos pre-hechos, aunque sean fáciles de programar por
nosotros mismos, alivianan el código (menos informe, menos
debuggeo, menos corrección...).
En C++:
set<int> c:
c.insert(1); c.insert(4); c.insert(2); c.insert(3);
for(set<int>::iterator it = c.begin(); it != c.end(); ++it) {
cout << *it << " ";
}
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Lenguaje
27 de Agosto de 2010
9 / 56
Labo de Algo III (Sabi)
C++ STL - Conjuntos y Diccionarios
Resolviendo problemas del TP
Lenguaje
C++ STL - Iteradores
27 de Agosto de 2010
10 / 56
C++ STL - Conjuntos y Diccionarios
C++ STL - Iteradores - Ejemplo
Tenemos un vector<int> v ordenado con los siguientes elementos:
v = 3 5 5 6 8 8 10
Las funciones lower bound y upper bound permiten encontrar un
elemento o un rango dentro de un contenedor ordenado:
lower bound dice el menor lugar donde se puede insertar ordenado
un elemento dado.
Un vector<> o array de C con sus elementos ordenados.
upper bound dice el mayor lugar donde se puede insertar ordenado
un elemento dado.
Un set<>...
...y sus variantes: map<>, multiset<>, multimap<>
Obs: Si el elemento no está, ambas dan el mismo resultado.
lower bound(v.begin(), v.end(), 5) =
el iterador v.begin()+1.
upper bound(v.begin(), v.end(), 5) =
el iterador v.begin()+3.
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
11 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
12 / 56
Lenguaje
C++ STL - Conjuntos y Diccionarios
Lenguaje
C++ STL - Iteradores - Ejemplo
C++ STL - Conjuntos y Diccionarios
C++ STL - Iteradores
¿...y si quiero el último elemento menor o menor o igual?
v = 3 5 5 6 8 8 10
(abreviando la escritura)
¡Ojo!
lower bound(7) = v+4.
La pregunta no está bien definida. El lugar del último elemento menor (o
igual) que 2 no existe.
upper bound(7) = v+4.
Observación:
lower bound(x) da el lugar del primer elemento mayor o igual que
x.
upper bound(x) da el lugar del primer elemento mayor que x.
Resolviendo problemas del TP
Lenguaje
27 de Agosto de 2010
Si existen, entonces:
El lugar del último elemento menor que x es lower bound(x)-1
El lugar del último elemento menor o igual que x es
upper bound(x)-1
¿...y si quiero el último elemento menor o menor o igual?
Labo de Algo III (Sabi)
v = 3 5 5 6 8 8 10
13 / 56
Labo de Algo III (Sabi)
C++ STL - Conjuntos y Diccionarios
Resolviendo problemas del TP
Lenguaje
Multi-conjuntos
27 de Agosto de 2010
14 / 56
Trucos y Tips
Modularización
Un multiconjunto es una colección de elementos sin orden,
pontencialmente repetidos con las mismas operaciones que un conjunto:
insert: Agrega un elemento al conjunto (aún si ya está).
Modularizar el código no es solamente dividirlo en
clases/objetos/módulos.
También se pueden atomizar las responsabilidades, separando:
find: Devuelve un iterador al elemento buscado.
erase: Elimina un elemento del conjunto.
empty: Dice si el conjunto está vacı́o.
Algoritmos
Estructuras de datos
Estructuras de control
Definiciones propias del problema
Entidades del problema
En C++:
multiset<int> mc:
mc.insert(1); mc.insert(2); mc.insert(3); c.insert(2);
¿Cómo queda el multiconjunto después de ejecutar mc.erase(2);?
mc.erase(mc.find(2)); vs. mc.erase(2);
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
15 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
16 / 56
Lenguaje
Trucos y Tips
Lenguaje
Sobremodularización
Ejemplo - Multiplicación de matrices
La multiplicación de matrices cuadradas de n × n se define como
¡Alerta!
La
sobremodularización1
Trucos y Tips
resi,j =
es perjudicial para la salud.
n
X
(ai,k · bk,j )
k=1
Para representar una matriz, usamos un arreglo bidimensional, o un
arreglo de arreglos (vector<vector<int> >).
Ahora sı́, veamos un ejemplo.
1
Si esta palabra existiera
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Lenguaje
27 de Agosto de 2010
17 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Trucos y Tips
Lenguaje
27 de Agosto de 2010
18 / 56
Trucos y Tips
Ejemplo - Multiplicación de matrices cuadradas
Tips - typedef
vector<vector<int> > mult(const vector<vector<int> > &a, const
vector<vector<int> > &b) {
int n = a.size();
vector<vector<int> > res(n, vector<int>(n, 0));
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; i++) {
for(int k = 0; k < n; k++) {
res[i][j] += a[i][k] * b[k][j];
}
}
}
return res;
}
La instrucción typedef permite renombrar un tipo de datos de C++. Por
ejemplo:
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
typedef vector<int> vint;
typedef vector<vint> vvint;
Con esto la declaración es mucho más simple:
vvint mult(const vvint &a, const vvint &b) {
int n = a.size();
vvint res(n, vint(n, 0));
...
Esto representa la estrucutra de datos de una matriz.
19 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
20 / 56
Lenguaje
Trucos y Tips
Lenguaje
Ejemplo - Multiplicación de matrices cuadradas
Trucos y Tips
Tips - define
La instrución for es a veces demasiado expresiva.
vvint mult(const vvint &a, const vvint &b) {
int n = a.size();
vvint res(n, vint(n, 0));
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; i++) {
for(int k = 0; k < n; k++) {
res[i][j] += a[i][k] * b[k][j];
}
}
}
return res;
}
Es común recorrer un rango de números de 0 a n − 1.
#define es nuestro amigo.
#define forn(i, n) for(int i = 0; i < (int)(n); ++i)
Este macro evita escribir 3 veces la variable de control:
vvint mult(const vvint &a, const vvint &b) {
int n = a.size();
vvint res(n, vint(n, 0));
forn(i, n) forn(j, n) forn(k, n) {
res[i][j] += a[i][k] * b[k][j];
}
return res; }
¿Alguien notó el bug?
Esto modulariza una estructura de control.
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Lenguaje
27 de Agosto de 2010
21 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Trucos y Tips
Lenguaje
Tips - define
27 de Agosto de 2010
22 / 56
27 de Agosto de 2010
24 / 56
Trucos y Tips
Ejemplo - Mergesort
Si tuviéramos una lista definida como:
void ordena(int v[], int a, int b) {
if (a == b) return;
int c = (a+b)/2;
ordena(v, a, c-1);
ordena(v, c, b);
/* Merge */
... /* STL: inplace_merge(...); */
}
struct nodo {
nodo* next;
int elem;
}
Recorrer toda la lista se podrı́a hacer de la siguiente forma:
for(nodo* i = lista; i != NULL; i = i->next) { ... }
Esta estructura de control también se puede separar:
¿Alguien notó el bug?
#define forlst(i, l) for(nodo* i = (l); i != NULL; i = i->next)
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
23 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Lenguaje
Trucos y Tips
Lenguaje
Tips - Rangos y fronteras
Ejemplo - Mergesort
Siempre los rangos se nombran cerrado
a izquierda y abierto a derecha: [a, b).
void ordena(int v[], int a, int b) {
if (b-a <= 1) return;
int c = (a+b)/2;
ordena(v, a, c);
ordena(v, c, b);
/* Merge */
... /* STL: inplace_merge(...); */
}
¿Siempre? Sı́
¿De verdad? Sı́
¿Posta? Sı́
Jefe de los minisuper
Tamaño
Subrangos
Rango vacı́o
Labo de Algo III (Sabi)
[a, b]
b−a+1
[a, c − 1] y [c, b]
[a, c] y [c + 1, b]
[a, a − 1]
Resolviendo problemas del TP
Lenguaje
Trucos y Tips
[a, b)
b−a
[a, c) y [c, b)
[a, a)
27 de Agosto de 2010
25 / 56
Labo de Algo III (Sabi)
Trucos y Tips
Resolviendo problemas del TP
Lenguaje
Ejemplo - Iteradores
27 de Agosto de 2010
26 / 56
Trucos y Tips
Ejemplo - Iteradores
Todos los contenedores de C++ permiten ser iterados.
Siempre los rangos se nombran cerrado a izquierda y abierto a
derecha: [a, b).
Mostrar un diccionario de string en int:
void show(const map<string, int> &v) {
for(map<string, int>::const_iterator it = v.begin(); it != v.
end(); ++it) {
cout << it->first << " --> " << it->second << endl;
}
}
En iteradores, los rangos son desde X.begin() hasta X.end().
Mostrar un arreglo de números:
void show(vector<int> v) {
vector<int>::iterator it;
for(it = v.begin(); it != v.end(); ++it) cout << *it << " ";
cout << endl;
}
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
27 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
28 / 56
Lenguaje
Trucos y Tips
Lenguaje
Tips - define
Trucos y Tips
Tips - define
Otras estructuras de control usuales:
Es común iterar toda una estructura.
#define forn(i, n) for(int i = 0; i < (int)(n); ++i)
#define dforn(i, n) for(int i = (int)(n)-1; i >= 0; --i)
#define es nuestro amigo.
#define forall(it, X) for(typeof((X).begin()) it = (X).begin();
it != (X).end(); ++it)
#define forsn(i, s, n) for(int i=(s); i<(int)(n); ++i)
#define dforsn(i, s, n) for(int i=(int)(n)-1;i>=(s);--i)
Esto modulariza una estructura de control.
#define
it
#define
();
void show(const map<string, int> &v) {
forall(it, v) {
cout << it->first << " --> " << it->second << endl;
}
}
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
forall(it, X) for(typeof((X).begin()) it = (X).begin();
!= (X).end(); ++it)
dforall(it, X) for(typeof((X).rbegin()) it = (X).rbegin
it != (X).rend(); ++it)
ATENCIÓN: Leer el capı́tulo del preprocesador del manual de gcc:
http://gcc.gnu.org/onlinedocs/cpp/Macros.html, en especial
“Macro Pitfalls”.
29 / 56
Labo de Algo III (Sabi)
Mediciones
Resolviendo problemas del TP
27 de Agosto de 2010
30 / 56
Mediciones
Errores
Hay que medir el comportamiento del algoritmo.
Definición (Error de apreciación)
Los errores de apreciación son los que resultan de obtener (o apreciar) el
valor medido en el instrumento.
Problemas propios de la medición:
Preparar un experimento que permita medir el valor buscado.
“Usualmente” los instrumentos digitales no tienen error de apreciación.
Errores del instrumento de medición (de apreciación, sistemáticos,
aleatorios, etc.).
Definición (Resolución del instrumento)
Resolución del instrumento
La resolución del instrumento (o resolución máxima) es la mı́nima
unidad que es capaz de medir el instrumento.
Ejemplo: con una regla milimetrada no se puede medir mejor que 1mm.
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
31 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
32 / 56
Mediciones
Mediciones
Problemas de resolución
Errores aleatorios
Hay errores que dependen de muchos otros factores externos, y los
consideramos aleatorios (interrupciones del sistema operativo, hits y
misses en cache).
Experimento
Correremos 300 veces el mismo caso de prueba y lo mediremos todas las
veces independientemente.
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
33 / 56
Labo de Algo III (Sabi)
Mediciones
27 de Agosto de 2010
34 / 56
27 de Agosto de 2010
36 / 56
Mediciones
Histograma
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Diagrama de caja
Resolviendo problemas del TP
27 de Agosto de 2010
35 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Mediciones
Mediciones
Alternativa
Medir tiempo trae problemas de medición.
Alternativa: “Medir” cantidad de operaciones
Algorithm 2.1: factorial(n)
res ← 1
inc(cont)
for i ←
1 to n
res ← res ∗ i
do
inc(cont)
return (res)
Resultado: Según esta medición de cantidad de operaciones factorial es
O(n).
¿O(n)? ¿Seguro?
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
37 / 56
Labo de Algo III (Sabi)
Mediciones
Resolviendo problemas del TP
27 de Agosto de 2010
38 / 56
Mediciones
Cantidad de operaciones
Conclusiones
Pros:
Mide la cantidad de operaciones en el modelo.
No hay una única forma de medir el comportamiento.
No tiene errores de medición (casi).
Las mediciones reales tienen error.
No se puede medir cualquier cosa.
Contras:
Se deben contemplar los problemas de cada medición y llegar a una
aproximación del valor.
No permite contrastar el modelo con el comportamiento en la
máquina real.
No permite detectar errores en la complejidad real del algoritmo.
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
39 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
40 / 56
Gráficos
Gráficos
Ejemplos
Ejemplos
Debe tener una escala
Los ejes deben tener
rótulos
Se deben incluir
referencias claras
Los ejes deben tener
unidades
No usar colores similares.
No usar colores si se
imprime en blanco y
negro.
Se deben distinguir las
mediciones
Se deben incluir
referencias
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
41 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Gráficos
27 de Agosto de 2010
42 / 56
27 de Agosto de 2010
44 / 56
Gráficos
Ejemplos
Gráficos
Para qué sirve un gráfico:
Comparar, cuantitativamente, funciones.
La interpolación no
siempre refleja
mediciones
Verificar correlación entre dos variables.
Para qué NO sirve un gráfico:
Se deben distinguir las
mediciones
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
43 / 56
Demostrar propiedades matemáticas.
Calcular complejidades.
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Gráficos
Gráficos
Correlación
Correlación
¿Cómo se contrastan los datos con los valores teóricos?
De la definición de f (n) ∈ O(g (n)):
∃k ∈
R+, n0 ∈ N : ∀n, (n0 < n) ⇒ f (n) ≤ k · g (n)
Atención
Los gráficos pueden ser engañosos.
Podemos graficar:
Las deducciones del gráfico sólo son ciertas dentro de los lı́mites del
gráfico, y para los valores observados.
f (n)
k · g (n)
y verificar que a partir de cierto n0 , f (n) está debajo de k · g (n).
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
45 / 56
Labo de Algo III (Sabi)
Gráficos
27 de Agosto de 2010
46 / 56
27 de Agosto de 2010
48 / 56
Gráficos
Escala lineal
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Escala logarı́tmica
Resolviendo problemas del TP
27 de Agosto de 2010
47 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Gráficos
Gráficos
Recordemos
Ejemplos
Algorithm 3.1: SlowSort(vector < Nat > v [])
n ← v .size()
for k ← 1 to n
do for
i ← 1 to n − 1
if v [i] > v [i + 1]
do
then swap(v [i], v [i + 1])
return
Complejidad temporal en el modelo uniforme: O(n2 )
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
49 / 56
Labo de Algo III (Sabi)
Gráficos
Resolviendo problemas del TP
27 de Agosto de 2010
50 / 56
27 de Agosto de 2010
52 / 56
Gráficos
Constraste con lo teórico
Constraste con lo teórico
Debemos encontrar una constante k para que k · n2 se mantenga por
encima del gráfico del algoritmo SlowSort.
Se puede buscar a mano
Se puede ajustar la curva (n2 ) a los datos.
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
51 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Gráficos
Gráficos
Software disponible
Ejemplo
Algorithm 3.2: Factorizar(n)
Existe mucho software para hacer gráficos y análisis de datos
d ←2
res ← ∅
while 
n>1
while d divide a n



n ← n/d
do
do
res ← res + {d}



d ←d +1
return (res)
Origin Pro (propietario).
Qtiplot
Gnuplot
Otros programas que permiten graficar funciones (Mathematica,
Matlab, Microsoft Excel (propietario)).
Labo de Algo III (Sabi)
Resolviendo problemas del TP
27 de Agosto de 2010
53 / 56
Labo de Algo III (Sabi)
Gráficos
27 de Agosto de 2010
54 / 56
27 de Agosto de 2010
56 / 56
Gráficos
Factorizar
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Factorizar
Resolviendo problemas del TP
27 de Agosto de 2010
55 / 56
Labo de Algo III (Sabi)
Resolviendo problemas del TP
Descargar