2. Arreglos e invariantes

Slides:



Advertisements
Presentaciones similares
ALGORITMOS DE ORDENAMIENTO
Advertisements

Algoritmos para Ordenar datos
Ordenación y Búsqueda.
1. Desarrollo de Programas iterativos usando invariante
2. Strings, Archivos y Arreglos
Universidad Domingo Savio Facultad de Ciencias y Tecnología de la Información Carrera Ingeniería en Redes y Telecomunicaciones Materia : Programación I.
ESTRUCTURAS DE DATOS “Conceptualización de estructuras de datos” Por: Eduardo Robayo.
INTRODUCCIÓN A LA PROGRAMACIÓN ORIENTADA A OBJETOS Arreglo.
Applications Development I 6.1 Foro Tomas Anzalotta Alvarado.
2. Arreglos e invariantes. Arreglos Un arreglo es una coleccion ordenada de elementos del mismo tipo – Tipos de datos primitivos (int, …) – Referencias.
BUSQUEDAS BINARIAS Y SECUENCIALES Hernández Salazar Alma Pérez González Luis Alberto Villa Méndez Edgar Adrián Villegas Titla Jorge Ramsés Ríos Álvarez.
Búsqueda Binaria Castillo Soria Luis Fernando Méndez Tinajero Armando Pérez Ramos Susana.
1 Ordenación, Clasificación Introducción Algoritmos Complejidad.
Convenciones de nomenclatura y diseño
Estructuras de Control en Visual Basic.net
TECNOLOGICO DE ESTUDIOS SUPERIORES DE COACALCO
2.  Diagramas de Estado.
Clase 8: Strings Valeria Herskovic –
Optimización: Programación Lineal
Ciclos condicionales y exactos Estructura de control de ciclos
Olimpiadas Chilenas de Informática - Formación
Ingeniería en Sistemas
Diagramas de Flujo Algoritmos.
INVESTIGACIÓN DE OPERACIONES
Colecciones Carlos Fontela, 2008.
MANEJO DE ARRELOGS EN C Clase 8: Arreglos.
1. Desarrollo de Programas iterativos usando invariante
Estructuras de control iterativas
Estructuras de Control en Visual Basic.net
Métodos en Java.
Clases y Objetos en Java
INTRODUCCIÓN A LA PROGRAMACIÓN ORIENTADA A OBJETOS
IPOO 2 cuatrimestre 2017 Departamento de Ciencias e Ingeniería
TUTORIAL PSeint.
Sonia Rueda Herencia y Polimorfismo
Listas Dinámicas.
Fundamentos del lenguaje de programación Condicionales, ciclos, Métodos, enumeraciones Escuela Técnica Superior Kinal Instructor Edwin Tumax.
Manejo de Punteros y objetos en memoria dinámica en C++
ALGORITMOS es un conjunto preescrito de instrucciones o reglas bien definidas, ordenadas y finitas que permite realizar una actividad mediante pasos.
Unidad 3. Introducción a la programación
ESTRUCTURA DE UN PROGRAMA SIMPLE EN JAVA
HISTORIA El lenguaje fue creado por Yukihiro "Matz" Matsumoto, quien empezó a trabajar en Ruby el 24 de febrero de 1993, y lo presentó al público en el.
Plantillas (Templates)‏
Estructuras Estructuras En la creación de soluciones para algunos problemas surge la necesidad de agrupar datos de diferente tipo o de manejar datos que.
Manejo de Punteros y objetos en memoria dinámica en C++
Aplicaciones de RECURSIVIDAD
ESTRUCTURAS DE CONTROL EN VISUAL BASIC.NET Prof.: Rafael Mourglia.
ELEMENTOS DE COMPUTACIÓN Profesor: Guillermo Figueroa
Estructuras de Repetición Pseudocodigo1 Estructuras de Repetición Algoritmos Mientras Hacer-Mientras Para.
Fundamentos de programación
Fundamentos de Informática Especialidad de Electrónica –
EL TDA COLA Estructuras de Datos.
Arreglos en Java.
INTRODUCCIÓN A LA PROGRAMACIÓN ABRAHAM SOPLA MASLUCÁN MAESTRO EN CIENCIAS DE LA COMPUTACIÓN INSTITUTO TECNOLÓGICO DE MONTERREY.
CICLOS EN JAVA FOR, WHILE, DO WHILE Un ciclo en Java o bucle en Java (como prefieras llamarlo) permite repetir una o varias instrucciones cuantas veces.
Manejo de Punteros y objetos en memoria dinámica en C++
Método de Ordenamiento por Inserción. El método recorrer el Vector de Izquierda a Derecha, tomando la posición Actual y Comparándola con su Izquierda.
TUTORIAL PS EINT FUNDAMENTOS DE PROGRAMACIÓN Ing. Elizabeth Díaz Orea.
METODOS DE ORDENAMIENTO CHRISTIAN MICHAEL OBANDO GARCES JOAO ADRIAN BARIONUEVO.
TUTORIAL PS EINT FUNDAMENTOS DE PROGRAMACIÓN Ing. Elizabeth Díaz Orea.
Árboles Binarios Estructuras de Datos.
COLAS O LINEA DE ESPERA EN C# SHARP. ¿QUE ES UNA COLA O LINEA DE ESPERA?  Es una estructura de datos que almacena elemento en una lista y permite acceder.
Manejo de Punteros y objetos en memoria dinámica en C++
METODOS DE ORDENAMIENTO
Estructuras de Repetición Algoritmos
Manejo de Punteros y objetos en memoria dinámica en C++
Casos de estudio Estudiaremos tres problemas
Templates (en español: Pantillas, modelos, patrones)‏
ALGORITMO DE ORDENAMIENTO POR BURBUJA. El método de la burbuja es uno de los mas simples, es tan fácil como comparar todos los elementos de una lista.
Transcripción de la presentación:

