Saltar a contenido

Operaciones estándar con arrays

Inserción. Posibles soluciones con Java

Para acceder a cada elemento del array se utiliza el nombre del array y un índice entre corchetes que indica la posición que ocupa el elemento dentro del array. Se puede utilizar como índice un valor entero, una variable de tipo entero o una expresión de tipo entero. Un elemento de un array se puede utilizar igual que cualquier otra variable. Se puede hacer con ellos las mismas operaciones que se pueden hacer con el resto de variables (incremento, decremento, operaciones aritméticas, comparaciones, etc).

Si se intenta acceder a un elemento que está fuera de los límites del array (un elemento con índice negativo o con índice mayor que el que corresponden al último elemento del array), el compilador no avisa del error. El error se producirá durante la ejecución. En ese caso se lanza una excepción java.lang.ArrayIndexOutOfBoundsException. Se puede saber el número de elementos del array mediante el atributo length. Podemos utilizar length para comprobar el rango del array y evitar errores de acceso.

Por ejemplo, para asignar un valor a un elemento del array que se lee por teclado:

import java.util.Scanner;

public class ejemploOperaciones {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int i, valor;
        int a[]= new int[10];
        System.out.print("Posición:");
        i = sc.nextInt(); // Pedimos la posición del array al que vamos a acceder
        if(i >= 0 && i < a.length){ // Si la posición está dentro del array
            System.out.println("Valor:"); // Pedimos el valor
            valor = sc.nextInt();
            a[i]= valor;
        }else{
            System.out.println("Posición no válida");
        }
    }
}

Para recorrer un array se utiliza una instrucción iterativa (normalmente una instrucción for, aunque también puede hacerse con while o do…while) utilizando una variable entera como índice que tomará valores desde el primer elemento al último o desde el último al primero. Por ejemplo, el siguiente fragmento de programa Java declara un array de 7 elementos de tipo double y le asigna valores iniciales. A continuación recorre el array, , utilizando la instrucción for, para mostrar por pantalla el contenido del array.

double[] notas = {2.3, 8.5, 3.2, 9.5, 4, 5.5, 7.0}; //array de 7 elementos
for (int i = 0; i < 7; i++) {
    System.out.print(notas[i] + " "); //se muestra cada elemento del array
}

Para evitar errores de acceso al array es recomendable utilizar length para recorrer el array completo.

double[] notas = {2.3, 8.5, 3.2, 9.5, 4, 5.5, 7.0}; //array de 7 elementos
for (int i = 0; i < notas.length; i++) {
    System.out.print(notas[i] + " "); //se muestra cada elemento del array
}

A partir de Java versión 5 se incorpora una instrucción for mejorada para recorrer arrays y contenedores en general. Permite acceder secuencialmente a cada elemento del array. La sintaxis general es:

for(tipo nombreDeVariable : nombreArray){
    
}
  • tipo: indica el tipo de datos que contiene el array.
  • nombreDeVariable: variable a la que cada iteración se le asigna el valor de cada elemento del array. Está definida dentro del for por lo que solo es accesible dentro de él.
  • nombreArray: es el nombre del array que vamos a recorrer.

Borrado. Posibles soluciones con Java

Las arrays en Java tienen longitudes fijas. Esto significa que tienen un número fijo de valores de un solo tipo. La longitud de una arrays se decide en el momento de su creación. Después de la creación, su duración es fija.

Dado que la longitud de la array es fija, no existe una forma estándar de eliminar elementos de ella. Sin embargo, puede crear una nueva array que contenga todos los elementos originales de la array excepto el que desea eliminar. Hay varias formas de lograr eso en Java.

A partir de Java 8

También puede aprovechar Stream API para eliminar un elemento de una array. La idea es convertir la array en una secuencia secuencial, filtrar la secuencia para eliminar el elemento dado y acumular los elementos restantes en una nueva array utilizando un colector.

import java.util.Arrays;
public class Main {
    public static int[] removeElement(int[] arr, int item) {
            return Arrays.stream(arr).filter(i -> i != item).toArray();
        }
    public static void main(String[] args) {
        int[] arr = {2, 5, 7, 3, 4, 8, 9};
        int item = 4;
        arr = removeElement(arr, item);
        System.out.println(Arrays.toString(arr));
    }
}

