670 likes | 938 Views
Instituto Tecnológico de Culiacán. Ingeniería en Sistemas Computacionales. Estructura de datos. Material de apoyo Unidad 1. Prof. Felipe E. Muñiz R. TEMARIO. Unidad 1.- Análisis de algoritmos. 1.1 Concepto de Complejidad de Algoritmos. 1.2 Aritmética de la notación O. 1.3 Complejidad.
E N D
Instituto Tecnológico de Culiacán Ingeniería en Sistemas Computacionales Estructura de datos Material de apoyo Unidad 1 Prof. Felipe E. Muñiz R.
TEMARIO Unidad 1.- Análisis de algoritmos. 1.1 Concepto de Complejidad de Algoritmos. 1.2 Aritmética de la notación O. 1.3 Complejidad. 1.3.1 Tiempo de ejecución de un algoritmo. 1.3.2 Complejidad en espacio. 1.4 Selección de un algoritmo.
Introducción a la materia • Los datos a procesar por una computadora se clasifican en : • a) Simples • b) Estructurados
Datos Simples: • La principal característica de los datos simples es que ocupan sólo una casilla de memoria, por lo tanto una variable simple hace referencia a un único valor a la vez. • Dentro de este grupo de datos se encuentran: enteros, reales, caracteres, booleanos, enumerados y subrangos ( los dos últimos no existen en algunos lenguajes de programación.
TIPOS DE DATOS SIMPLES • Es uno de los conceptos fundamentales de cualquier lenguaje de programación. Estos definen los métodos de almacenamiento disponibles para representar información, junto con la manera en que dicha información ha de ser interpretada. • Para crear una variable (de un tipo simple) en memoria debe declararse indicando su tipo de variable y su identificador que la identificará de forma única.. • Los simples son tipos nucleares que no se derivan de otros tipos, como los enteros, de coma flotante, booleanos y de carácter.
Definición de bit Unidad mínima de información digital que puede ser tratada por una computadora. Proviene de la contracción de la expresión binary digit (dígito binario), y puede tener dos estados "0" o "1". Definición de byte Simboliza un carácter en una computadora (ej. una letra). . Conjunto significativo de ocho bits que representan un carácter, por ejemplo la letra "a", en un sistema informático. Definición de carácter Cualquier signo tipográfico. Puede ser una letra, un número, un signo de puntuación o un espacio. Definición de ascii American Standard Code for Information Interchange. Estándar Americano para Intercambio de Información. La tabla básica de caracteres ASCII está compuesta por 128 caracteres incluyendo símbolos y caracteres de control. Existe una versión extendida de 256. Conjunto de normas de codificación de caracteres mediante caracteres numéricos, de amplia utilización en informática y telecomunicaciones.
b) Dato Estructurado o Abstracto: Los datos estructurados se caracterizan por el hecho de que con un nombre (identificador de variable estructurada) se hace referencia a un grupo de casillas de memoria. Es decir, un dato estructurado tiene varios componentes. Cada uno de los componentes básicos puede ser a su vez un dato simple o estructurado. Sin embargo, los componentes básicos (los de nivel más bajo) de cualquier tipo estructurado son datos simples. Se ejemplifica un dato estructurado en la siguiente figura :
Estructura de datos Las estructuras de datos constituyen un aspecto muy importante de la computación. Muchos algoritmos, requieren una representación apropiada de los datos para lograr ser eficientes. Esta representación junto con las operaciones permitidas se llama estructura de datos. Definición de Estructura de datos: Es una colección de datos organizados de un modo particular
Unidad 1 - Análisis De Algoritmos • Tipos de algoritmos según su función • • Algoritmo de ordenamiento • Es un algoritmo que pone elementos de una lista o un vector en una secuencia dada por una relación de orden, es decir, el resultado de salida ha de ser una permutación —o reordenamiento— de la entrada que satisfaga la relación de orden dada. • • Algoritmo de búsqueda • Es aquel que está diseñado para localizar un elemento concreto dentro de una estructura de datos. Consiste en solucionar un problema booleano de existencia o no de un elemento determinado en un conjunto finito de elementos, es decir al finalizar el algoritmo este debe decir si el elemento en cuestión existe o no en ese conjunto (si pertenece o no a él), además, en caso de existir, el algoritmo podría proporcionar la localización del elemento dentro del conjunto.
Concepto de complejidad de algoritmos • Algoritmo:Es una secuencia de operaciones o pasos perfectamente definidos que conducen a la solución de un problema • Complejidad de un algoritmo: es la función que da la eficiencia de un algoritmo (tiempo de respuesta)
Concepto de complejidad de algoritmos Dado el nombre queremos conocer su numero de teléfono. • Búsqueda secuencial: Recorre cada elemento, uno a uno, hasta encontrar el nombre buscado y su teléfono • Búsqueda binaria: compara el nombre buscado con el que se encuentra en la mitad de la lista. Divide la lista en dos partes y determina en cual de las dos se encuentra el nombre buscado Es evidente que entre menos comparaciones se realicen menos tiempo de ejecución tendrá el algoritmo
Concepto Complejidad Algoritmos La resolución práctica de un problema exige por una parte un algoritmo o método de resolución y por otra un programa o codificación de aquel en un ordenador real. Ambos componentes tienen su importancia, pero la del algoritmo es absolutamente esencial, mientras que la codificación puede muchas veces pasar a nivel de anécdota. A efectos prácticos o ingenieriles, nos deben preocupar los recursos físicos necesarios para que un programa se ejecute. Aunque puede haber muchos parámetros, los mas usuales son el tiempo de ejecución y la cantidad de memoria (espacio). Ocurre con frecuencia que ambos parámetros están fijados por otras razones y se plantea la pregunta inversa: ¿cual es el tamaño del mayor problema que puedo resolver en T segundos y/o con M bytes de memoria? En lo que sigue nos centramos casi siempre en el parámetro tiempo de ejecución, si bien las ideas desarrolladas son fácilmente aplicables a otro tipo de recursos.
Concepto Complejidad Algoritmos Para cada problema determinaremos una medida N de su tamaño (por número de datos) e intentaremos hallar respuestas en función de dicho N. El concepto exacto que mide N depende de la naturaleza del problema. Así, para un vector se suele utizar como N su longitud; para una matriz, el número de elementos que la componen; para un grafo, puede ser el número de nodos (a veces es mas importante considerar el número de arcos, dependiendo del tipo de problema a resolver), en un archivo se suele usar el número de registros, etc. Es imposible dar una regla general, pues cada problema tiene su propia lógica de coste.
Concepto Complejidad Algoritmos Tiempo de Ejecución Una medida que suele ser útil conocer es el tiempo de ejecución de un programa en función de N, lo que denominaremos T(N). Esta función se puede medir físicamente (ejecutando el programa, reloj en mano), o calcularse sobre el código contando instrucciones a ejecutar y multiplicando por el tiempo requerido por cada instrucción. Así, un trozo sencillo de programa como: S1; for (int i= 0; i < N; i++) S2; requiere T(N)= t1 + t2*N siendo t1 el tiempo que lleve ejecutar la serie “S1” de sentencias, y t2 el que lleve la serie “S2”. Prácticamente todos los programas reales incluyen alguna sentencia condicional, haciendo que las sentencias efectivamente ejecutadas dependan de los datos concretos que se le presenten.
Concepto Complejidad Algoritmos Esto hace que mas que un valor T(N) debamos hablar de un rango de valores Tmin(N) ⇐ T(N) ⇐ Tmax(N) los extremos son habitualmente conocidos como “caso peor” y “caso mejor”. Entre ambos se hallara algún “caso promedio” o más frecuente. Cualquier fórmula T(N) incluye referencias al parámetro N y a una serie de constantes “Ti” que dependen de factores externos al algoritmo como pueden ser la calidad del código generado por el compilador y la velocidad de ejecución de instrucciones del ordenador que lo ejecuta. Dado que es fácil cambiar de compilador y que la potencia de los ordenadores crece a un ritmo vertiginoso (en la actualidad, se duplica anualmente), intentaremos analizar los algoritmos con algún nivel de independencia de estos factores; es decir, buscaremos estimaciones generales ampliamente válidas.
Aritmética de notación • Existen diversas formas para representar nuestros algoritmos y estas representaciones pueden ayudarnos en la comprensión de los mismos; así como poderlos trasladar a algún lenguaje de programación.
NOTACIONES: • Notaciones matemáticas • Función factorial: Es el producto de los n números enteros positivos que van desde 1 hasta n Ejemplo: n! 2!= 1.2=2 3!= 1.2.3=6 4!=1.2.3.4=24
NOTACIONES: • Notaciones matemáticas • Simbolo de la suma (sumatorio) El simbolo sumatorio es ∑ Ejemplo: Sea la secuencia a1, a2, a3, a4,……..an Las sumas a1+a2+a3+a4+ ……. +an = ∑ a n J=1
NOTACIONES: NOTACION INFIJA: Los operadores aparecen en medio de los operandos. A + B, A – 1, E/F, A * C , A ^ B , A + B + C NOTACION PREFIJA: El operador aparece antes de los operandos. + AB, - A1, /EF, *AC, ^AB, ++ABC NOTACION POSTFIJA: El operador aparece al final de los operandos. AB+, A1-, EF/, AC*, AB^, AB+C+
Estructuras de control • Lógica secuencial: se ejecuta en una secuencia obvia. Algoritmo Diagrama de flujo Modulo A Modulo B Modulo C Modulo A Modulo B Modulo C
Estructuras de control • Lógica Selectiva: Utiliza un conjunto de condiciones que implica la ejecución de alguna alternativa entre varias. Este tipo de estructuras reciben el nombre de estructura condicionadas • Alternativa simple • Alternativa doble • Alternativa múltiple
Estructuras de control • Alternativa simple: si condición, entonces: [Modulo A] [Final de la estructura condicional] • Alternativa doble: si condición, entonces: [Modulo B] [Fin de la estructura condicional]
Estructuras de control • Alternativa doble: si condicion(1), entonces: [Modulo A1] si No Si condicion(2), entonces: [Modulo A2] si No Si condicion(M), entonces: [Modulo AM] si No: [Modulo B] [Final de la estructura condicional]
Estructuras de control • Lógica iterativa (flujo repetitivo): ciclos • Ciclo Repetir-Mientras Repetir-Mientras condición: [Modulo] [Fin del ciclo]
Ejemplo de un Algoritmo con búsqueda secuencial. • [inicializar]. K:=1 y LUG:=0 • Repetir paso 3 y 4 mientras LUG=0 y K<=N. • Si ITEM=DATO[K], entonces: LUG:=K. • K:= K+1. [Incrementamos el contador] • [Fin del ciclo del paso 2]. • 5.[¿lo hemos encontrado?] • Si LUG=0, entonces: • Escribir: ITEM no pertenece al arreglo DATOS. • Si No: • Escribir: LUG es la posición que ocupa ITEM. • [Fin de la estructura condicional]. • 6. Salir La complejidad esta dada por? el número de comparaciones C entre ITEM y DATOS[K] Caso peor: Que ITEM sea el Ultimo Elemento
Complejidad • Analizar algoritmos es la tarea mas costosa en el diseño de los algoritmos. Por que ? • Legibilidad • Costo en mantenimiento • Se tienen que aportar criterios que midan la eficiencia
Factores que miden la eficiencia de un algoritmo • Por el tiempo de ejecución (ordenación o búsqueda) • Por el espacio (memoria)
Relación espacio-tiempo Tenemos un archivo con datos de nombres seguro social etc. Si se desea encontrar un nombre cual es el mejor método? la busqueda binaria Si lo que conocemos es el numero de seguro que método es mejor? La busqueda secuencial , Pero implica mayor tiempo Como solucionarlo:
Algoritmos ¿Qué es un algoritmo? es un conjunto finito de instrucciones o pasos que sirven para ejecutar una tarea o resolver un problema dado.
Algoritmos Características de los algoritmos: • Precisión: los pasos se enuncian con precisión. 2. Entrada: el algoritmo recibe una entrada de datos 3. Salida: el algoritmo produce una salida de información
Análisis de algoritmos Introducción • Es difícil determinar la cantidad exacta de ejecución de un algoritmo ya que esto depende de: • Como se codifico el programa • Que computadora se utilizara • Que datos debe utilizar el programa
Análisis de algoritmos Introducción: Tasa de crecimiento A medida que crece un elemento del programa, generalmente crece el tiempo de ejecución del mismo. Esto es que el tiempo de ejecución varia según el tamaño de la entrada. Observando estas variaciones se puede determinar la tasa de crecimiento del programa. Tasa de crecimiento: Es una medida importante de la eficiencia de un programa ya que predice cuanto tiempo se requerirá para entradas muy grandes de un determinado problema.
Análisis de algoritmos Introducción: Consideraciones de eficiencia Para determinar la eficiencia de un programa debemos de considerar: • El tiempo • El espacio La complejidad del espacio de un programa.- Es la cantidad de memoria que se necesita para ejecutar hasta la compleción (terminación) La complejidad del tiempo de un programa.- Es la cantidad de tiempo de computadora que se necesita para Ejecutar hasta la compleción (terminación)
Análisis de algoritmos Introducción En ocasiones pueden existir varios algoritmos para resolver una aplicación particular (A1, A2, …,An). ¿Cómo decidir cuál de los algoritmos es mejor (tiempo de ejecución y espacio de memoria)? Solución 1 (a posteriori, medida experimental). La solución más sencilla parece ser implementar los algoritmos en algún lenguaje de programación y medir el tiempo de ejecución que cada uno de ellos requiere para resolver el problema. Solución 2 (a priori, medida teórica). Estableciendo una medida de calidad de los algoritmos, que nos permita compararlos sin necesidad de implementarlos.
Análisis de algoritmos Introducción En la solución 1, resulta muy costoso (por no decir imposible), implementar todos los algoritmos para poder realizar la comparación de los tiempos de ejecución. Factores que influyen en el tiempo de ejecución: • La velocidad de operación de la computadora en que se ejecuta. Es diferente ejecutar el programa en un micro 80386, que en un pentium de 1.83 Ghz. • El compilador utilizado (calidad del código generado). Cada compilador utiliza diferentes estrategias de optimización, siendo algunas más efectivas que otras. • La estructura del algoritmo para resolver el problema.
Análisis de algoritmos Introducción En la solución 2, lo ideal, al hacer la evaluación de la eficiencia del algoritmo, sería encontrar una función matemática que describiera de manera exacta el tiempo que dura el algoritmo al ejecutarse, con una entrada de n datos - TA(n) – En muchos casos, el cálculo de la función matemática no se puede realizar, ya que depende de la calidad o contenido de la entrada, se ilustra a continuación: for (int i=0; i < N && V[i]!=busca; i++); existe=i<N TA(n)= 3
Análisis de algoritmos Introducción TA(n)= 11 Esto implica que, por más que se conozca el tamaño de los datos de entrada, es imposible (para muchos problemas) determinar el tiempo de ejecución para cada una de las posibles entradas.
Análisis de Algoritmos Introducción Usualmente el análisis de un algoritmo incluye: • Un caso medio que tan cerca al caso promedio trabaja el algoritmo, Notación Θ (theta) peor caso Notación O (big-oh) • Un caso pesimista Notación Ω (big-omega) • Un caso optimista mejor caso Nosotros trabajaremos con el TA(n) en el peor de los casos (O), ya que es mucho más fácil definir cuál es el peor de los casos, que considerarlos todos o incluso que considerar el caso promedio. TA(n)=tiempo que se demora el algoritmo A, en el peor de los casos, para encontrar una solución a un problema de tamaño n.
Análisis de Algoritmos Complejidad Cuando se dice que T(n)=O(f(n)) se esta garantizando que la funcion T(n) crece a una velocidad no mayor que f(n) Concepto de complejidad: Es tratar de encontrar un función f(n), que acote el crecimiento de la función tiempo, para poder decir: Que en ningún caso TA(n) se comporta peor que f al aumentar el tamaño del problema. Así f(n) es una cota superior de T(n) Y T(n) es una cota inferior de f(n) • Así sea T(n) el tiempo de ejecución de algún programa, medido por una función de la entrada de tamaño n, esta función supondrá que: • El argumento n es un entero no negativo • T(n) es no negativo para todos los argumentos n TA (n) es un O(f(n)), leído como “O de f(n)”, si existe una constante positiva c, tales que, TA(n) <= cf(n)
Crecimiento de las funciones típicas de complejidad de algoritmos Análisis de Algoritmos Complejidad TA(n) más comunes n Al afirmar que un algoritmo es O (f(n)), se está diciendo que al aumentar el número de datos que debe procesar, el tiempo del algoritmo va a crecer a como crece f en relación a n
Análisis de Algoritmos Complejidad • O(n) es mas eficiente que el O(n2) • O(log n) es mas rápido que O(n log n) y • a su vez es mas rápido que O(n2)
Análisis de Algoritmos Logaritmo • Logaritmo de un numero: Es el exponente a que hay que elevar otro número llamado base para obtener el numero dado • Base: cualquier numero positivo 5º=1 5¹=5 5²=25 5³=125 Siendo la base el 5 el logaritmo de Log 1 es 0 , y cero es el exponente al que hay que elevar la base 5 Log 5 es 1 Log 25 es 2
Análisis de Algoritmos Complejidad Los algoritmos de tipo polinómico (O(nª)) no son una maravilla, y se enfrentan con dificultad a problemas de tamaño creciente. Mientras complejidades del orden O(n2) y O(n3) suelen ser efectivamente abordables, prácticamente nadie acepta algoritmos de orden O(n100), por muy polinómicos que sean.
Análisis de Algoritmos Aritmética en notación O Para facilitar el cálculo de la complejidad de un algoritmo es necesario desarrollar aritmética en notación O, de tal manera que sea posible dividir el algoritmo y, a partir del estudio de sus partes, establecer el cálculo global. Teorema 1: Si TA(n) es O( k f(n) ) TA(n) es O( f(n) ) Este teorema expresa una de las bases del análisis de algoritmos: lo importante no es el valor exacto de la función que ocota el tiempo, sino su forma. Esto permite eliminar todos los Factores constantes de la función cota. Ejemplo: un algoritmo que es O(2n) también es O(n) un algoritmo que es O(6n2+2) también es O(n2) un algoritmo que es O(5+3n+2) también es O(n)
Análisis de Algoritmos Aritmética en notación O Teorema 2: Si A1 y A2 son segmentos de un algoritmo, tales que TA1(n) es O(f1(n)) y TA2(n) es O(f2(n)), el tiempo empleado para ejecutarse A1 seguido de A2 es O(max(f1(n), f2(n))). Esto quiere decir que la complejidad del programa resultante es igual a la complejidad del bloque más costoso. Ejemplo: a=1; b=1; c=1; Una asignación que no tiene llamadas a funciones se ejecuta en un tiempo constante, sin depender del número de datos del problema. TA(n) es O(max(1,1,1)) O(1)
for( i=0 ; i<n ; i++) for( j=0 ; j<n ; j++) cont++; A1 A A2 el tiempo de ejecución del programa Completo TA(n)=TA1(n) * TA2(n) es O(f1(n) * O(f2(n)) Análisis de Algoritmos Aritmética en notación O Teorema 3 Sea A un algoritmo que se forma: Tal que TA2 es O(f2(n)) y TA1 es O(f1(n)),
Análisis de Algoritmos Aritmética en notación O Donde: en los bucles con contador explícito, podemos distinguir dos casos, que el tamaño N forme parte de los límites o que no. Si el bucle se realiza un número fijo de veces, independiente de N, entonces la repetición sólo introduce una constante multiplicativa que puede absorberse. K= constante for (int i= 0; i <K; i++) { algo_de_O(1) } K*O(1) = O(1) a[0]=0;a[1]=0; a[2]=0;a[3]=0; A[4]=0; for(i=0; i<5 ; i++) a[i]=0; Complejidad del programa O(1)
Análisis de Algoritmos Aritmética en notación O Si el tamaño N aparece como límite de iteraciones ... for (int i= 0; i < N; i++) { algo_de_O(1) } N * O(1) = O(n) El tiempo de ejecución va a depender, del tamaño del N. Ciclos anidados for (int i= 0; i < N; i++) { for (int j= 0; j < M; j++) { algo_de_O(1) } } for (int i= 0; i < N; i++) { for (int j= 0; j < N; j++) { algo_de_O(1) } } N * N * O(1) = O(n2) N * M * O(1) = O(n*m)
Análisis de Algoritmos Aritmética en notación O El caso peor es cuando j se ejecuta N veces for (int i= 0; i < N; i++) { for (int j= 0; j < i; j++) { algo_de_O(1) } } el bucle exterior se realiza N veces, mientras que el interior se realiza 1, 2, 3, ... N veces respectivamente. En total, 1 + 2 + 3 + ... + N = N*(N+1)/2 -> O(n2)