2. Arreglos e invariantes

Arreglos Un arreglo es una coleccion ordenada de elementos del mismo tipo Tipos de datos primitivos (int, …) Referencias a objetos El tamaño es definido en la creación (new) y no puede ser modificado

Arreglos de Tipos Primitivos int[] x; // equivalente a int x[] x = new int[3]; x[0] = 10; X 10 x[1] = 20; 20 30 x[2] = 30; Nota: x.length es una variable final que entrega el tamaño del arreglo

Arreglos de Objetos Circulo[] x; x = new Circulo[3]; Referencias X Circulo[] x; x = new Circulo[3]; x[0] = new Circulo(); x[1] = new Circulo(); x[2] = new Circulo();

Arreglos de Arreglos Java permite crear arreglos de arreglos con la siguiente sintaxis int[][] matriz = new int[4][]; for (int i = 0; i < matriz.length; i++) { matriz[i] = new int[5]; for (int j = 0; j < matriz[i].length; j++) { matriz[i][j] = i + j; }

Arreglos de Strings Paso de parámetros Static public void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println(″Argumento ″+(i+1)+ ″ = ″+args[i]); }

Inicialización de Arreglos Un arreglo puede inicializarse con la siguiente sintaxis: boolean[] respuestas = {true, false, true}; String[] nombres = {"Ana María", "Carlos"}; String[][] humor = { { "Coco Legrand", "Alvaro Salas" }, { "Les Luthiers" }, { "Groucho Marx", "Buster Keaton", "Jerry Lewis", "Woody Allen" } };

for-each (desde Java 5.0) Java 5.0 introdujo un for simplificado para recorrer arreglos y otras estructuras El siguiente método retorna la suma de los elementos de un arreglo // Java 1.4 o anterior int sum(int[] a) { int result = 0; for (int i=0; i<a.length; i++) { result += a[i]; } return result; // Java 5.0 int sum(int[] a) { int result = 0; for (int x : a) { result += x; } return result;