Eliminar por índice

Si tiene el índice del elemento a eliminar, puede usar el System.arraycopy() método para garantizar un mejor rendimiento. La idea es asignar una nueva array de tamaño uno menos que la array original. A continuación, puede realizar dos llamadas al System.arraycopy() para copiar los elementos de la array en la nueva array antes y después de ese índice.

import java.util.Arrays;
public class Main {
    public static String[] removeElement(String[] arr, int index) {
        String[] result = new String[arr.length - 1];
        System.arraycopy(arr, 0, result, 0, index);
        if (arr.length != index) {
            System.arraycopy(arr, index + 1, result, index, arr.length - index - 1);
        }
        return result;
    }
    public static void main(String[] args) {
        String[] arr = {"A", "C", "B", "C", "D"};
        int index = 1;
        arr = removeElement(arr, index);
        System.out.println(Arrays.toString(arr));
    }
}

¿Cómo "borramos"?

Como se ha visto, en Java el tamaño de los arrays es fijo y se define en memoria, por lo que si queremos borrar un elemento debemos rehacer el array. Si no se quiere instanciar un nuevo array, para eliminar el valor, se puede igualar al valor por defecto que se decida. De este modo, el valor se podría, mediante programación, no tener en cuenta y no supondría el tener que rehacer el array.

Ordenación: Burbuja e inserción directa

Uno de los procedimientos más comunes y útiles en el procesamiento de datos, es la ordenación de los mismos. Se considera ordenar el proceso de reorganizar un conjunto dado de objetos en una secuencia determinada. El objetivo de este proceso generalmente es facilitar la búsqueda de uno o más elementos pertenecientes a un conjunto. Son ejemplos de datos ordenados las listas de alumnos matriculados en una cierta asignatura, las listas del censo, los índices alfabéticos de los libros, las guías telefónicas, etc. Esto quiere decir que muchos problemas están relacionados de alguna forma con el proceso de ordenación. Es por lo que la ordenación es un problema a considerar.

La ordenación, tanto numérica como alfanumérica, sigue las mismas reglas que empleamos nosotros en la vida normal. Esto es, un dato es mayor que otro cuando su valor es más grande, y una cadena es mayor que otra cuando está después por orden alfabético.

En esta unidad no trataremos de analizar exhaustivamente todos los métodos de ordenación y ver sus prestaciones de eficiencia, rapidez, etc. sino que simplemente analizaremos desde el punto de vista práctico los métodos más comunes para la ordenación de arrays.

Método de la burbuja (Bubble sort)

Hay muchas formas de ordenar datos, pero una de las más conocidas es la ordenación por el método de la burbuja. Consiste en comparar pares de elementos adyacentes en un array y si están desordenados intercambiarlos hasta que estén todos ordenados. Si a es el array a ordenar, se realizan a.length-1 vueltas o pasadas. Si los elementos adyacentes están desordenados se intercambian.

Método de la burbuja

El código en Java correspondiente al algoritmo de ordenación por el método burbuja sería el siguiente:

Método de la burbuja

No es un buen algoritmo de ordenación por su elevado tiempo de ejecución, solamente es recomendable su uso para ordenar listas con un número pequeño de elementos.

Método de inserción (Insertion Sort)

El método de ordenación por inserción consiste en recorrer todo el array comenzando desde el segundo elemento hasta el final. Para cada elemento, se trata de colocarlo en el lugar correcto entre todos los elementos anteriores a él o sea entre los elementos a su izquierda en el array. Dada una posición actual p, el algoritmo se basa en que los elementos a[0], a[1], ..., a[p-1] ya están ordenados.

Método de inserción

Este método también puede ser optimizado: en lugar de intercambiar el elemento analizado con cada uno de los mayores hallados a su izquierda, puede modificarse el algoritmo para que el elemento analizado solo se inserte en su posición final de forma que se evitan las asignaciones intermedias innecesarias. Se trata del método de ordenación conocido como Inserción Directa (Direct Insertion Sort). El código es el siguiente:

Método de inserción

Método de selección (Selection Sort)

