LAS SERIES SON A LA VEZ LA ESTRUCTURA DE DATOS mas básica y mas importante, y las técnicas para procesar series serán una de las cosas mas importantes que va a aprender sobre programación. En  la siguiente sección trataremos dos técnicas fundamentales para el tratamiento de series: la búsqueda y la clasificación. En esta sección presentare algunas ideas generales sobre el tratamiento de series.

En muchos casos, procesar una serie significa aplicar la misma operación a cada elemento de la serie. Esto normalmente lo haremos con un bucle for. Un bucle para procesar todos los elementos de una serie tiene la forma:

             // inicializar elementos...
             for (int i = 0; i < A.length; i++) {
                . . . // procesar A[i]
             }

Suponga, por ejemplo, que A es una serie de tipo double[]. Suponga que el objetivo es sumar todos los números de la serie. El algoritmo informal para realizarlo sería:

            Empezar con 0;
            Sumar A[0];   (procesar el primer elemento de A)
            Sumar A[1];   (procesar el segundo elemento de A)
              .
              .
              .
            Sumar A[ A.length - 1 ];   (procesar el ultimo elemento de A)

Transformemos esta repetición tan obvia en un bucle y definamos sum para obtener esto:

            double sum = 0;  // arranca en 0
            for (int i = 0; i < A.length; i++)
               sum += A[i];  // suma A[i] a sum, para
                             //     i = 0, 1, ..., A.length - 1

Observe que la condición de continuación, «i<A.length», implica que el ultimo valor de i que realmente se procesara será A.length-1 que es el índice del ultimo elemento de la serie. Es importante el emplear «<» y no «<=» ya que en el segundo caso se produciría un error por violación de limites.

Actualmente, debería poder escribir bucles similares a este incluso durmiendo. Le muestro uno de los ejemplos mas simples. Aquí tenemos un bucle que cuenta el numero de elementos de una serie que son menores que cero:

              int count = 0;  // pone a 0 el contador de elementos
              for (int i = 0; i < A.length; i++) {
                 if (A[i] < 0.0)   //si este elemento es menor de cero...
                    count++;          //     ...lo contamos
              }
              // En este punto, el valor del contador es el
              //numero de elementos que han cumplido  < 0

Cambie la comparación «A[i] < 0.0", si quiere contar el numero de elementos de la serie que satisfacen cualquier otra propiedad. Aquí tenemos una variación sobre el mismo tema. Suponga que quiere contar el numero de veces que un elemento de la serie es igual al elemento siguiente. El elemento que sigue a A[i] en la serie, es A[i+1], entonces la comprobación a realizar será «A[i] == A[i+1]". Pero aquí hay un problema: La prueba no se puede realizar cuando A[i] es el  último elemento de la serie, ya que no existe A[i+1]. El resultado de intentar aplicar la prueba en este caso, significaría un error por violación de los limites de la serie. Esto significa que deberá detenerse un elemento antes del último elemento:

            int count = 0;
            for (int i = 0; i < A.length-1; i++) {
               if (A[i] == A[i+1])
                  count++;
            }

Otro problema típico es buscar el numero mas grande de A. La estrategia a seguir es recorrerse toda la serie, controlando cual es el mayor numero hasta el momento. Iremos guardando el numero mas grande hasta el momento en una variable llamada max. A medida que vamos avanzando por la serie, dondequiera que encontremos un numero mayor que el valor actual de max, cambiaremos el valor de max por ese numero. Cuando finalicemos el tratamiento de toda la serie, max contendrá el numero mas grande que contenía la serie. La única pregunta que queda es: ¿Con que valor deberemos inicializar max?. Parece lógico que empecemos con max igual a A[0], y buscaremos el numero mas grande en el resto de la serie, empezando en el elemento 1:

            double max = A[0];
            for (int i = 1; i < A.length; i++) {
               if (A[i] > max)
                  max = A[i];
            }
            // en este punto, max es el valor mayor de A

(Nos queda un problema muy sutil. En Java es posible que una serie tenga longitud cero. En este caso, A[0] no existe y la referencia que se hace en la primera línea a   A[0] provocaría un error de violación de limites. Sin embargo, las series de longitud cero son algo que debería evitar . De cualquier forma, que significado tiene preguntar por el elemento de mayor valor en una serie que no contienen elementos?).

Como ejemplo final sobre operaciones básicas con series, considere el problema de copiar una serie en otra. Para conseguir una copia de la serie A no basta con decir:

           double[] B = A;

porque esto, no creara un nuevo objeto Array. Todo lo que hará será declarar una nueva variable array y hacer que se refiera al mismo objeto a que se refiere A.(Esto quiere decir, por ejemplo que si cambiamos A[i] automáticamente quedara cambiado  B[i]). Para hacer que una serie nueva sea copia de A, es necesario crear un nuevo objeto array y copiar individualmente cada elemento de A en la nueva serie

           double[] B = new double[A.length]; // crear nuevo objeto array,
                                              // del mismo tamaño que A
           for (int i = 0; i < A.length; i++)
              B[i] = A[i];   // copiar cada elemento de A en B