Ejemplo: Búsqueda del máximo Estrategia: revisar todos los elementos a[0] hasta a[n-1] y registrar el mayor visto hasta ahora en m Invariante: m = max(a[0] … a[k]), 1 <= k<n a0 a1 ai an-1 . . . k

El invariante de una iteración Invariante: Condición (conjunto) que describe lo que un ciclo hace. Permanece invariante: al entrar, en cada iteración y al final. Debería representar la estrategia que se usa para resolver el problema. Se usa para: -       A partir del invariante desarrollar el trozo de programa -       Demostrar que el trozo programa hace lo que queremos -       Explicar un trozo de programa Al escribir un ciclo con invariante se debe a) establecer la validez inicial del invariante, instrucciones de inicialización. b) avanzar hacia un estado final F. c) cada iteración debe preservar la validez del invariante.

Condiciones iniciales y finales a) El invariante se debe cumplir antes de entrar al ciclo, pero no hemos revisado nada aún. Podemos decir que el primero es el mayor de los revisados hasta ahora m = a[0]; k = 0; a0 a1 ai an-1 . . . k b) Para conseguir el objetivo, k debe valer n, por lo que debemos parar el ciclo cuando k = n, o continuarlo mientras k != n, o k < n a0 a1 ai an-1 . . . k

Avanzar y restablecer el invariante c) Para avanzar hay que tratar de que k llegue a n. Esto se hace incrementando k. Esto puede significar que el invariante no se cumple pues el nuevo a[k] podría ser mayor que m. k++; Para restablecer el invariante podemos incluir en el ciclo las siguientes instrucciones (después de incrementar k) if (a[k] < m) m = a[k]; Ahora solo basta ensamblar a), b) y c) para tener el trozo de programa que hace lo que queremos a0 a1 . . . ai ai+1 . . . an-1 k

Ejemplo 1: ordenación por selección Este algoritmo se basa en hacer pasadas sucesivas sobre los datos. En cada pasada, se encuentra el máximo del arreglo, y se lo lleva al extremo derecho. Una vez hecho esto, ese elemento deja de ser considerado, porque se encuentra ya en su posición definitiva. Esto conduce al siguiente invariante: a[i] < a[i+1] para i = k hasta n-1 a[j] < a [i] con j = 0 hasta k-1, todos desordenados En palabras: "Los elementos desde k hasta n-1 ya están ordenados y son mayores que los primeros k".

Condiciones iniciales y finales Condiciones iniciales: al principio no se puede decir nada, por lo que se hace k = n, lo que dice que implica: a[i] < a[i+1] para i = n hasta n-1 (no existe elemento) a[j] < a [n] con j = 0 hasta n-1, todos desordenados (a[n] no existe) ¿Más comprensible?: al principio poner el mayor del arreglo en el lugar n-1 y hacer k = n-1 b) Condición final: k = 1 (o mientras k >= 2) a[i] < a[i+1] para i = 1 hasta n-1 a[j] < a [1] con j = 0 hasta 0, todos desordenados

Ord. x selección: avanzar y restablecer invariante // Ordenar a[0], ..., a[n-1] por selección  k = n; // inicialmente los n primeros están desordenados while( k>1 )  { --k; //acercar k a la meta, se rompe el invariante     Llevar el max de a[0], ..., a[k] hacia a[k]; //esto restablece el invariante   } Donde Llevar el max de a[0], ..., a[k] hacia a[k] => i = 0; // a[i] es el max hasta el momento for( j=1; j<=k; ++j )     if( a[j]>a[i] )         i = j; // ahora intercambiamos a[i] con a[k] t = a[i]; a[i] = a[k]; a[k] = t;

Ejemplo 2: ordenación por inserción Este algoritmo va construyendo un trozo ordenado del arreglo al extremo izquierdo, y en cada iteración le agrega un nuevo elemento a ese grupo. Invariante: a[i] < a[i+1] para i = 0 hasta k-1 a[k] hasta a[n-1] desordenados En palabras: "Los elementos desde 0 hasta k-1 ya están ordenados y los siguientes desordenados".