El método de ordenación por selección consiste en realizar los siguientes pasos:

  • Se busca el elemento más pequeño del array y se coloca en la primera posición.
  • Entre los restantes, se busca el elemento más pequeño y se coloca en la segunda posición.
  • Entre los restantes, se busca el elemento más pequeño y se coloca en la tercera posición.
  • Este proceso se repite hasta colocar el último elemento.
Método de selección

El código en Java para este algoritmo de ordenación es el siguiente:

Método de selección

Búsqueda: Secuencial y binaria

Java define la clase Arrays con métodos que permiten realizar operaciones de ordenación y búsqueda en objetos de tipo array. Estos métodos se pueden utilizar con todos los tipos primitivos, String y con cualquier otro tipo de objeto. Para ordenar arrays de cualquier tipo Java dispone del método sort de la clase Arrays.

Para utilizarlo es necesario incluir el import:

import java.util.Arrays;
Por ejemplo, dado el siguiente array de Strings:
String [] nombres = {"juan", "pedro", "ana", "maria", "felipe", "luis", "miguel"}; 
para ordenarlo de forma ascendente escribiremos la instrucción: Arrays.sort(nombres);

Otros métodos de la clase Arrays son:

  • Arrays.binarySearch(array-de-datos, clave). Busca la clave indicada en el array de números enteros. Arrays.binarySearch(numeros, 1991) busca el número 1991 en el array números.
  • Arrays.fill(array-de-datos, dato). Rellena el array con el valor dado. Se puede utilizar con todo los tipos primitivos, String y con cualquier otro tipo de objeto. Arrays.fill(numeros, 5) rellena con el valor 5 todo el array números.
  • Arrays.fill(array-de-datos, dato, inicio, fin). Rellena el array con el valor dado, indicando la posición inicial y final. Arrays.fill(numeros, 5, 0, 5) rellena con el valor 5 desde la posición 0 hasta la posición 5 del array numeros.
  • Arrays.copyOf(array-origen, longitud). Construye y devuelve una copia de array-origen con la longitud especificada. Si la longitud del nuevo array es menor que la del original, solo se copian los elementos que caben. En caso contrario, los elementos extras se inicializan por defecto.
    int[] t = {1, 2, 1, 6, 23}; //array origen
    int[] a, b; //arrays destino
    a = Arrays.copyOf(t, 3); //a = [1, 2, 1]
    b = Arrays.copyOf(t, 10); //b = [1, 2, 1, 6, 23, 0, 0, 0, 0, 0]
    
  • Arrays.copyOfRange(array-origen, desde, hasta). Crea y devuelve un array donde se han copiado los elementos de array-origen comprendidos entre los índices desde y hasta, sin incluir este último.
    int[] t = {7, 5, 3, 1, 0, -2};
    int[] a = Arrays.copyOfRange(t, 1, 4); //a = [5, 3, 1]
    

Arrays.sort ordena de forma ascendente (de menor a mayor). Para ordenar un array de forma descendente (de mayor a menor) hay que indicarlo utilizando el método reverseOrder() de la clase Collections. Como en este tema no se trabaja con colecciones, este método lo deberías de programar y tenerlo en vuestro fichero de métodos de utilidad.

Actividades

A tener en cuenta en las actividades

