Introducción a la programación y la informática. Tema 10
1. Tema 10. Arrays: definición y
aplicaciones
Introducción a la Informática y a la Programación (IIP)
Curso 2011/12
Departamento de Sistemas Informáticos y Computación
2. Contenidos
1. Arrays unidimensionales
2. Tratamiento secuencial y directo de un array
3. Representación de una secuencia de datos dinámica
usando un array
4. Arrays multidimensionales
5. Más problemas de acceso directo
6. Problemas propuestos
25/11/2011 IIP - Curso 2011/12 2
3. Introducción
• A menudo interesa almacenar y referenciar variables que
representan una colección de valores, para poder tratarlos de
forma uniforme.
• Ejemplos:
– Obtener estadísticas básicas sobre medidas diarias de la temperatura
media en una determinada zona geográfica.
– Manejar una colección de objetos homogéneos, por ejemplo, una clase
Garaje que pueda tener asociado un conjunto de objetos de tipo
Vehiculo.
– …
• Java proporciona el array como mecanismo para agrupar datos
de tipo homogéneo (tanto de tipo objeto como de tipo
primitivo).
25/11/2011 IIP - Curso 2011/12 3
4. Arrays unidimensionales
• Definición: Un array es una colección de elementos homogéneos
(del mismo tipo de datos) agrupados de forma consecutiva en
memoria.
• Características
– Cada elemento de un array tiene asociado un índice, que es un
número entero no negativo que lo identifica inequívocamente y
permite acceder a él.
– El tamaño (número de componentes) del array debe establecerse
en su declaración y es invariable a lo largo de la ejecución.
– El acceso a los elementos de un array es directo (gracias a su
índice).
• Estas estructuras de datos son adecuadas para situaciones en las
que el acceso a los datos se realice de forma aleatoria (esto es,
conjuntos de datos que pueden ser indexados) o secuencial.
25/11/2011 IIP - Curso 2011/12 4
5. • Valores: Se representan como una sucesión de elementos entre llaves y
separados por comas.
{e0, e1, … ,en-1}
• Operador de arrays: Operador de acceso a las componentes []
nomVble[índice]
índice es una expresión que se evalúa a un valor válido para el array
nomVble.
• Declaración y creación:
– Declaración: tipo[] nomVble; ó tipo nomVble[];
– Inicialización (con componentes): nomVble = new tipo[tamaño];
– Conjuntamente: tipo[] nomVble = new tipo[tamaño];
tipo es cualquier tipo primitivo o referencia, nomVble es cualquier
identificador válido y tamaño es una expresión que se evalúa a un entero
no negativo y determina la cantidad de componentes.
25/11/2011 IIP - Curso 2011/12 5
Arrays unidimensionales
Declaración y uso
Válido pero
desaconsejado
6. • Todos los arrays disponen de un atributo constante (de sólo
consulta) length que indica la cantidad de componentes
(tamaño) de un array:
nomVble.length
• Los índices válidos de un array van desde 0 hasta length-1.
• Una variable array puede verse como una referencia a la posición
de memoria del primer elemento del array.
• Existe una referencia especial que puede utilizarse con cualquier
array (o con otros tipos referencia): null.
• Todas las componentes de arrays de tipo numérico se inicializan
por defecto a 0.
• Todas las componentes de arrays de tipo referencia (p.e., un
array de String) se inicializan por defecto a null.
25/11/2011 IIP - Curso 2011/12 6
Arrays unidimensionales
Declaración y uso
7. • Gráficamente podemos ver un array como sigue:
25/11/2011 IIP - Curso 2011/12 7
Arrays unidimensionales
Declaración y uso
e0 e1 e2 e3 en-1
0 1 2 3 … nomVble.length-1
nomVble
donde n = nomVble.length y todos los ei , 0≤i<n, son del mismo
tipo.
Variable referencia Componentes
Valores
Índice
Tamaño
Último índice
8. • Array de 5 caracteres:
– Variable referencia: char[] letras;
– Objeto array (con componentes): letras = new char[5];
– Conjuntamente: char[] letras = new char[5];
• Dos arrays de enteros:
int[] numeros1 = new int[5000], numeros2 = new int[50];
• Array de 20 cadenas de caracteres: final int NUM = 10;
String[] nombres = new String[NUM*2];
• Array de reales cuya cantidad de componentes se decide por teclado:
double[] precios = new double[teclado.nextInt()];
• Creación e inicialización de un array de 4 enteros: int[] v={-5,6,10,3};
25/11/2011 IIP - Curso 2011/12 8
‘V’ ‘g’ ‘A’ ‘i’ ‘J’
letras
0 1 2 3 4 = letras.length-1
Arrays unidimensionales
Declaración y uso - Ejemplos
9. • En un array de tamaño N, los índices válidos para acceder a sus
componentes pertenecen al intervalo [0, N−1].
• Un acceso fuera de dicho intervalo producirá una excepción en
ejecución del tipo:
java.lang.ArrayIndexOutOfBoundsException
• Por ejemplo:
int[] n = new int[10];
int a = n[11]; // Produce una excepción
a = n[-1]; // Produce una excepción
• El acceso a las componentes de un array debe controlarse utilizando las
cotas inferior (0) y superior (nomVble.length-1) de los índices.
25/11/2011 IIP - Curso 2011/12 9
Arrays - Excepciones
10. • Una variable referencia array (nomVble) utiliza la memoria donde haya
sido definida.
• Las componentes del array se crean en el montículo o heap que es una
zona de memoria reservada para guardar variables dinámicas.
• Las variables dinámicas son variables que se crean en tiempo de
ejecución mediante la operación de creación new.
• Las componentes sólo son accesibles si existe una referencia a ellas.
• Es posible sugerir la destrucción de un array v al desreferenciarlo (v =
null)
– Recuerda que existe un mecanismo de recolección de basura (garbage
collector) que se activa automáticamente en tiempo de ejecución y libera la
memoria que está ocupada pero no es accesible al no estar referenciada.
– También se puede sugerir su ejecución mediante la instrucción System.gc().
25/11/2011 IIP - Curso 2011/12 10
Arrays - Memoria
11. • Las componentes de un array pueden verse como variables del tipo de
los elementos del array.
nomVble[índice] = expresión;
expresión debe ser del tipo de las componentes del array nomVble.
• La asignación entre arrays sólo afecta a las referencias.
int[] v1 = {1,3,2,0};
int[] v2;
v2 = v1;
boolean igual = (v1==v2);
// igual vale true
• Si se desea una copia de un array se deben crear nuevas componentes
y realizar la asignación de cada uno de los valores.
v2 = new int[4];
v2[0]=v1[0]; v2[1]=v1[1];
v2[2]=v1[2]; v2[3]=v1[3];
igual = (v1==v2);
// igual vale false
25/11/2011 IIP - Curso 2011/12 11
1 3 2 0
v1
v2 0 1 2 3
1 3 2 0v1
v2
0 1 2 3
1 3 2 0
0 1 2 3
Arrays unidimensionales - Asignación
12. • Los arrays se definen como cualquier parámetro formal, indicando el
tipo y el nombre de la variable
static int metodo1(int[] v1, int[] v2) { … }
public static void main(String[] args) { … }
• En la llamada, sólo se utiliza el nombre de la variable:
int i = metodo1(a1,a2);
• Cuando se invoca a un método con algún argumento de tipo referencia
sólo se copia la referencia del parámetro real en el formal.
• Los métodos pueden devolver como resultado un array (referencia a las
componentes). Por ejemplo:
static char[] metodo2(int[] v1) {
char[] nuevo = new char[v1.length+10];
…
return nuevo;
}
25/11/2011 IIP - Curso 2011/12 12
Arrays unidimensionales - Métodos
13. Ejemplo: Paso de arrays como parámetros
25/11/2011 IIP - Curso 2011/12 13
public class PasoParametros {
public static void main(String[] args) {
double[] elArray = {5.0, 6.4, 3.2, 0.0, 1.2};
metodo1(elArray);
// el array no ha sido modificado en absoluto
metodo2(elArray);
// la primera componente del array vale ahora 0.1
}
public static void metodo1(double[] copia) {
copia = new double[5]; // Este array desaparece al acabar el método
}
public static void metodo2(double[] copia) {
copia[0] = 0.1;
}
}
14. Arrays de objetos
• Es posible construir arrays de objetos.
• Las componentes del array valdrán inicialmente null.
25/11/2011 IIP - Curso 2011/12 14
class Estudiante {
private long dni;
private double nota;
private String nombre;
private boolean asistencia;
...
}
public static void main(String[] args) {
Estudiante grupo[] = new Estudiante[56];
grupo[0] = new Estudiante();
grupo[0].setDni(12123123);
grupo[0].setNota(8.5);
grupo[0].setNombre(“Luisa García”);
grupo[0].setAsistencia(true);
}
15. • Gráficamente:
25/11/2011 IIP - Curso 2011/12 15
Arrays de objetos
null null null null
0 1 2 3 … 55
grupo.length-1
grupo
dni
nota
nombre
asistencia
12123123
8.5 true
“Luisa García”
grupo[0]
Estudiante
16. Array de objetos - Ejemplo
• Se asume que la clase Punto implementa el método distancia.
25/11/2011 IIP - Curso 2011/12 16
public class TestArrayObjetos {
public static final int NUM_PUNTOS = 20;
public static void main(String[] args) {
Punto[] camino = new Punto[NUM_PUNTOS];
for(int i=0; i<camino.length; i++)
camino[i] = new Punto();
// se han creado los 20 objetos Punto de camino
...
System.out.println("Distancia entre los dos primeros
puntos: " + camino[0].distancia(camino[1]));
Punto[] copiaP = copiarPunto(camino);
}
public static Punto[] copiarPunto(Punto[] orig) {
Punto[] copia = new Punto[orig.length];
for (int i=0; i<orig.length; i++)
copia[i] = new Punto(orig[i].getX(),orig[i].getY());
return copia;
}
}
17. Tratamiento secuencial y directo
de un array
25/11/2011 IIP - Curs 2011/12 17
• Por lo general se consideran dos tipos de tratamiento de los elementos
de una estructura lineal: los denominados tratamiento directo y
secuencial:
– Directo: Se accede a los elementos por su posición, sin ningún patrón de acceso
específico.
• Ejemplos de acceso por posición: Problemas que usan la estructura como un conjunto
de contadores o como referencias posicionales,
• Ejemplos más complejos: Problemas que aprovechan el acceso directo de los arrays y las
propiedades de ordenación de sus elementos como la búsqueda binaria o los algoritmos
de ordenación, etc. (Se verán más adelante)
– Secuencial: Se accede a los elementos de la estructura (o de una parte de ella)
posicionalmente, uno detrás del otro.
• Ejemplos: Problemas de recorrido y búsqueda secuencial.
• Como los arrays son estructuras de acceso directo, cualquiera de los
dos tipos de tratamiento es posible.
18. Acceso directo I: array de contadores
Supongamos que queremos contar los números las veces que un usuario
escribe números del 0 al 9. Una solución inadecuada, sería definir 10
variables contador1, contador2, ... contador10 y una estructura de
switch o de if anidados para incrementar el contador correcto en cada
caso. La solución ideal, sería usar un array de contadores:
25/11/2011 IIP - Curso 2011/12 18
import java.util.Scanner;
public class EjemploContadores {
public static void main(String[] args) {
Scanner tec = new Scanner(System.in);
int[] contadores = new int[10]; boolean salir = false;
do{ val=tec.nextInt();
if (val>=0 && val<=9) contadores[val]++;
else salir=true;
}while(!salir);
}
}
19. Acceso secuencial: recorrido y
búsqueda
• Un recorrido se caracteriza por tener que visitar todos los elementos
del array para poder encontrar la solución del problema.
– Por el contrario, una búsqueda persigue encontrar el primero elemento que
cumple una característica dada.
• El recorrido de arrays se utiliza para resolver problemas que precisan
procesar todos los datos para poder determinar la solución.
• Ejemplos:
– Obtener el máximo o el mínimo de un conjunto de números, obtener la suma
o el producto de todos los números de un conjunto dado, obtener la media,
etc.
• Se llevan a cabo mediante variables enteras que se usan como índices
para acceder a sus distintas posiciones.
• Se debe llevar el control de qué posiciones ya se han visitado y cuántas
se deben visitar para poder solucionar el problema.
25/11/2011 IIP - Curso 2011/12 19
20. Recorrido ascendente de un array
• Recorrido iterativo ascendente con un bucle while:
• Recorrido iterativo ascendente con un bucle for:
• El método avanzar representa el incremento del índice.
25/11/2011 IIP - Curso 2011/12 20
int i=inicio;
while (i<=fin) {
tratar(a[i]); // Operaciones con elemento i-ésimo
avanzar(i);
}
for (int i=inicio; i<=fin; avanzar(i)) {
tratar(a[i]); // Operaciones con elemento i-ésimo
}
21. Recorrido descendente de un array
• Recorrido iterativo descendente con un bucle while:
• Recorrido iterativo descendente con un bucle for:
• El método retroceder representa el decremento del índice.
25/11/2011 IIP - Curso 2011/12 21
int i=fin;
while (i>=inicio) {
tratar(a[i]); // Operaciones con elemento i-ésimo
retroceder(i);
}
for (int i=fin; i>=inicio; retroceder(i)) {
tratar(a[i]); // Operaciones con elemento i-ésimo
}
22. Problemas de recorrido en arrays
• Ejemplo de recorrido iterativo ascendente: método que suma
todos los elementos de un array de enteros.
25/11/2011 IIP - Curso 2011/12 22
Y si queremos calcular
la media de los
elementos del array?
static double mediaIteAsc(int[] v) {
double suma=0;
for (int i=0; i<v.length; i++)
suma = suma + v[i];
return suma/v.length;
}
0 1 2 3 4 5
v
v.length = 6
static int sumaIteAsc(int[] v) {
int suma=0;
for (int i=0; i<v.length; i++)
suma = suma + v[i];
return suma;
}
23. Problemas de recorrido en arrays
• Ejemplo de procesado de parte de un array: método que calcula la
media aritmética del subarray a[izq … der]
• El número de elementos entre izq y der (izq<=der) es: der-izq+1
25/11/2011 IIP - Curso 2011/12 23
public static double media(int[] a, int izq, int der){
double suma = 0;
for (int i=izq; i<=der; i++) suma+=a[i];
return suma/(der-izq+1);
}
0 1 2 3 4 5
v
6
Hay 4 elementos en v[2…5]
(5-2+1)
24. Problemas de recorrido en arrays
• Ejemplo de recorrido iterativo descendente: método que suma
todos los elementos de un array de enteros.
• El bucle se detiene cuando i < 0, es decir, tras procesar la
componente 0 del array, cuando i vale -1.
25/11/2011 IIP - Curso 2011/12 24
0 1 2 3 4 5
v v.length = 6
public static int sumaIteDesc(int[] v) {
int suma=0;
for (int i=v.length-1; i>=0; i--)
suma = suma + v[i];
return suma;
}
25. Problemas de recorrido en arrays
• Ejemplo de recorrido iterativo ascendente: Calcula la posición del
máximo en el array a.
• Fíjate que el recorrido se inicia en 1, ya que la posición 0 ya ha
sido tratada.
• Recuerda que los tipos primitivos se comparan con ==,>,>=,<,<=
mientras que los tipos objeto se comparan con los métodos
equals y/o compareTo.
25/11/2011 IIP - Curso 2011/12 25
public static int maximo(String[] a) {
int posMax = 0;
for (int i=1; i<a.length; i++)
if (a[i].compareTo(a[posMax])>0) posMax = i;
return posMax;
}
26. Problemas de recorrido en arrays
• Ejemplo de recorrido iterativo descendente: Calcula la posición
del máximo en el array a.
• El recorrido se inicia en a.length-2, ya que la posición
a.length-1 ya ha sido tratada.
25/11/2011 IIP - Curso 2011/12 26
public static int maximo(double[] a) {
int posMax = a.length-1;
for (int i=a.length-2; i>=0; i--)
if (a[i]>a[posMax]) posMax = i;
return posMax;
}
27. Esquemas de búsqueda en arrays
• Una búsqueda requiere determinar si existe algún elemento del
array que cumpla una cierta propiedad.
• Este tipo de problemas implican operaciones que pueden
obtener la solución sin necesidad de conocer todos los datos:
localizar el primero que cumpla cierto requisito, tratar todos los
datos hasta que se cumpla cierta condición, etc.
– Las búsquedas en arrays requieren el uso de variables de tipo int para
acceder a sus distintas posiciones, de forma similar a los recorridos, y con
variables de tipo boolean para comprobar la condición de terminación.
– Debemos llevar el control de que posiciones ya se han visitado y cuantas
se deben visitar para poder solucionar el problema.
25/11/2011 IIP - Curso 2011/12 27
28. Problemas de búsqueda en arrays
• Se establecen dos estrategias principales a la hora de buscar:
– Búsqueda lineal: se va reduciendo la cantidad de información
sobre la que buscar elemento a elemento. Se puede aplicar
siempre independientemente de si los datos están ordenados
o no en el array.
– Búsqueda binaria o dicotómica: se va reduciendo la cantidad
de información sobre la que buscar, eliminando cada vez la
mitad de elementos. Esta estrategia necesita que los datos
dentro del array estén ordenados de una forma conocida (por
ejemplo, de menor a mayor), pero es más eficiente que las
búsquedas lineales.
25/11/2011 IIP - Curso 2011/12 28
29. Búsqueda ascendente en un array
• Estructura de búsqueda ascendente utilizando una variable
lógica: ¿Existe algún elemento a[i] que cumpla la propiedad?
25/11/2011 IIP - Curso 2011/12 29
int i=inicio, j=fin;
boolean encontrado=false;
while (i<=j && !encontrado) {
if (propiedad(a[i])) encontrado=true;
else avanzar(i);
}
// Resolver la búsqueda
if (encontrado) ... // a[i] cumple la propiedad
else ... // ningún elemento cumple la propiedad
30. Búsqueda descendente en un array
• Estructura de búsqueda descendente utilizando una variable
lógica: ¿Existe algún elemento a[i] que cumpla la propiedad?
25/11/2011 IIP - Curso 2011/12 30
int i=inicio, j=fin;
boolean encontrado=false;
while (j>=i && !encontrado) {
if (propiedad(a[j])) encontrado=true;
else retroceder(j);
}
// Resolver la búsqueda
if (encontrado) ... // a[j] cumple la propiedad
else ... // ningún elemento cumple la propiedad
31. Estrategias de búsqueda en arrays
• Estructura de búsqueda ascendente. Solución con salida del
bucle, acabando el método en ejecución.
25/11/2011 IIP - Curso 2011/12 31
int i=inicio, j=fin;
while (i<=j) {
if (propiedad(a[i])) return i; //Búsqueda con éxito
avanzar(i);
}
// i>j y ningún elemento cumple la propiedad
return -1;
32. Estrategias de búsqueda en arrays
• Estructura de búsqueda ascendente con garantía de éxito: se
sabe de antemano que existe algún elemento a[i] que cumple
la propiedad.
• Es posible incluir deliberadamente un elemento que cumpla la
propiedad. Dicho elemento se denomina centinela. En ese caso,
la búsqueda se llama búsqueda con centinela.
25/11/2011 IIP - Curso 2011/12 32
int i=inicio;
while (!propiedad(a[i]))
avanzar(i);
// Resolver la búsqueda: Se sabe que en i
// hay un elemento que cumple la propiedad
33. Estrategias de búsqueda en arrays
• Estructura de búsqueda lineal iterativa (sin garantía de éxito) con
guarda que evalúa la propiedad. ¿Algún elemento a[i] cumple
la propiedad?
25/11/2011 IIP - Curso 2011/12 33
int i=inicio, j=fin;
While (i<=j && !propiedad(a[i]))
avanzar(i);
// El bucle acaba porque:
// i <= fin a[i] cumple la propiedad o
// i vale fin+1
// Resolver la búsqueda
if (i<=fin) ... // se cumple propiedad(a[i])
else ... // no hay ningún elemento a[i]
// que cumpla propiedad(a[i])
34. Problemas de búsqueda sobre arrays
• Búsqueda ascendente de un elemento en un array de String sin
garantía de éxito. Si no lo encuentra, devuelve -1.
25/11/2011 IIP - Curso 2011/12 34
public static int buscarPos(String[] a, String dato) {
int i = 0;
while (i<a.length && !a[i].equals(dato)) i++;
if (i<a.length) return i;
else return -1; // o bien directamente: return -1;
}
• Búsqueda descendente de un elemento en un array de double
sin garantía de éxito. Si no lo encuentra, devuelve -1.
public static int buscarPos(double[] a, double dato) {
int i = a.length-1;
while (i>=0 && a[i]!=dato) i--;
return i;
}
35. Problemas de búsqueda sobre arrays
• Búsqueda ascendente de un elemento en un array de String
con garantía de éxito.
25/11/2011 IIP - Curso 2011/12 35
public static int buscarPosEsta(String[] a, String dato) {
int i = 0;
while (!a[i].equals(dato)) i++;
return i;
}
• Búsqueda descendente de un elemento en un array de double
con garantía de éxito.
public static int buscarPosEsta(double[] a, double dato) {
int i = a.length-1;
while (a[i]!=dato) i--;
return i;
}
36. Problemas de búsqueda sobre arrays
• Comprueba si hay algún elemento del array mayor que dato.
• Devuelve, si existe, la posición del primer elemento del array
mayor que la suma de los anteriores. Si no, devuelve -1.
25/11/2011 IIP - Curso 2011/12 36
public static boolean estaMayor(double[] a, double dato) {
int i = 0;
while (i<a.length && a[i]<=dato) i++;
return (i<a.length);
}
public static int buscaPosMaySuma(int[] a, int dato) {
int i = 0, suma = 0;
while (i<a.length && a[i]<=suma) { suma+=a[i]; i++; }
if (i<a.length) return i;
else return -1;
}
37. Esquemas combinados de búsqueda y
recorrido sobre arrays
• Hay problemas que requieren combinar ambas estrategias. Ej.:
– Dado un array de String, determinar para cada String del array la
primera repetición. El resultado debe ser un String en el que en cada
línea conste el dato y las dos posiciones en las que aparece.
25/11/2011 IIP - Curso 2011/12 37
public static String listaDuplicados(String[] a) {
String res = "";
for (int i=0; i<a.length; i++) {
int j = i+1;
while (j<a.length && !a[i].equals(a[j])) j++;
if (j<a.length)
res+=a[i] + " duplicado en: " + i + " y " + j + "n";
}
return res;
}
38. Representación de una secuencia de
datos dinámica usando un array (I)
• Un array permite la representación sencilla de una lista de datos en la
que se puede añadir y eliminar elementos.
• Elementos en posiciones consecutivas del array: [0,numElem-1]
– Primera posición libre en numElem
• Se construye un array de tamaño igual al número máximo de
elementos a almacenar.
tipoBase[] lista = new tipoBase[MAX_ELEM];
int numElem = 0;
25/11/2011 IIP - Curso 2011/12 38
lista 0 11
elementos de la lista
numElem = 7
6
posiciones vacías
39. Representación de una secuencia de
datos dinámica usando un array (II)
• Para añadir un nuevo elemento a la lista:
• Borrar un elemento de la lista debe preservar la contigüidad de
los elementos y su orden de inserción.
– Desplazar los elementos posteriores una posición a la
izquierda.
25/11/2011 IIP - Curso 2011/12 39
int i = 0;
while (i<numElem && lista[i] distinto de x) i++;
if (i<numElem) {
for (int j=i+1; j<numElem; j++)
lista[j-1] = lista[j];
numElem--;
}
else // búsqueda sin éxito
if (numElem<MAX_ELEM) lista[numElem++] = x;
else // tratar el caso de lista llena
40. Arrays multidimensionales:
Justificación
• Ejemplo de aplicación:
– Medidas de temperatura en una zona para todos los días de un año.
• Soluciones posibles:
– Array temp de 366 elementos (por si el año es bisiesto) que almacena de
forma correlativa los datos de temperatura para cada día.
• 1 de Enero temp[0] 3 de Febrero temp[33] 2 de Julio temp[183]
– Representación matricial de dimensiones 12x31
• Simplifica los cálculos de la posición real de cada día en la estructura de datos.
25/11/2011 IIP - Curso 2011/12 40
… …
…
…0
11
12filas
31 columnas
0 30
Esta representación
desperdicia memoria
41. Arrays multidimensionales:
Justificación (II)
– Representación mediante array multidimensional con 12 filas y tamaño
variable de columnas:
• Siempre es conveniente ajustar el tamaño del array a los datos
que se vayan a almacenar para reducir el consumo de memoria.
– Se trata de un array de 12 componentes donde cada componente es a su
vez un array con un nº variable de componentes. Esto es un ejemplo de
array multidimensional (array de arrays).
25/11/2011 IIP - Curso 2011/12 41
… …
…
…0
11
12filas
0 3029
Enero tiene 31 días
Febrero puede tener 28 ó 29 días
Marzo puede tener 31 días
Diciembre puede tener 31 días
Esta representación
reduce el consumo
de memoria
nº variable de columnas
42. Arrays multidimensionales: Definición
• Definición: Un array multidimensional es un array cuyas
componentes son a su vez arrays.
• La dimensión de un array es el número de definiciones anidadas
que incluye.
• Cada anidamiento es un array de una dimensión menor.
• La dimensión define el número de índices que se utilizarán para
acceder a los elementos primitivos del array.
25/11/2011 IIP - Curso 2011/12 42
43. Arrays multidimensionales
Declaración y uso
• Valores: Se representan como una sucesión de elementos entre llaves y
separados por comas. Por ejemplo: {{1,2},{1,2,3},{1}} es un array
bidimensional de enteros con tres arrays unidimensionales.
• Operador: El operador de acceso [] debe repetirse para cada dimensión.
nomVble[índice1][índice2]…[índiceN]
índicek es una expresión que se evalúa a un índice válido para el array
nomVble en la dimensión k
• Declaración y creación:
– Declaración: deben de aparecer tantos pares de corchetes como la dimensión del
array. tipo[]…[] nomVble;
– Inicialización: deben de aparecer tantos pares de corchetes como la dimensión
del array y, al menos, la primera dimensión debe de tener un tamaño específico.
Las demás dimensiones pueden estar vacías.
nomVble = new tipo[expresión1]…[expresiónN];
̶ Conjuntamente:
tipo[]…[] nomVble = new tipo[expresión1]…[expresiónN];
25/11/2011 IIP - Curso 2011/12 43
44. int[][] v;
v = new int[5][];
v[0] = new int[3];
v[1] = new int[2];
v[3] = new int[3];
v[4] = new int[1];
v[0][1] = 10;
v[4][0] = 3;
Errores:
v[2] = -3; //Error de compilación
v[4][1] = -3; // Error en ejecución
// ArrayIndexOutOfBoundsException
Arrays bidimensionales
25/11/2011 IIP - Curso 2011/12 44
10
(null)
3
0
1
2
3
4
v
0 1 2
v[3]
v[3][1]
v[v.length-1]
0
v[v.length-1][v[v.length-1].length-1] v[3][v[3].length-1]
v[0]
v[0][1]
0 1 2
v[0][2]
45. • Las matrices son un caso particular de arrays bidimensionales
donde todos los arrays de la segunda dimensión tienen el mismo
tamaño.
• Se pueden definir con una única instrucción new.
• Ejemplo: matriz con dos filas y tres columnas:
double[][] matriz = new double[2][3];
• Otra forma:
double[][] matriz = new double[2][];
matriz[0] = new double[3];
matriz[1] = new double[3];
Arrays bidimensionales: Matrices
25/11/2011 IIP - Curso 2011/12 45
0
1
matriz
0 1 2
0 1 2
for(int i=0; i<matriz.length; i++)
for(int j=0; j<matriz[i].length; j++)
matriz[i][j] = teclado.nextDouble();
46. Arrays Multidimensionales
Ejemplo: Temperatura (I)
• Declaración de una matriz de 12x31 para almacenar las medidas
diarias de temperatura para cada mes.
• Declaración de un array multidimensional de 12 filas y nº variable
de columnas.
25/11/2011 IIP - Curso 2011/12 46
double[][] tempMed = new double[12][31];
tempMed[3][6] = 50.1; // Temp. del día 7 de Abril
double[][] tempMed = new double[12][];
// tempMed.length es igual a 12
tempMed[0] = new double[31]; // Índices del 0 al 30
tempMed[1] = new double[29]; // Índices del 0 al 28
// …
tempMed[2][4] = 78.0; // Temp. del día 5 de Marzo
47. Arrays Multidimensionales
Ejemplo: Temperatura (II)
• Alternativa de implementación con definición previa del nº de días.
• tempMed[i][j] representa la temperatura media del día (j+1) del
mes (i+1)
– tempMed[3][14] es la temperatura media del 15 de Abril
25/11/2011 IIP - Curso 2011/12 47
final int[] NUM_DIAS = {31,28,31,30,31,30,31,31,30,31,30,31}
// NUM_DIAS[i] = nº días del mes, 0<=i<=11
double[][] tempMed = new double[12][];
// tempMed[i] representa el mes, 0<=i<=11
for (int i=0; i<tempMed.length; i++)
tempMed[i] = new double[NUM_DIAS[i]];
// el nº elementos de tempMed[i] = NUM_DIAS[i], 0<=i<=11
48. Arrays Multidimensionales
Ejemplo: Temperatura (III)
• Alternativa de implementación usando numeración desde 1.
• Ahora, tempMed[i][j] representa la temperatura media del día j del
mes i.
– tempMed[4][15] es la temperatura media del 15 de Abril.
25/11/2011 IIP - Curso 2011/12 48
final int[] NUM_DIAS = {0,31,28,31,30,31,30,31,31,30,31,30,31};
// NUM_DIAS[0] = 0 y NUM_DIAS[i] = nº días del mes i, 1<=i<=12
double[][] tempMed = new double[13][];
// tempMed[0] = null y tempMed[i] representa el mes i, 1<=i<=12
for (int i=1; i<tempMed.length; i++)
tempMed[i] = new double[NUM_DIAS[i]+1];
// el nº elementos de tempMed[i] = NUM_DIAS[i]+1, 1<=i<=12
49. Arrays de dimensión N
• Para dimensiones mayores que dos se siguen las mismas reglas.
Por ejemplo:
• Tres dimensiones:
• Cuatro dimensiones:
De forma equivalente:
25/11/2011 IIP - Curso 2011/12 49
int[][][] tres = {{{1}},{{1,2},{3,4}},{{1},{2}}};
int[][] dos = {{5,4},{6,7}};
tres[1] = dos;
tres[1][0][1] = 6;
int[][][][] cuatro = new int[10][2][][];
for(int i=0; i<cuatro.length; i++)
for(int j=0; j<cuatro[i].length; j++)
cuatro[i][j] = new int[3][3];
int[][][][] cuatro = new int[10][2][3][3];
50. Recorrido de arrays
multidimensionales
• Suma de dos matrices de double de dimensión NxM
• Se asume que m1 y m2 están inicializadas y ambas tienen
dimensiones NxM
25/11/2011 IIP - Curso 2011/12 50
public static double[][] sumaM(double[][] m1, double[][] m2) {
double[][] res= new double[m1.length][m1[0].length];
for (int i=0; i<m1.length; i++)
for (int j=0; j<m1[i].length; j++)
res[i][j]= m1[i][j] + m2[i][j];
return res;
}
+ =
51. Recorrido de arrays
multidimensionales
• Producto matriz por vector:
• El nº de columnas de la matriz debe coincidir con el tamaño del
vector.
25/11/2011 IIP - Curso 2011/12 51
public static double[] matPorVec(double[][] m, double[] v) {
double[] res = new double[m.length];
for (int i=0; i<m.length; i++)
for (int j=0; j<v.length; j++)
res[i] += m[i][j] * v[j];
return res;
}
m v
* =
res
52. Búsqueda en array multidimensional
• En el ejemplo de las temperaturas, búsqueda de la fecha en la
que se registraron 40º.
25/11/2011 IIP - Curso 2011/12 52
public static void main(String[] args) {
final int[] NUM_DIAS = {0,31,28,31,30,31,30,31,31,30,31,30,31};
double[][] tempMed = new double[13][];
for (int i=1; i<tempMed.length; i++)
tempMed[i] = new double[NUM_DIAS[i]+1];
.....
int i = 1, j = 1; boolean encontrado = false;
while (i<tempMed.length && !encontrado) {
while (j<tempMed[i].length && !encontrado) {
encontrado = (tempMed[i][j]==40);
j++;
}
i++;
}
if (encontrado) {
System.out.print("40º medido el día " + (j-1));
System.out.println(" del mes " + (i-1));
}
else System.out.println("Ningún día con 40º");
}
53. Más problemas de acceso directo
25/11/2011 IIP - Curso 2011/12 53
• El array permite el acceso en tiempo constante a cualquier
componente, conocida su posición.
– Dado el array a[0..1000], a[0] tiene el mismo coste temporal (teórico)
que a[999].
• Esto permite implementar algunos algoritmos de forma muy
eficiente. Ejemplos:
• Búsqueda binaria o dicotómica
– Permite la búsqueda eficiente sobre un array ordenado.
• Representación de un conjunto de naturales
• Cálculo de la moda de un conjunto de naturales
• El miembro del conjunto que más veces se repite.
54. Búsqueda binaria: estrategia
• Aplicable únicamente a arrays ordenados (ascendentemente en
este caso).
• Estrategia: Buscar el elemento 12
25/11/2011 IIP - Curso 2011/12 54
2 4 5 7 9
0 1 2 3 4
12
5
a zona de búsqueda15
6
2 4 5 7 9 12a 15
2 4 5 7 9 12a 15
Calcular el elemento central y
decidir proseguir la búsqueda
por una mitad u otra del array
La búsqueda ha finalizado con éxito
4 6
5
55. Búsqueda binaria: implementación
• Implementación de búsqueda binaria: Encontrar x en el array
ordenado ascendentemente: a[inicio…fin].
25/11/2011 IIP - Curso 2011/12 55
public static int busBinaria(int[] a, int inicio, int fin,
int x){
int izq = inicio, der = fin, mitad = 0;
boolean encontrado = false;
while (izq<=der && !encontrado) {
mitad = (izq+der)/2;
if (x==a[mitad]) encontrado = true;
else if (x<a[mitad]) der = mitad-1;
else izq = mitad+1;
}
if (encontrado) return mitad;
else return -1;
}
57. Representación de un conjunto de
naturales (I)
• Representación de un conjunto de números naturales en el
intervalo [0..n] mediante un array conjunto de boolean donde:
– conjunto[i]=true si i pertenece al conjunto (false en caso contrario)
25/11/2011 IIP - Curso 2011/12 57
true true true false true
conjunto
public class Conjunto {
private boolean[] conjunto;
private int ultimo;
public Conjunto(int ult) {
conjunto = new boolean[ult+1]; ultimo = ult;
}
/** 0<=x<=ultimo */
public boolean pertenece(int x) { return conjunto[x]; }
58. Representación de un conjunto de
naturales (II)
• Esta representación permite conocer de forma muy rápida
(tiempo independiente del número de elementos) si un natural
pertenece o no al conjunto.
25/11/2011 IIP - Curso 2011/12 58
public int cardinal() {
int card = 0;
for (int i=0; i<conjunto.length; i++)
if (conjunto[i]) card++;
return card;
}
/** 0<=x<=ultimo */
public void añade(int x) { conjunto[x] = true; }
public void setAlAzar() {
for (int i=0; i<conjunto.length; i++)
conjunto[i] = (Math.random()>=0.5);
}
...
}
59. Moda de un conjunto de naturales
• La moda de un conjunto es el elemento del mismo que más veces
aparece.
• Estrategia en dos fases:
– Fase 1: Recorrido secuencial ascendente y array auxiliar de contadores
(frecuencia) donde frecuencia[i]: nº de veces que aparece i en el
array.
– Fase 2: La moda se obtiene calculando el máximo del array frecuencia.
• Ejemplo para C={5,7,1,7,8,7,3,0,7,8,5,0} con n = 8 (numero más grande)
25/11/2011 IIP - Curso 2011/12 59
a
5 7 1 7 8
0
7 3
11
0 7 8 5 0
frecuencia
2 1 0 1 0
0
2 0 2
1 2 3 4 5 6 7 8
4
El tamaño de este array
se corresponde con el
número natural más
grande a representar
60. Moda de un conjunto de naturales
• Calcula la moda de un array que contiene elementos enteros en el rango [0..n]
25/11/2011 IIP - Curso 2011/12 60
public static int modaDe0aN(int[] a, int n) {
// se construye un array entre 0 y n
int[] frecuencia = new int[n+1];
// recorrido de a y obtención de frecuencias
for (int i=0; i<a.length; i++) frecuencia[a[i]]++;
// la moda es el máximo del array frecuencia
int moda = 0;
for (int i=1; i<frecuencia.length; i++)
if (frecuencia[i]>frecuencia[moda]) moda = i;
return moda;
}