Condiciones iniciales y finales Condiciones iniciales: al principio se puede decir que el primer elemento a[0] está ordenado por definición, por lo que se hace k = 1, lo que implica: a[i] < a[i+1] para i = 0 hasta 1-1 a[1] hasta a[n-1] desordenados b) Condición final: k = n (o mientras k < n) a[i] < a[i+1] para i = 0 hasta n-1 a[n] hasta a[n-1] desordenados (no existe!)

Avanzar y restablecer invariante // Ordenar a[0], ..., a[n-1] por inserción  k = 0; // inicialmente el primer elemento esta ordenado while( k < n )  { ++k; //acercar k a la meta, se rompe el invariante Insertar a[k-1] entre a[0],...,a[k-2]; //esto restablece el invariante   } Donde Insertar a[k-1] entre a[0],...,a[k-2] => for( j=k-1; j>0 && a[j-1]>a[j]; --j )  {     // intercambiar a[j-1] con a[j]     t = a[j];    a[j] = a[j-1];    a[j-1] = t;

Optimización Al seguir el proceso de la inserción, se puede observar que la variable t toma siempre el mismo valor: el del elemento que se está insertando. Por lo tanto, se puede optimizar el programa realizando una única asignación a t antes de comenzar el ciclo. Otra observación es que la mayoría de las asignaciones a a[j-1] son inútiles, porque esa variable va a ser sobre-escrita en la iteración siguiente. Luego, se puede evitar esas asignaciones, reemplazándolas por una sola al final del ciclo: Insertar a[k-1] entre a[0],...,a[k-2] => // versión optimizada t = a[k]; for( j=k; j>0 && a[j-1]>t; --j )     a[j] = a[j-1]; a[j] = t;

Versión final optimizada (y algo variada) // Ordenar a[0],...,a[n-1] por inserción k = 1; // inicialmente primer elemento ordenado while( k < n )  {     // Insertar a[k] entre a[0],...,a[k-1]     t = a[k];     for( j=k; j>0 && a[j-1]>t; --j )         a[j] = a[j-1];     a[j] = t;     ++k;  }

Ejemplo 3: ordenación por burbuja Este método se basa en hacer pasadas de izquierda a derecha sobre los datos, intercambiando pares de elementos adyacentes que estén fuera de orden. Al final de cada pasada, en forma natural el máximo estará en la posición de más a la derecha (que es su posición final) y puede por lo tanto ser excluido en pasadas sucesivas. Esto conduce al siguiente invariante (idéntico al de ordenación por selección): a[i] < a[i+1] para i = k hasta n-1 a[j] < a [i] con j = 0 hasta k-1, todos desordenados

Ord. X burbuja: avanzar y restablecer invariante // Ordenar a[0], ..., a[n-1] por la burbuja (borrador) k = n; while( k>1 )  {     Hacer una pasada sobre a[0], ..., a[k-1];     Disminuir k;   } Donde Hacer una pasada sobre a[0], ..., a[k-1] => for( j=0; j<=k-2; ++j )    if( a[j]>a[j+1] ){ // Intercambiar a[j] con a[j+1]        t = a[j]; a[j] = a[j+1]; a[j+1] = t;    } y Disminuir k =>--k;