No está permitido el uso de los métodos de la clase Arrays. En caso de que se use el método sort()se anulará el ejercicio; cualquier otro método será penalizado pero el ejercicio será puntuado.

  • AC 503 (RA6 /CE6a / IC1 / 3p) Crea un programa que guarde en un array 10 números enteros leídos desde el teclado. A continuación se deberá recorrer el array y calcular cuántos números son positivos y cuántos negativos y así como sus respectivos promedios (medias).

  • AC 504 (RA6 /CE6a / IC1 / 3p) Genera un programa que lea 5 números por entrada estándar y los muestre por pantalla en orden inverso al introducido.

  • AC 505 (RA6 /CE6a / IC1 / 3p) Realiza un programa que lea por teclado la nota de los alumnos de una clase y calcule la nota media del grupo. También debe mostrar los alumnos con notas superiores a la media. El número de alumnos se lee por teclado. El array debe terminar ordenado de menor a mayor nota.

  • AC 506 (RA6 /CE6a / IC1 / 3p) En nuestro país cada persona está identificada con un DNI en el que figura un número y una letra, por ejemplo 56999545-W. Crea un programa que calcule la letra de un DNI a partir del número que introduzca el usuario. Es decir, se debe pedir el DNI sin la letra por teclado y el programa nos devolverá el DNI completo (con la letra). Para calcular la letra, se debe tomar el resto de dividir nuestro número de DNI entre 23. El resultado debe estar por tanto entre 0 y 22.

  • AC 507 (RA6 /CE6a / IC1 / 3p) En teoría hemos visto el método Array.equals. Imagina que la clase Arrays no existe. Implementa tú el método equals que compare si dos arrays pasados por parámetro son iguales (mismos elementos en el mismo orden).

  • AC 508 (RA6 /CE6a / IC1 / 3p) Implementa otra versión del método equals que compare si dos arrays son iguales, pero ahora teniendo en cuenta que dos arrays son iguales si tienen los mismos elementos, sin importar el orden.

    Ayuda

    Puedes hacerlo ordenando primero los arrays y luego comparándolos elemento a elemento como hicimos en el ejercicio 9 o puedes hacerlo creando en el método un nuevo array que realice un seguimiento de las posiciones que ya han sido comprobadas y no las tenga en cuenta.

  • AC 509 (RA6 /CE6a / IC1 / 3p) Crea un método para comprobar si un array contiene otro. El método devuelve true si el array fuente está contenido en el array destino, es decir, si todos sus elementos están en el array destino.

    public static boolean isArrayOn(int[] src, int [] dst) {}
    

  • AC 510 (RA6 /CE6a / IC1 / 3p) Crea un programa que dado un array insertado por el usuario, lea los valores, los inserte en un array, ordene el array en orden ascendente y muestre por pantalla el array ordenado. Para ordenar el array, deberás copiar el array que se pasa por parámetro en un nuevo array, ordenar ese nuevo array y devolverlo.
    public static int[] ordenarArray(int[] array) {}
    
  • PR 511 (RA6 /CE6a / IC2 / 5p) Vamos a crear una clase últil, como las que encontramos dentro del paquete java.util relacionadas con arrays. Llama a esta clase ArrayOperations.java. Dentro crearemos métodos estáticos, por tanto, asegúrate que sea una clase estática y nadie pueda llamar al constructor. Al ser estáticos los métodos, se utilizarán de la forma ArrayOperations.reverse(array). La clase debe incluir los siguientes métodos (algunos realizados en prácticas anteriores):

    • a. Método print que imprima el array con formato [1, 2, 3]. No utilices el método Arrays.toString, se trata de que lo programes tú.
    • b. El método reverse. Invierto un array.
    • c. Un método que devuelva el máximo elemento del array, llamado max. public static int max(int[] array)
    • d. Un método que devuelve el mínimo elemento del array, llamado min. public static int min(int[] array)
    • e. Método que realice la suma del array. public static int sum(int[] array)
    • f. El método equals que devuelva un booleano si dos arrays son iguales.
    • g. El método equals, llamado equalsWithoutOrder. Que comprueba si dos arrays son iguales sin importar el orden. [1,2,4,3] es igual a [1,2,3,4]
    • h. Método isArrayOn (AC509).
    • i. Método sort (AC 510). Este método se modifica ligeramente, ya que no hay que crear un nuevo array y devolverlo. Se ordena el array pasado por parámetro. public static void sort(int[] array)
    • j. Método copy, que copie el array fuente en el destino. En este método cada array apunta a una referencia distinta. public static void copy(int[] src, int[] dst)
    • k. Método removeOddNumbers que elimine del array los números impares. Es decir, cuando encuentre un número impar establezca un 0 en la celda. public static void removeOddNumbers(int[] array) Por ejemplo: [1,2,3] → [0,2,0]
  • PR 512 (RA6 /CE6a / IC2 / 5p) Se solicita crear un programa que haga las veces de una libreta de profesor. Para ello se deberá trabajar con Arrays y métodos. El programa ha de realizar las siguientes funciones:

    • Poder poner notas
    • Sacar la nota más alta y la posición.
    • Calcular la media de la clase quitando la nota más alta y más baja.
    • Borrar notas pero no la posición
    • Actualizar una nota en concreto

    Se ha de usar todo lo aprendido en Arrays y en el manejo de funciones.