Complejidad Listas Estructuras de Datos Andrea Rueda Pontificia Universidad Javeriana Departamento de Ingeniería de Sistemas Lecciones aprendidas ● Taller 1 Lecciones aprendidas ● Taller 1: - Describir una estrategia experimental para comparación de algoritmos. - ¿Los experimentos me permiten corroborar las hipótesis teóricas? - Manejo del tiempo, distribución de tareas, formalidad en la documentación. - Adaptación a nuevos entornos y herramientas. ¿Qué recordamos? ● ¿Análisis de complejidad de un algoritmo? ¿Qué recordamos? ● Análisis de complejidad de un algoritmo. tiempo de ejecución T(n): cantidad de instrucciones básicas ejecutadas. análisis teórico: orden de un algoritmo O(n): función que acota el crecimiento de T(n) (peor caso). Ejercicio ● ¿T(n) para búsqueda lineal? int busqueda_lineal (int elemento, int lista[], int n) { int res = ­1; for (int i=0; i<n; i++) if (lista[i]==elemento) res = i; return(res); } Ejercicio ● ¿T(n) para búsqueda lineal? int busqueda_lineal (int elemento, int lista[], int n) { int res = ­1; // 1 for (int i=0; i<n; i++) // 1+(n+1)+n if (lista[i]==elemento) // n*(1+1) res = i; // 1 return(res); // 2 } T(n) = 1+1+(n+1)+n+2n+1+2 = 4n+6 → O(n) Ejercicio ● ¿T(n) para suma de matrices cuadradas? void suma_matrices (int** A, int** B, int** C, int n) { for (int i=0; i<n; i++) for (int j=0; j<n; j++) C[i][j] = A[i][j] + B[i][j]; } Ejercicio ● ¿T(n) para suma de matrices cuadradas? void suma_matrices (int** A, int** B, int** C, int n) { for (int i=0; i<n; i++) // 1+(n+1)+n for (int j=0; j<n; j++)// n*(1+(n+1)+n) C[i][j] = A[i][j] + B[i][j];// n*n*8 } T(n) = 1+(n+1)+n+n(1+(n+1)+n)+n*n*8 = 2n+2+2n2+2n+8n2 = 10n2+4n+2 → O(n2) Ejercicio ● ¿T(n) para multiplicación de matrices cuadradas? void mult_matrices (int** A, int** B, int** C, int n) { for (int i=0; i<n; i++) for (int j=0; j<n; j++) { C[i][j] = 0; for (int k=0; k<n; k++) C[i][j] += A[i][k] * B[k][j]; } } Ejercicio ● ¿T(n) para multiplicación de matrices cuadradas? void mult_matrices (int** A, int** B, int** C, int n) { for (int i=0; i<n; i++) // 1+(n+1)+n for (int j=0; j<n; j++) { // n*(1+(n+1)+n) C[i][j] = 0; // n*n*3 for (int k=0; k<n; k++) // n*n*(1+(n+1)+n) C[i][j] += A[i][k] * B[k][j]; // n*n*n*9 } } T(n) = 2n+2+n(2n+2)+3n2+n2(2n+2)+9n3 = 11n3+7n2+4n+2 → O(n3) Ejercicio ● ¿T(n) para Fibonacci recursivo? unsigned int nFib( unsigned int n ) { if( n <= 1 ) return( n ); else return( nFib( n ­ 1 ) + nFib( n ­ 2 ) ); } Ejercicio ● ¿T(n) para Fibonacci recursivo? unsigned int nFib( unsigned int n ) { if( n <= 1 ) return( n ); else return( nFib( n ­ 1 ) + nFib( n ­ 2 ) ); } ● Tfib(n) = 1 + 2 + Tfib(n-1) + Tfib(n-2) ● Tfib(n-1) = 1 + 2 + Tfib(n-2) + Tfib(n-3) ● Tfib(n-2) = 1 + 2 + Tfib(n-3) + Tfib(n-4) Ejercicio ... Tfib(n-2) ... Tfib(n-1) ... Tfib(n-3) ... Tfib(n) ... Tfib(n-3) ... Tfib(n-2) ... Tfib(n-4) ... Ejercicio ... Tfib(n-2) ... Tfib(n-1) ... Tfib(n-3) ... Tfib(n) ... Tfib(n-3) ... Tfib(n-2) ... →O(2 ) n Tfib(n-4) ... Ejercicio ● Comparación de algoritmos en términos de complejidad: Algoritmos de búsqueda: – Búsqueda lineal. → O(n) – Búsqueda binaria. Ejercicio ● Comparación de algoritmos: Búsqueda binaria. bool busqueda_binaria (int elemento, int lista[], int n) { bool encontrado = false; int primero = 0; int ultimo = n – 1; while (primero <= ultimo && !encontrado) { int p = (primero + ultimo) >> 1; if (elemento < lista[p]) ultimo = p – 1; else if(elemento > lista[p]) primero = p + 1; else encontrado = true; } return(encontrado); } Ejercicio ● Comparación de algoritmos: Búsqueda binaria. – Tbb(n) = 6 + k (k: número de iteraciones necesarias) – n0 = n; n1 = n/2; n2 = n/4; n3 = n/8; …; nk = 1. – n/2k < 2 (tamaño del sub-arreglo después de k iteraciones) – n/2k < 2 : n < 2k+1 : fórmula de acotamiento. Ejercicio ● Comparación de algoritmos: Búsqueda binaria. – Tbb(n) = 6 + k (k: número de iteraciones necesarias) – n0 = n; n1 = n/2; n2 = n/4; n3 = n/8; …; nk = 1. – n/2k < 2 (tamaño del sub-arreglo después de k iteraciones) – n/2k < 2 : n < 2k+1 : fórmula de acotamiento. – Tbb(n) es O(log2(n)) Ejercicio ● Comparación de algoritmos: Búsqueda binaria – Tbb(n) = 6 + k (k: número de iteraciones necesarias) – n0 = n; n1 = n/2; n2 = n/4; n3 = n/8; …; nk = 1 – n/2k < 2 (tamaño del sub-arreglo después de k iteraciones) – n/2k < 2 : n < 2k+1 : fórmula de acotamiento – Tbb(n) es O(log2(n)) ¿Cuál búsqueda es mejor? Análisis teórico T.H. Cormen, C.E. Leiserson, R.L. Rivest, C. Stein. Introduction to Algorithms, 3rd edition. MIT Press, 2009. Análisis teórico vaxxxa.github.io/talks/introduction.to.algorithms-computational.complexity/index.html#/28 TAD Tipo Abstracto de Dato ¿Qué es un TAD? ● ● TAD: Tipo Abstracto de Dato. – Nuevo tipo de dato bien especificado (propio). – Amplía el lenguaje de programación. Definición: – Especificación (¿qué hace el TAD?) General, global. Formal, matemática. – Implementación (¿cómo lo hace el TAD?) Dependiente del lenguaje a usar. Diseño de TADs ● Programas = Algoritmos + Datos (ecuación de Wirth). https://web.archive.org/web/20130207170133/http://w ww.inf.ethz.ch/personal/wirth/books/AlgorithmE0/ ● Diseño de TADs: – Comportamientos del objeto en el mundo real (interfaz/verbos). – Conjunto mínimo de datos que lo representan (estado/sustantivos). – TAD = Interfaz + Estado. Consideraciones de diseño ● Diseño de TADs: TAD nombre Conjunto mínimo de datos: nombre valor (variable), tipo de dato, descripción ... Comportamiento (operaciones) del objeto: nombre operación (argumentos), descripción funcional ... ¡Atención! ● Recordatorio: El diseño descrito anteriormente será exigido en todas las actividades del curso (talleres, parciales, proyecto, quices) de aquí en adelante, durante todo el semestre. TAD Lista TAD Lista ● ● Secuencia finita de datos: – Primero, último. – Siguiente, anterior. Recorrido: – Primero → Último. – Último → Primero. ● Acceso aleatorio: – ● Restringido. Algoritmos: – Vacía, 1 elemento. – Cabeza, cola. – Intermedio. TAD Lista Cabeza 1 56 12 7 Ventana / Cursor / Iterador -9 3 1 Cola NULL TAD Lista Cabeza 1 56 12 7 Ventana / Cursor / Iterador ¿Estado? -9 3 1 Cola ¿Interfaz? NULL TAD Lista ● ● Estado: – Cabeza. – Cola. – {Ei} (¿importa el tipo?). – ¿Ventana / Cursor / Iterador? Interfaz: – Creadoras. – Analizadoras: tamaño, acceso, cabeza, cola, ¿ventana? – Modificadoras: insertar, eliminar. TAD Lista TAD Lista Conjunto mínimo de datos: - cabeza, ?, representa el punto de inicio. - cola, ?, representa el punto de finalización. Comportamiento (operaciones) del objeto: - esVacia(), indica si la lista está vacía. - tamaño(), cantidad de elementos en la lista. - cabeza(), retorna el elemento en la cabeza. - cola(), retorna el elemento en la cola. - insertarCabeza(v), inserta v en la cabeza. - insertarCola(v), inserta v en la cola. TAD Lista TAD Lista Conjunto mínimo de datos: - cabeza, ?, representa el punto de inicio. - cola, ?, representa el punto de finalización. Comportamiento (operaciones) del objeto: - eliminarCabeza(), elimina elemento de la cabeza. - eliminarCola(), elimina elemento de la cola. - insertar(pos,v), inserta v en la posición pos. - eliminar(pos), elimina el elemento ubicado en pos. - vaciar(), elimina todos los elementos de la lista. TAD Lista: esVacia() Cabeza NULL Cola → true Cabeza 1 56 12 7 -9 3 1 → false Cola NULL TAD Lista: tamaño() Cabeza NULL Cola →0 Cabeza 1 56 12 7 -9 3 1 →7 Cola NULL TAD Lista: cabeza() Cabeza NULL Cola → ¿? (comportamiento indefinido) Cabeza 1 56 12 7 -9 3 1 →1 Cola NULL TAD Lista: cola() Cabeza NULL Cola → ¿? (comportamiento indefinido) Cabeza 1 56 12 7 -9 3 1 →1 Cola NULL TAD Lista: insertarCola(v) Cabeza Cabeza NULL Cola v Cola NULL Cabeza 1 TAD Lista: insertarCola(v) 56 12 7 NULL Cola Cabeza 1 1 56 12 7 1 v Cola NULL TAD Lista: eliminarCola() Cabeza v Cola Cabeza NULL NULL Cola Cabeza 1 TAD Lista: eliminarCola() 56 12 7 1 Cola Cabeza 1 v 56 12 7 1 Cola NULL NULL TAD Lista: insertarCabeza(v) Cabeza Cabeza NULL Cola v Cola NULL Cabeza 1 TAD Lista: insertarCabeza(v) 56 12 7 NULL Cola Cabeza v 1 1 56 12 7 1 Cola NULL TAD Lista: eliminarCabeza() Cabeza v Cola Cabeza NULL NULL Cola Cabeza v TAD Lista: eliminarCabeza() 1 56 12 7 Cola Cabeza 1 1 56 12 7 1 Cola NULL NULL TAD Lista: insertar(pos, v) Cabeza Cabeza pos NULL Cola v Cola NULL TAD Lista: insertar(pos, v) Cabeza Cabeza pos 5 Cola NULL v 5 Cola NULL Cabeza TAD Lista: insertar(pos, v) pos 1 56 12 7 Cabeza 1 1 NULL Cola 56 12 v 7 1 NULL Cola TAD Lista: eliminar(pos) Cabeza Cabeza pos 5 Cola NULL NULL Cola Cabeza TAD Lista: eliminar(pos) pos 1 56 12 7 Cola Cabeza 1 1 56 12 1 NULL Cola NULL TAD Lista: vaciar() Cabeza NULL Cola Cabeza 1 56 12 7 -9 3 1 Cola NULL Programación genérica Programación genérica a = b + c; En C++, ¿qué problemas tiene la línea anterior? Programación genérica int b = 5; int c = 6; int a = b + c; int suma( int a, int b ) { return( a + b ); } Programación genérica float b = 5.67; float c = 6.923; float a = b + c; float suma( float a, float b ) { return( a + b ); } Programación genérica ● Generalización → adaptabilidad, flexibilidad. template< class identificador > declaracion_funcion; template< typename identificador > declaracion_funcion; Programación genérica ● Plantilla con un tipo de dato: template< class T > T suma( T a, T b ) { return( a + b ); } int a = suma<int>(5, 7); double b = suma<double>(6.4, 1.7); Programación genérica Organización de las plantillas ● Encabezado (.h) ● Incluir archivo de código (.hxx) ● ESTOS DOS ARCHIVOS NO SE COMPILAN. – Se usan en un archivo compilable (.cxx, .cpp, .c++) donde se INSTANCIAN las clases genéricas. STL Standard Template Library STL (Standard Template Library) ● ● ● ¡Librería con “muchas cosas” genéricas! Provee un conjunto de clases comunes, usables con cualquier tipo de dato y con operaciones elementales. Tres componentes: ● Contenedores (containers). ● Algoritmos (algorithms). ● Iteradores (iterators). www.bogotobogo.com/cplu splus/stl_vector_list.php http://www.sgi.com/tech/stl Contenedores STL ● Contenedores secuenciales estándar: ● De acceso aleatorio: - vector: Arreglos dinámicos. (std::vector ↔ #include <vector>) - deque: Cola de doble cabeza, inserción/eliminación en cabeza y cola. (std::deque ↔ #include <deque>) ● De acceso iterativo: - list: Doblemente encadenada. (std::list ↔ #include <list>) vector 0 1 2 3 4 5 Head ● 6 7 8 9 Tail ¿Orden de complejidad de los métodos? – size, empty. – front, back. – clear. – push_back, pop_back. – push_front, pop_front. – insert, erase. 10 11 deque double-ended queue 0 1 2 3 4 5 Head ● 6 7 8 9 Tail ¿Orden de complejidad de los métodos? – size, empty. – front, back. – clear. – push_back, pop_back. – push_front, pop_front. – insert, erase. 10 11 list ● ¿Orden de complejidad de los métodos? – size, empty, front, back, clear. – push_back, pop_back. – push_front, pop_front. – insert, erase. Órdenes de complejidad vector size clear empty push_front pop_front push_back pop_back insert erase ¿Acceso aleatorio? deque list Órdenes de complejidad vector deque list size O(1) O(1) O(1) clear O(1) O(1) O(n) empty O(1) O(1) O(1) push_front O(n) O(1) O(1) pop_front O(n) O(1) O(1) push_back O(1) O(1) O(1) pop_back O(1) O(1) O(1) insert O(n) O(n) O(1) erase O(n) O(n) O(1) si si no ¿Acceso aleatorio? Criterios para escoger ● Evolución de la secuencia: – Estática: ● – ¿Inserción sólo por final? ¿O por final y cabeza? Dinámica: ● ¿Inserción sólo por final? ¿O por final y cabeza? ¿O en cualquier punto? ● ¿Memoria limitada? ● Tipo de acceso: – ¿Necesita acceso aleatorio? – ¿Predominan las iteraciones sobre toda la secuencia? Tarea Estudiar la STL: ● ¿Qué elementos la componen? ● ¿Cómo se usa en el código? ● ¿Ventajas y desventajas? Referencias ● ● ● ● T.H. Cormen, C.E. Leiserson, R.L. Rivest, C. Stein. Introduction to Algorithms, 3 rd edition. MIT Press, 2009. L. Joyanes Aguilar, I. Zahonero. Algoritmos y estructuras de datos: una perspectiva en C. McGraw-Hill, 2004. vaxxxa.github.io/talks/introduction.to.algorithms -computational.complexity/ https://philipstel.wordpress.com/2011/03/07/det ermining-the-complexity-of-an-algorithm-thebasic-part/