Ord. X burbuja: eficiencia Disminuir k => --k; Si el archivo está inicialmente ordenado, el programa igual hace n pasadas, cuando después de la primera ya podría haberse dado cuenta que el archivo ya estaba ordenado. Para aprovechar cualquier posible orden que pueda haber en el archivo, se puede hacer que el programa anote ("recuerde") el lugar en donde se produjo el último intercambio. Si la variable i se define de manera que el último intercambio en una pasada dada fue entre a[i-1] y a[i], entonces todos los elementos desde a[i] en adelante están ya ordenados (de lo contrario habría habido intercambios más hacia la derecha), y por lo tanto k se puede disminuir haciendo que sea igual a i: Hacer una pasada sobre a[0], ..., a[k-1] => i=0; for( j=0; j<=k-2; ++j )   if( a[j]>a[j+1] )   {    t = a[j];  a[j] = a[j+1]; a[j+1] = t;        i = j+1; //Recordar el lugar del último intercambio   } Disminuir k => k=i;

Ejemplo 4: Xn Cuando n es entero se puede programar una función más eficiente que la que usa java, basada en el cálculo de una serie. Incluso una solución simple sería más eficiente: public static double power(double x, int n) { // Algoritmo simple int y = 1; for( int j=n; j>0; --j )     y = y*x; return y; } Este algoritmo evidentemente toma tiempo O(n), y su invariante se puede escribir como         y * xj == xn

Aprovechando el invariante para la eficiencia Es posible encontrar un algoritmo sustancialmente más eficiente de la siguiente manera. public static double power(double x, int n) { int j = n; long z = x; int contador = 0; while (j>1) { if (j%2 == 0){ z = z*z; j = j/2; } else { z = x*z; j = j-1; } System.out.println(“Resultado = "+z); con invariante z* xj == xn

Algoritmo algo más eficiente aún Sacando x del invariante public static double power(double x, int n) { int y = 1, z = x; for( int j=n; j>0; --j ) {     while( j%2 == 0) {        z = z*z;         j = j/2;     }     y = y*z;  } Con invariante y * zj = xn

Algoritmo eficiente no recursivo Mejor todavía, si esto se puede hacer una vez, entonces se puede hacer muchas veces siempre que j siga siendo par: y = 1; z = x; for( j=n; j>0; --j ) // Invariante: y * zj == xn  {     while( j es par )      {        z = z*z;         j = j/2;       }     y = y*z;  } La detección que j es par se puede implementar como j es par => j%2 == 0   Este algoritmo demora tiempo O(log n), lo cual se debe a que j sólo se puede dividir log n veces por 2 antes de llegar a 1. Es cierto que j sólo se divide cuando es par, pero si es impar en una iteración del for, está garantizado que será par a la siguiente.

Ejemplo 4: Explicar un algoritmo difícil Se tiene un arreglo con n elementos (a[0] hasta a[n-1]) blanco y negros desordenados. Dejar los elementos intercalados. Si hay mas de una clase que de otra dejarlos todos al final. Ejemplo, si inicialmente se tiene dejarlos invariante ??????????? i j

Ejemplo 4: Explicar un algoritmo difícil (cont.) Inicialmente se hace i = 0; j = 1; Condicion final: j = n => continuación: while (j < n) Restablecer el invariante i j j i ?????????? i j Si a[j] mismo color que a[i] no se hace nada, si no, se intercambia con a[i+1]; j++

Otras Estructuras: Vector Una implementación de lista enlazada eficiente Puede contener objetos de cualquier clase Ultimas versiones de java apuntan a que todos sean de una sola (super)clase Vector v = new Vector(); //crea un vector vacio v.add(“Hola”); v.add(new Scanner()); ... //agregar elementos al final, v.add(5, “chao”); //agrega en el indice 5 //mostrar los elementos for(int i = 0; i < v.size(); i++) System.out.println(v.get(i).toString());

Generics: chequeo de tipos Usando Generics se puede hacer que se chequee el tipo de objeto Vector<Tipo> v = new Vector<Tipo>(); Solo se pueden poner objetos de la Clase Tipo (o derivados) v.add(“Hola”); //produciría error de compilación

Ejercicio en clases Se tiene un arreglo a[0] . . . a[n-1] con enteros y se quiere particionarlo de modo que queden todos los menores que cero a la izquierda y los iguales o mayores que cero a la derecha. En palabras: los elementos anteriores a a[i] son menores que cero, los elementos desde a[i] hasta a[j-1] son mayores que cero y los elementos desde a[j] en adelante son desconocidos <= 0 > 0 desconocidos i j