Series parcialmente llenas

Una vez se crea el objeto array, su tamaño queda fijo. A menudo, sin embargo, el numero de elementos que quiere guardar en una serie va cambiando mientras el programa esta funcionando. Dado que el tamaño real de la serie no se puede cambiar, para poder controlar cuantos elementos hemos usado, es necesario utilizar una variable independiente como contador . (Naturalmente, cada espacio de la serie contiene algo; la pregunta es ¿cuantos elementos contienen algo útil o son validos?)

Suponga, por ejemplo, que está programando un juego, y los jugadores pueden dejar el juego e incorporarse a él sobre la marcha. Como un buen programador con orientación a objetos tendrá, posiblemente, una clase llamada Player que representa de forma individualizada a cada jugador. La lista de todos los jugadores que están participando en este momento puede guardarse en una serie, playerList de tipo Player[]. Como el numero de jugadores puede cambiar, también necesitara una variable, playerCt para guardar el numero de jugadores actuales. Asumiendo que nunca van a participar mas de 10 jugadores, podría declarar la variables como:

         Player[] playerList = new Player[10];  // max. 10 jugadores
         int      playerCt = 0;  // al principio no hay jugadores

Podemos encontrarnos con un problema si intenta añadir mas de 10 jugadores. Es posible el permitir un numero ilimitado de jugadores si esta dispuesto a crear una nueva serie cada vez que se queda sin espacio:

      // añadir nuevo jugador, aunque este llena la serie
      if (playerCt == playerList.length) {  // comprueba si esta llena
         Player[] temp = new Player[playerCt + 10];  // crea una mas grande
         for (int i = 0; i < playerCt; i++)
           temp[i] = playerList[i];  // copia la referencia a los objetos
         playerList = temp;  // deja playerList que apunte a la nueva
                             //La antigua, quedara como memoria libre
      }
      // En este punto, sabemos los que están jugando
      playerList[playerCt] = newPlayer; // añadimos nuevo jugador
      playerCt++;                       // y lo contamos

Quitar un jugador de la partida es un poco mas difícil, ya que no querrá dejar huecos en la serie. Suponga que quiere borrar el jugador que esta en el índice K de playerList. Si no tienen que preocuparse de mantener a los jugadores en un orden determinado, una forma de hacer esto es mover el jugador que esta en la ultima posición de la serie, a la posición k y decrementar. el valor de playerCt:

         playerList[k] = playerList[playerCt - 1];
         playerCt--;

Es importante destacar que con el ejemplo de los jugadores,  vemos como podemos tratar con series cualquier cosa basada en clases. Un elemento de la serie puede ser nulo o referenciar un objeto perteneciente a la clase Player. Los objetos Player no se guardan en la serie, pero debido a las reglas de asignación de Java, los objetos pertenecen realmente a una subclase de Player.

Otro ejemplo, suponga que la clase Shape representa la idea general de un dibujo en la pantalla, y tiene unas subclases que representan tipos concretos de figuras como líneas, rectángulos, rectángulos redondeados, elipses, elipses rellenas, y mas. (Shape en si misma, es una clase abstracta, como se explicó en la Sección 4.3). Entonces, podemos declarar un array de tipo Shape[] y podemos guardar referencias a objetos pertenecientes a las subclases de Shape. Por ejemplo la situación creada por la instrucciones

       Shape[] shapes = new Shape[100]; // array para guardar 100 figuras
       shapes[0] = new Rect();        // ponemos algunos objetos en la serie
       shapes[1] = new Line();          //En un programa real, deberá
       shapes[2] = new FilledOval();    //utilizar parametros.) 
       int shapeCt = 3;  // controla el numero de objetos en la serie

podemos representarla como:

Curso de Java. Procesando arrays

Como vemos, una serie puede ser muy útil en un programa de dibujo. La serie puede emplearse para guardar la lista de las figuras que tienen que presentarse. Si la clase Shape incluye el método redraw() para realizar los dibujos, entonces todas las figuras de la serie podrán ser dibujadas con un sencillo bucle:

            for (int i = 0; i < shapeCt; i++)
               shapes[i].redraw();

La instrucción «shapes[i].redraw();»  llama al método redraw() perteneciente a la figura concreta indicada por i. Cada objeto sabe como se debe dibujar, por lo que la repetición de la instrucción puede crear una variedad de diferentes figuras en la pantalla. Todo esto es un bello ejemplo del poliformismo. y del proceso de las series.

Un comentario sobre “Java para programadores (7.2).Tratamiento de Arrays”

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.