...el poder de lo simple...
Marzo.4.2010
Arreglos
de objetos
Piénsese
en el
siguiente problema:
Un
usuario desea que nosotros le mostremos en orden
inverso sus dos datos entrados.
La solución es trivial puesto que será suficiente con recibir los dos
datos cada uno en un objeto variable y después de conocidos estos
mostrarlos emitiendo primero el segundo entrado:
Tarea:
{
los objetos primero, segundo son cantidades
entre primero, segundo
muestre segundo, primero
}
Y…¿qué se haría si no fueran dos datos sino 5 ?
Haríamos algo parecido: reservamos espacio para 5 objetos variables en
la RAM, luego pedimos los cinco datos por teclado y los recibimos en
las cinco variables y una vez conocidos los emitimos empezando por el
último recibido:
Tarea:
{
los objetos primero, segundo, tercero, cuarto, quinto son cantidades
entre primero, segundo, tercero, cuarto, quinto
muestre quinto, cuarto, tercero, segundo, primero
}
Y…¿Si no fueran 5 datos sino 150 ?
Pues haríamos algo parecido pero esta vez utilizando 150 variables
diferentes.
Nótese que si al momento de diseñar el algoritmo ya conocemos el número
de datos bastará con separar tantos objetos variables como sea
necesario y después de entrados proceder a mostrarlos en orden inverso,
así sea un tanto engorroso cuando la cantidad de ellos sea grande.
Ahora generalicemos el problema:
El usuario desea que le resolvamos el problema anterior pero ésta vez
no para dos, ni para cinco, ni para 150, ni para un número ya conocido
sino para una cantidad desconocida de ellos en el momento de diseñar el
algoritmo:
El usuario desea que nosotros le mostremos en orden
inverso sus datos
entrados.
La pregunta que surge inmediatamente es ¿En éste caso cuantos objetos
variables reservamos en la RAM ?
Estamos metidos en un lío: primero que todo no conocemos tal cantidad
en éste momento y sin embargo debemos programar el algoritmo ya y para
hacerlo debemos definir
todas las variables para conservar todos los datos sin
perder ninguno de ellos hasta que llegue el último !
Un apoyo para resolver tal situación es utilizar un arreglo. Sus
características principales son:
La reserva de espacio
en la RAM para todos los objetos previstos del grupo se hace en una
sola petición.
Todos los objetos
quedan ubicados en forma adyacente dentro de un solo bloque de memoria .
Todos los objetos se
identifican por con un solo nombre.
Todos los objetos son
del mismo tipo o clase.
A cada objeto se le
puede discriminar por la posición que ocupa dentro del grupo.
La posición es un
ordinal o cantidad a la que se llama índice y puede
describirse en cualquiera de las tres formas usuales: como una constante de
cantidad, como una variable
para cantidades o como una expresión
aritmética (que al evaluarse produce una cantidad).
Una
convención generalizada en muchos lenguajes de programación es asumir
que la primera posición se valora con 0, la segunda con 1 y así
sucesivamente. En consecuencia cuando se discrimine un objeto dentro
del grupo pueden utilizarse valores para el índice en el rango válido:
entre 0 y la cantidad
reservada menos uno.
Si se intenta acceder un elemento del arreglo con un índice por fuera
del rango ocurrirá un error de lógica o una excepción y suspensión de
la ejecución del programa.
Se pedirá
al usuario el tamaño del grupo N
y con él se crean o reservan espacios en memoria para el grupo con una
sola petición (por lo tanto será un arreglo estático):
el
objeto N es una cantidad
entre N
los
objetos Grupo[N] son cantidades
Características de los
arreglos:
Todos los elementos del grupo tienen el mismo nombre.
Todos los elementos del grupo son semejantes, de la misma clase.
Están dispuestos contiguamente: físicamente vecinos en la RAM.
Se les discrimina por la posición relativa que ocupan respecto al
primero del grupo.
La posición relativa es una cantidad entera. A su valor se le denomina
índice.
Un índice es expresable en las tres modalidades usuales: una constante,
una variable o una expresión aritmética.
Convencionalmente en muchos lenguajes de programación el índice o
posición relativa que ocupa el primer elemento es el 0.
El operador de manejo indizador [
] permite señalar o discriminar un elemento dentro del grupo:
Grupo[0] hace referencia
al primer elemento del grupo
Grupo[1] hace referencia
al segundo elemento
Grupo[2] ...al tercero
....
Grupo[N-1] hace referencia
al último elemento del grupo.
Nótese que si han separado N espacios o elementos los índices válidos
estarán en el rango 0.....N-1. Si se viola tal
convención obtendrá una excepción y cancelación de la ejecución del
programa.
Veamos el problema pendiente de resolver. Se reserva espacio para un
grupo de tamaño dicho por el usuario final, luego se le piden uno a uno
los datos y se conservan en posiciones adyacentes dentro del arreglo,
finalmente se recorren las posiciones en orden inverso dentro del
arreglo y se va mostrando su contenido. Nótese también que un índice en
forma de una variable o una expresión,
por ejemplo contador,
proporciona mucha flexibilidad en el manejo del grupo de elementos.:
tarea
{
los
objetos N, contador son cantidades
entre N
los
objetos Grupo[N] son cantidades
copie 0
en contador
mientras
contador
< N haga:
{
entre Grupo[contador]
copie contador
+ 1 en contador
}
mientras
contador
> 0 haga
{
copie contador
- 1 en contador
muestre Grupo[contador]
}
}
Ejemplo:
Una los dos puntos más alejados
tarea
{
el objeto v es una Form
el objeto bm es un bitmap (1024,768)
el objeto g es una graphics no_crear
copie Graphics.FromImage(doy bm) en g
el objeto lápiz es un pen (doy Color.Blue , doy 3)
copie "Traslado de puntos" en v.Text
v.Show
los objetos n, i, j, x1, y1, x2, y2, d, dmay son cantidades
entre n
los objetos x[n], y[n] son cantidades
copie 0 en i
mientras i<n haga
{
entre x[i], y[i]
copie i + 1 en i
}
copie 0 en i, dmay
mientras i < n haga
{
copie i + 1 en j
mientras j<n haga
{
copie ( (x[j] - x[i])^2 + (y[j] - y[i])^2 )^(1/2) en d
es d > dmay ?
si:{
copie d en dmay
copie x[i] en x1
copie y[i] en y1
copie x[j] en x2
copie y[j] en y2
}
copie j + 1 en j
}
copie i + 1 en i
}
g.Clear(doy Color.Black)
copie 0 en i
mientras i<n haga
{
g.DrawEllipse(doy lápiz, doy x[i], doy y[i], doy 1, doy 1)
copie i + 1 en i
}
g.DrawLine(doy lápiz, doy x1, doy y1, doy x2, doy y2)
copie bm en v.BackgroundImage
muestre "Esperando para terminar"
}
Ejemplo:
Mover paulatinamente los puntos del usuario hacia un punto común:
tarea
{
el objeto v es una Form
el objeto bm es un bitmap (1024,768)
el objeto g es una graphics no_crear
copie Graphics.FromImage(doy bm) en g
el objeto lápiz es un pen (doy Color.Blue , doy 3)
copie "Traslado de puntos" en v.Text
v.Show
los objetos n, c, npasos, p, xdestino, ydestino son cantidades
entre n, npasos, xdestino, ydestino
los objetos x[n], y[n], dx[n], dy[n] son cantidades
copie 0 en c
mientras c<n haga
{
entre x[c], y[c]
copie (xdestino - x[c])/npasos en dx[c]
copie (ydestino - y[c])/npasos en dy[c]
copie c + 1 en c
}
copie 0 en p
mientras p < npasos haga
{
copie p + 1 en p
g.Clear(doy Color.Black)
copie 0 en c
mientras c<n haga
{
copie x[c] + dx[c] en x[c]
copie y[c] + dy[c] en y[c]
copie c + 1 en c
g.DrawEllipse(doy lápiz, doy x[c], doy y[c], doy
1, doy 1)
v.Refresh
}
copie bm en v.BackgroundImage
muestre "paso ", p
}
muestre "Esperando para terminar"
}
Dimensiones
Los elementos dentro de los arreglos pueden disponerse de muchas forma
llamadas dimensiones. Cada dimensión permite categorizar por criterio
diferente. Cada dimensión se maneja con un índice. En los
ejemplos
anteriores se utilizó un solo índice por lo que se le llama arreglo de
una dimensión y algunos más atrevidos le llaman vector.
Cuando se usan dos índices se le llama de dos dimensiones o
bidimensional o matriz por la asociación con el concepto matemático. La
forma de reservar espacio en la memoria para ellos es:
los objetos Mat[20, 10] son
cantidades
y significa que reservará 200 elementos dispuestos en una estructura
organizativa de 20 horizontales o filas cada una de ellas con 10
elementos. O lo que es equivalente: la organización consta de 10
verticales o columnas y en cada una de ellas hay 20 elementos.
Cuando se usan tres índices se le llama de tres dimensiones o
tridimensional:
los objetos Trid[12, 5, 6] son cantidades
reserva
360 espacio para elementos conformando el arreglo Trid de 12
horizontales, cada una con 5 columnas de profundidad 6.
Ejemplo:
Producto de dos matrices
tarea
{
los objetos i, j, k, NF, NC, NCS, suma son cantidades
entre NF, NC, NCS
los objetos A[NF, NC], B[NC, NCS], C[NF, NCS] son cantidades
variando i desde 0 hasta NF-1 haga
variando j Desde 0 hasta NC-1 haga
entre A[i, j]
variando i desde 0 hasta NC-1 haga
variando j Desde 0 hasta NCS-1 haga
entre B[i, j]
variando i desde 0 hasta NF-1 haga
variando j Desde 0 hasta NCS-1 haga
{
copie 0 en suma
variando k desde 0 hasta NC-1 haga
copie suma + A[i,
k]*B[k, j] en suma
copie suma en C[i, j]
}
variando i desde 0 hasta NF-1 haga
variando j Desde 0 hasta NCS-1 haga
muestre C[i, j]
}