You are on page 1of 51

ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 1

TEMA 1.

Introduccin a la programacin.

1.1. CONCEPTOS BSICOS.


Un programa es un conjunto ordenado de instrucciones, que se aloja en la memoria
del ordenador. Estas instrucciones operan sobre datos, normalmente (aunque no
necesariamente) procedentes del mundo exterior a dicha memoria: usuarios, dispositivos de
almacenamiento (electrnicos, magnticos, pticos, etc), redes de comunicaciones, etc, para
producir resultados tanto en forma de acciones como de nuevos datos (informacin).
Acciones
ORDENADOR Resultados
Datos
(memoria)
PROGRAMA
Informacin

Figura 1.1. Esquema de funcionamiento de un programa.


Adoptamos la definicin de Wirth (1985) para programa como conjunto de
algoritmo ms estructuras de datos.

La estricta materializacin del esquema anterior implicara que el programa debera


estar escrito utilizando un lenguaje binario (de mquina): tanto el algoritmo (haciendo
referencia al repertorio de instrucciones -instruction set- del ordenador, concretamente de
su CPU) como los datos (adecuadamente codificados).

Salvo en una efmera temporada, coincidente con la aparicin de los primeros


ordenadores (1944), apenas se ha utilizado esta modalidad de programacin como
2 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

consecuencia de su extrema dificultad y escasa productividad para el desarrollo de


software1.

La alternativa por la que se opt fue escribir programas en un lenguaje de ms alto


nivel (lenguaje de programacin2). Uno de estos lenguajes, de gran popularidad
actualmente, es el Java.

La programacin consiste en la actividad de escribir programas utilizando para ello


lenguajes de programacin adecuados.

Para que un programa escrito (codificado) en un lenguaje de programacin


(programa fuente) pueda ejecutarse en un ordenador es necesario traducirlo a su lenguaje
(de mquina). Para ello hay que utilizar los programas adecuados, denominados
genricamente traductores.

La figura siguiente muestra un esquema de funcionamiento3:

Programa Ordenador Programa


fuente TRADUCTOR ejecutable

Figura 1.2. Esquema de funcionamiento de un traductor.

La figura anterior se corresponde con una de las dos filosofas4 en la que se basan los
traductores: la compilacin. Mediante ella se genera un cdigo denominado objeto, que,
una vez cargado (load) en la memoria del ordenador, se puede ejecutar. La compilacin
solo se realiza una vez (siempre que no se hagan cambios en el programa). El resultado
(programa ejecutable) puede guardarse en un dispositivo de almacenamiento externo
(disco, CD, etc.) y desde l cargarse en memoria y ejecutarse en futuras ocasiones.

La otra alternativa, denominada interpretacin (que no genera cdigo objeto),


funciona de manera que el programa traductor traduce y ejecuta las lneas del cdigo fuente
de una en una.

El Java es un lenguaje mixto: primero se compila (por medio del compilador Javac,
produciendo ficheros con extensin .class), y a continuacin, ese cdigo se interpreta en el

1
Por el contrario, sera la tcnica ms eficiente (mayor velocidad de ejecucin y menor consumo de
memoria). No obstante, y como consecuencia de la incesante mejora y abaratamiento de la tecnologa, esta
alternativa no ha sido nunca tomada en consideracin.
2
Difcilmente se podr encontrar otra actividad ms viva que el desarrollo de lenguajes de programacin:
en tan solo cincuenta aos de existencia de los ordenadores y de la Informtica algunos autores llegan a
identificar en torno a medio millar de ellos. Se puede encontrar una referencia en:
http://www.lenguajesdeprogramacion.com/
3
Se trata de un modelo muy elemental. La realidad es algo ms compleja.
4
Existen otras soluciones intermedias.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 3

ordenador en el que se va a ejecutar el cdigo (por medio de la JVM, Java Virtual


Machine).

1.1.1. Caractersticas especficas del lenguaje Java.

1.1.1.1. Clases y objetos.

Una clase es una agrupacin de variables miembro (o campos) y mtodos miembro


que operan sobre dichos datos y permiten comunicarse con otras clases: una clase puede ser
equivalente a un tipo de datos creado por el usuario junto las operaciones que se pueden
realizar sobre dicho tipo de datos. Una variable de dicho tipo de datos es un objeto o
instancia de la clase.

A los campos de un objeto se les denomina variables miembros de objeto, y a todos


aquellos mtodos que se definen dentro de la clase se les denomina mtodos miembro.

Para lograr el encapsulamiento en Java, se utiliza un tipo especial de clase: el interfaz


(interface). Una interfaz es un conjunto de declaraciones de funciones. Si una clase
implementa (implements) una interfaz, debe definir todas las funciones especificadas por la
interfaz. Una clase puede implementar ms de una interfaz.

1.1.1.2. Mtodos.

Dentro de una clase en la que se define una estructura de datos, se pueden definir
mtodos de objeto, que se aplican a una variable de la clase poniendo el nombre de la
variable y luego el nombre del mtodo, separados por un punto.

Adems de definir mtodos de objeto, dentro de la clase se pueden crear mtodos con
el modificador static: son mtodos de clase, que se pueden utilizar aunque no se haya
creado ningn objeto de la clase (al contrario de lo que ocurre con los mtodos de objeto: si
se intentan invocar sin haber creado previamente el objeto se produce un error). Los
mtodos static se invocan desde fuera de la clase poniendo el nombre de la clase y luego el
nombre del mtodo, separados por un punto.

1.1.1.3. Modificadores.

Las variables miembro pueden ir precedidas en su declaracin por uno de los


modificadores de acceso: public, private, protected y package (este ltimo es el valor por
defecto y se puede omitir). A su vez las clases pueden ser public (accesibles desde
cualquier otra clase, siempre que el paquete est en un directorio accesible) o package (por
defecto, accesible solo para el resto de las clases del paquete).

El significado de los modificadores de acceso (para variables miembro y mtodos


miembro) es el siguiente:

o private: solo son accesibles dentro de la propia clase.


o package: tienen acceso todas las clases del resto del paquete.
4 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

o protected: tienen acceso las clases del resto del paquete, as como desde
subclases definidas fuera del paquete.
o public: se puede acceder desde cualquier otra clase.

1.1.1.4. Excepciones.

Las excepciones son elementos que almacenan informacin para detectar hechos
excepcionales, como por ejemplo errores. En Java existen muchos tipos de excepciones
estndar y las ms habituales son del tipo IOException (errores de lectura), as como del
tipo NumberFormatException (que se genera cuando se espera leer un nmero y se recibe
algo diferente).

1.1.2. Entorno de programacin (IDE).

Para realizar la actividad de programacin se requiere, adems del correspondiente


programa traductor (compilador o intrprete), un conjunto de herramientas (software
development tools) que proporcionan funcionalidades tales como escribir / modificar
(editar) el cdigo fuente, facilitar la puesta a punto de programas (debugger), cargar
(load), montar (link) y ejecutar (run) programas, gestionar ficheros con cdigo fuente y
ejecutable, etc. Normalmente estas herramientas se ofrecen en forma de paquete integrado
(Integrated Development Environment IDE-). Uno de ellos, de libre distribucin para
programacin en Java es Eclipse (http://www.eclipse.org, donde adems de descargar la
aplicacin, se pueden encontrar distintos recursos como por ejemplo tutoriales para
aprender el manejo del entorno).

Figura 1.3. Entorno de programacin Eclipse.


ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 5

1.2. SINTAXIS DEL LENGUAJE JAVA.


Java es un representante de la familia de los lenguajes orientados a objetos.

1.2.1. Estructura de un programa en Java.

A continuacin se muestra un incipiente programa en Java sobre el que se indican los


aspectos ms importantes.

Cdigo Explicacin
//Primer programa en Java Lnea de comentario.
public class hola_EUI Se indica el nombre del programa.
{ Delimitador de inicio del programa.
public static void main (String [ ] args) Clase principal
{ Delimitador de inicio de la clase
Ejemplo de accin: sentencia println (escribir en el dispositivo
de salida system.out y avanzar al comienzo de la lnea
System.out.println ("Hola EUI");
siguiente) que acta sobre un sujeto (dato): la cadena de
caracteres Hola EUI.
} Delimitador de fin de clase.
} Delimitador de fin de programa.

Tabla 1.1. Estructura bsica de un programa en Java.


La estructura general de un programa en Java es la siguiente5:

Sintaxis Semntica
import <nombre>; Llamada a una (o varias) componente(s) de la biblioteca.
public class <nombre de la clase general> Nombre de la clase general (obligatorio)
{ Principio de la clase.

<constantes y variables globales>


<mtodos6>
public static void main (String [ ] args) Declaracin del programa principal
{ Inicio del programa principal

<cuerpo del programa principal>


} Fin del programa principal.
} Fin de la clase.

Tabla 1.2. Estructura general de un programa en Java.


La sintaxis del lenguaje Java es de formato libre7. Para identificar sus partes se
utilizan delimitadores. El delimitador ms importante es el punto y coma (;), que se utiliza
como fin de instruccin. As mismo las llaves ({ }), se utilizan para indicar el inicio y final

5
Este esquema se ampliar en el punto de Programacin modular (1.3)
6
Devuelve/n uno o ningn (void) valor/es. En Java no existe la posibilidad de devolver varios valores.
7
La otra alternativa (utilizada por lenguajes tales como COBOL o FORTRAN) se basa en considerar lneas
de cdigo de una longitud determinada estructuradas en campos, cada uno de los cuales tiene un significado
predeterminado.
6 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

de bloques de instrucciones o del programa. Estos (u otros) delimitadores pueden tener un


significado particular en diferentes contextos.

Generalmente una aplicacin se desarrolla en varios ficheros, que se agrupan en


packages, que son libreras de clases. Cada uno de los ficheros que la componen debe tener
la extensin .java, y la aplicacin se ejecutar por medio de la clase que contenga la
funcin main.

1.2.2. Nomenclatura habitual en Java.

Los nombres en Java son sensibles a las maysculas y las minsculas (por ejemplo,
cadena sera una variable distinta de Cadena). Habitualmente en Java se escribe con
minsculas, con las siguientes excepciones:
o Cuando un nombre consta de varias palabras, se escriben seguidas, comenzando
en minsculas, excepto la primera letra de cada palabra a partir de la segunda (por
ejemplo presuntoDivisor, datoMayor, etc.).
o Los nombres de las clases e interfaces empiezan con mayscula (por ejemplo
Pila, Lista, Arbol).
o Los nombres de objetos, variables y mtodos empiezan por minscula (por
ejemplo buscarMayor, maximaDiferencia, etc.).
o Los nombres de las constantes (o variables finales) se escriben en maysculas
(por ejemplo PI).

1.2.3. Los datos.

Como ya se ha indicado, los datos son los sujetos del tratamiento. Los datos, en un
programa se pueden presentar en tres modalidades:
o En forma literal. Es decir, indicando de forma explcita el propio dato. Por
ejemplo, la cadena de caracteres Hola EUI en el ejemplo anterior.
o Mediante un identificador de constante. Si se ha dado un nombre simblico al
valor de un dato (por ejemplo: PI = 3.14), el programa puede hacer referencia a l
mediante el identificador asociado.
o Mediante un identificador de variable. Se trata de un caso parecido al de
constantes, con la importante diferencia que el valor asociado al identificador de
la variable (en adelante, simplemente, variable) puede cambiar durante la
ejecucin del programa.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 7

1.2.3.1. Tipos de datos.

El lenguaje Java reconoce de forma predefinida los siguientes tipos8 de datos:

Numricos:
o Enteros (int). En el rango, aproximadamente, 2*109. Adems existen otros tipos
de datos enteros: byte, short y long.
o Racionales o fraccionarios (float). Aproximadamente en el rango 3.4*1038. La
parte real y la fraccionaria se separan mediante un punto (.). Tambin se pueden
utilizar nmeros reales con mayor precisin por medio del tipo double
(aproximadamente en el rango 1.8*10308).
Lgicos (boolean). Se refieren a los valores utilizados en el lgebra de Boole
(verdadero: true o falso: false).
Carcter (char). Se utiliza para representar todos los caracteres del estndar Unicode
(que incluye el ASCII).
Cadena de caracteres (String). Este tipo de datos consiste en una secuencia de
caracteres (por ejemplo El cielo est enladrillado).

1.2.3.2. Tratamiento de datos.

1.2.3.2.1. Operaciones.
Una operacin es un proceso que acta sobre dos datos (operandos) y produce, en
consecuencia, un resultado. Se identifica mediante un smbolo (o palabra reservada)
denominado operador. Excepcionalmente se pueden presentar operaciones (unarias) que
implican un solo operando y/u operaciones con datos de diferentes tipos9. Normalmente
(pero no siempre) se utilizan dos operandos del mismo tipo que, adems, es el tipo del
resultado.

Como consecuencia de la naturaleza (tipo) de un dato, tendr sentido realizar cierto


tipo de operaciones con l. La tabla siguiente muestra las ms habituales:

8
El concepto tipo de datos se asocia implcitamente al los datos elementales (simples). Ms adelante
(apartado 1.4) se contemplar la posibilidad de agrupar datos simples en unidades de orden superior para dar
lugar a diferentes estructuras de datos.
9
Las operaciones con ms de dos operandos las consideramos dentro del epgrafe de expresiones.
8 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

Ejemplo
Tipo Operacin Operador
Operacin Resultado
Entero (int) Suma + 3+5 8
Resta - 1-3 -2
Multiplicacin * 2 * (-5) -10
Cociente / 7/3 2
Resto % 7%3 1
Real (float) Suma + 1,23 + 8,77 10,0
Resta - 1,23 - 8,77 -7,54
Multiplicacin * -3,2 * 4,6 -14,72
Divisin / 3,2 / (-4,6) -0,6956
Lgico (boolean) Negacin ! ! true false
Unin (or) || true || false true
Interseccin (and) && true && false false
Carcter (char) No existen
10
Cadena (String) Concatenacin + Hola + Antonio Hola Antonio

Tabla 1.3. Operaciones bsicas.


Operaciones de relacin.
Se trata de un tipo especial de peraciones en donde los operandos son del mismo
11
tipo y el resultado es de tipo lgico (boolean). Su interpretacin es ligeramente distinta
en funcin del tipo de operandos.

Tipos numricos (int o float) Tipo carcter (char)


Operador
Significado Ejemplo Result. Significado Ejemplo Result.
> Mayor que 7>3 true Posterior a a > z false
12
< Menor que 7<3 false Anterior a P < p true
== Igual a 7 == 3 false Igual a a == A false
>= Mayor o igual que 3 >= 3 true Posterior o igual a z >= m true
<= Menor o igual que (-3) <= 3 true Anterior o igual a M <= N true
!= Distinto de 3 != 3 false Distinto de p !=P true

Tabla 1.4. Operaciones de relacin.

1.2.3.2.2. Funciones estndar y complementos.


En trminos generales se define una funcin como un tratamiento que se realiza
sobre ninguno, uno o varios operandos (argumentos) y produce (devuelve) un resultado.

Los lenguajes de programacin incluyen un conjunto ms o menos amplio de


funciones13 que se identifican como palabras reservadas (forman parte del lenguaje) y

10
Obsrvese que la cadena (String) Antonio incluye un espacio en blanco a su izquierda.
11
Excepto de tipo lgico (boolean) en donde no tiene sentido.
12
Los cdigos Unicode de las letras maysculas son ms bajos que los de las minsculas.
13
La diversidad de oferta de funciones integradas en el lenguaje es muy dispar, no solo entre diferentes
lenguajes sino, tambin, para un mismo lenguaje, entre diferentes desarrolladores de traductores. Para su
eficiente utilizacin se insta encarecidamente a utilizar el manual del fabricante. En este sentido su empleo
debe entenderse como manejo de catlogo, dado que la aportacin conceptual es escasa.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 9

deben emplearse siguiendo la sintaxis adecuada: <nombre de la funcin> (<arg1>,


<arg2>, <argN>).

Algunas funciones estn disponibles como parte integrante del propio lenguaje en
tanto que otras no forman parte del lenguaje. En el caso de Java, las correspondientes
funciones (mtodos) estn declaradas y definidas en componentes (en Java, paquetes o
packages) que, en su conjunto, configuran una biblioteca, almacenadas en uno o varios
directorios14.

Ejemplos:

Algunos de los mtodos de la clase MATH son:


o Valor absoluto. (abs). Su sintaxis es abs (<tipo int|float>). Devuelve un
nmero (integer o real, segn proceda, positivo). Ejemplos:
abs(-3.25) devuelve el valor 3.25.
abs(77) devuelve el valor 77.
o Nmero aleatorio (random). No utiliza argumentos. Devuelve un nmero
racional (real) en el rango 0 < n < 1. Ejemplo: random puede devolver
0,67635
o Redondeo (round), Devuelve el entero ms cercano al argumento.
La clase String tiene entre otros los siguientes mtodos:
o length () devuelve la longitud de una cadena ().
o toLowerCase () devuelve una cadena con todas las letras en minsculas,
o toUpperCase () devuelve una cadena con todas las letras en maysculas
o subString (int, int), devuelve un subString extrado de otro.
La clase Integer (es un wrapper del tipo primitivo int: los wrappers se utilizan para
poder utilizar mtodos como conversin de cadenas de caracteres a enteros y
viceversa), tiene entre otros los siguientes mtodos:
o parseInt (String) convierte una cadena a un nmero entero,
o toString () convierte un nmero entero a una cadena,
o MAX_VALUE, MIN_VALUE, constantes predefinidas que devuelven el
valor mayor y menor de un entero.
Finalmente, usted tambin puede desarrollar sus propias libreras (packages),
almacenarlas en el directorio que considere oportuno, indicarle dicha ubicacin al
compilador y utilizar las correspondientes operaciones (Ver Tema 2 Tipos
Abstractos de Datos).

14
Adems de las componentes (clases) proporcionadas por el fabricante (en este caso Eclipse) el
programador puede incorporar otras de desarrollo propio (ver tema 2: Tipos Abstractos de Datos) o
adquiridas a terceros.
10 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

1.2.3.2.3. Expresiones.
Una expresin es una combinacin (coherente) de datos (literales, constantes y/o
variables), operaciones y funciones, enlazados entre s por medio de operadores.

Como consecuencia de evaluar una expresin, siguiendo las reglas


correspondientes, se obtiene un resultado de tipo acorde con la naturaleza de la expresin.

1.2.4. Sentencias.

Las sentencias son construcciones sintcticas que indican al ordenador qu


operaciones debe realizar y, normalmente, con qu datos. Materializan la parte operativa
de un programa que implementa el algoritmo (definicin de Wirth, 1985) que se deber
ejecutar15. Dicha parte constituye un bloque delimitado por { y }.

Se describe a continuacin, la sintaxis de las sentencia de Java, agrupadas en funcin


de su naturaleza.

1.2.4.1. Asignacin.

Permite, como su propio nombre indica, asignar un valor a una variable (ver 1.2.2)
definida en la parte declarativa. Su sintaxis es:
16
<nombreVariable> = <expresin >;

Ejemplo (HolaEui2.Java):

//Ejemplo de asignacion a variables.


public class HolaEui2 {
public static void main (String [ ] args) {
String cadena = "Hola EUI";
System.out.println (cadena);
}
}

1.2.4.2. Entrada y salida17.

Para realizar la entrada y salida de datos se utiliza la clase Java.io. La entrada


estndar es System.in y la salida estndar es System.out. Para realizar la entrada/salida se
utilizan flujos de datos (streams). Un stream es una conexin entre el programa y la fuente
o destino de los datos. Las sentencias principales son readline (entrada) y print o println
(salida).

La sentencia print, cuya sintaxis bsica es:


System.out.print (<expresin>);

15
Con excepcin de comentarios y Directivas de compilacin. Consultar el manual del compilador.
16
Ver epgrafe Expresiones.
17
Hacen referencia a los dispositivos configurados por defecto (el teclado y la pantalla).
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 11

Hace que se muestre en la pantalla (System.out representa la salida estndar, es decir,


la pantalla) el resultado de evaluar la <expresin> utilizada como argumento. Dicho
argumento debe ser un String, que puede estar formado por la concatenacin (con +) de
varias cadenas de caracteres diferentes. Si se incluye un nmero o valor lgico dentro de la
expresin, se convertir automticamente a un String (por medio de los wrappers: las clases
Integer, Float, Boolean etc.).

Si en vez de utilizar print, utilizamos println, se incluir un salto de lnea despus de


<expresin>.

La sentencia readline, cuya sintaxis bsica es:

BufferedReader linea = new BufferedReader (new InputStreamReader (System.in));


String cadena;
.

cadena = linea.readLine();
.

implica la realizacin de la siguiente secuencia de acciones:

En las dos primeras lneas, se declaran los objetos linea del tipo
BufferedReader y cadena de tipo String.
El usuario escribe los caracteres correspondientes y finaliza pulsando la tecla
Intro.
Se utiliza el mtodo readLine sobre el objeto linea, y se almacena en cadena.
Se contina con la ejecucin del programa.

Para leer otros datos que no sean de tipo String, habra que utilizar una sintaxis
similar a la siguiente:

BufferedReader linea = new BufferedReader (new InputStreamReader (System.in));


int n;
.

n = Integer.parseInt (linea.readLine());
.

que implica la realizacin de la siguiente secuencia de acciones:

En la primera lnea, se declara el objeto linea del tipo BufferedReader.


El usuario escribe los datos correspondientes y finaliza pulsando la tecla
Intro.
Se utiliza el mtodo readline sobre el objeto linea, y como se espera la
introduccin de un dato de tipo int, se convierte la lnea leda (de tipo String),
al tipo entero mediante el mtodo parseInt de la clase Integer.
Se contina con la ejecucin del programa.

A continuacin se muestra un ejemplo (HolaEui3.Java) que contempla la mayora de


consideraciones explicadas hasta el momento.
12 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

import java.io.*;
//Ejemplo de sentencias de entrada/salida.
public class HolaEui3 {
public static void main(String [] args) throws
NumberFormatException,IOException{
String cadena, cadena2;
int edad, ao = 2010;
BufferedReader linea=new BufferedReader (new InputStreamReader (System.in));
System.out.println ("Hola, como te llamas? ");
cadena = linea.readLine();
System.out.println ("Encantado de conocerte, " + cadena);
System.out.println ("Cuantos aos tienes? ");
edad = Integer.parseInt (linea.readLine());
edad = edad+3;
ao = ao+3;
cadena2 = cadena+", en algun momento de "+ao+" tendrs "+edad+" aos";
System.out.println (cadena2);
System.out.println (cadena);
}
}

La figura siguiente (consola de eclipse) muestra un posible resultado de su ejecucin.

Figura 1.4. Ejecucin del ejemplo HolaEui3.pas.

1.2.4.3. Control de flujo.

En los ejemplos anteriores se ha mostrado una de las tres estructuras consideradas en


el enfoque (paradigma) de programacin estructurada: la secuencia. El ordenador ejecuta
(salvo imprevistos) una sentencia tras otra.

Las dos estructuras restantes suponen una ejecucin no lineal del conjunto de
sentencias respecto al orden en que aparecen escritas en el programa. Son las estructuras
alternativa y repetitiva (o iteracin).
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 13

1.2.4.3.1. Estructura alternativa.


Lo que se ejecute depender del resultado de evaluar una operacin de relacin
(<condicin>).

Alternativa simple (if..else).


En su modalidad ms sencilla la estructura alternativa se regula mediante la
sentencia if, cuya sintaxis18 es:
if (<condicion>) {
<grupo de sentencias>;
}
else {
<grupo de sentencias>;
}

Ejemplo:
El siguiente programa informa al usuario de la paridad de un nmero entero
introducido por el teclado.
import java.io.*;

//Ejemplo de alternativa simple.


public class PruebaIf {
public static void main (String [] args) throws NumberFormatException,
IOException {
int dato;
BufferedReader linea=new BufferedReader (new InputStreamReader (System.in));
System.out.print("Numero: ");
dato = Integer.parseInt (linea.readLine());
if ((dato % 2) == 0)
System.out.println (" es par");
else System.out.println (" es impar");
}
}

Operador condicional
El operador condicional ?: se puede usar como abreviatura de la sentencia if, cuya
sintaxis es:
expresionCondicional ? expresionSI : expresionNO;

Primero se evala expresionCondicional. Si es true, se devuelve expresionSI, en


caso contrario se devuelve expresionNO. Por ejemplo, si queremos guardar el valor
menor entre x e y en la variable minimo podramos hacer:

minimo = x <= y ? x : y;

18
Se consideran los siguientes casos particulares:
<grupo de sentencias> puede ser una nica sentencia, y no haran falta las llaves ({ y }).
Se puede omitir else: el ordenador no realizara ninguna accin y ejecutara la siguiente sentencia.
14 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

Alternativa mltiple (switch).


La ejecucin del programa contina por una de entre varias opciones en funcin
del resultado de evaluar una variable (de tipo char o int). Para utilizar esta estructura
se utiliza la sentencia switch, cuya sintaxis general es:

switch (<variable>) {
case <valor1>:
<grupo de sentencias1;>
break;
.
case <valorN>:
<grupo de sentenciasN;>;
break;
default
<grupo de sentenciasD;>
break;
}

Ejemplo:
El programa siguiente espera recibir desde el teclado un dgito, entre 1 y 7,
correspondiente al ordinal del da de la semana (lunes a domingo) y mostrar por la
pantalla el literal del da asociado o un mensaje de error si el cdigo no es vlido.

import java.io.*;
//Ejemplo de alternativa multiple.
public class PruebaSwitch {
public static void main (String [ ] args) throws NumberFormatException,
IOException {
BufferedReader linea = new BufferedReader (new InputStreamReader
(System.in));
System.out.print ("Opcion: ");
int opc = Integer.parseInt (linea.readLine ());
switch (opc) {
case 1: System.out.println ("lunes");
break;
case 2: System.out.println ("martes");
break;
case 3: System.out.println ("miercoles");
break;
case 4: System.out.println ("jueves");
break;
case 5: System.out.println ("viernes");
break;
case 6: System.out.println ("sabado");
break;
case 7: System.out.println ("domingo");
break;
default: System.out.println ("opcion no valida");
break;
}
}
}
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 15

1.2.4.3.2. Estructura iterativa.


Consiste en realizar la ejecucin de un bloque de cdigo varias veces. Las
modalidades que se explican a continuacin dependen de la forma en que se realiza el
control del nmero de repeticiones.

Estructura iterativa controlada por contador (for).


Se utiliza una variable entera que acta como contador. La sentencia indica el
valor inicial del contador, hasta cuando se debe realizar el bucle, as como la cuanta
en que se incrementa (o decrementa) el contador. Su sintaxis es:
for (<val._inicicial> ; <comprobacion>;<incremento>) {
<grupo de sentencias;>
}

Ejemplo:

El siguiente programa muestra por la pantalla el valor de los cuadrados de 5


nmeros introducidos por el teclado.

import java.io.*;
//Ejemplo de bucle for.
public class PruebaFor {
public static void main(String[] args) throws NumberFormatException,IOException{
int i, dato, cuadrado;
BufferedReader linea = new BufferedReader (new InputStreamReader (System.in));
for (i = 1; i <= 5; i ++) {
System.out.print ("Numero: ");
dato = Integer.parseInt (linea.readLine ());
cuadrado = dato * dato;
System.out.println ("El cuadrado de " + dato + " es: " + cuadrado);
}
}
}

Estructura iterativa controlada por condicin.


En los casos siguientes la repeticin, o no, de la ejecucin de un bloque de cdigo
es consecuencia del resultado de evaluar una expresin booleana (<condicin>).
o Estructura mientras (while).
Se utiliza la sentencia while, cuya sintaxis es:
while (<condicion>) {
<grupo de sentencias;>
}
La evaluacin de la <condicin> es previa19 a la ejecucin del bloque de
cdigo que se repite.

19
En consecuencia, podra ser que el bloque de cdigo pudiera no ejecutarse ninguna vez.
16 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

Ejemplo:
El siguiente programa ejecuta reiteradamente el ejemplo de los das de la
semana, salvo que el usuario teclee 0 como opcin20.
import java.io.*;
//Ejemplo de bucle while.
public class PruebaWhile {
public static void main (String [] args) throws NumberFormatException,
IOException {
int opc;
BufferedReader linea = new BufferedReader (new InputStreamReader
(System.in));
System.out.print ("Opcin: ");
opc = Integer.parseInt (linea.readLine());
while (opc != 0) {
switch (opc) {
case 1: System.out.println ("lunes");
break;
case 2: System.out.println ("martes");
break;
case 3: System.out.println ("miercoles");
break;
case 4: System.out.println ("jueves");
break;
case 5: System.out.println ("viernes");
break;
case 6: System.out.println ("sabado");
break;
case 7: System.out.println ("domingo");
break;
default: System.out.println ("opcin no valida");
break;
}
System.out.print ("Opcin: ");
opc = Integer.parseInt (linea.readLine ());
}
}
}

o Estructura Repetir mientras (do while).


Se utiliza la sentencia do ... while, cuya sintaxis es:
do
<grupo de sentencias;>
while (<condicin>);

La evaluacin de la <condicin> es posterior21 a la ejecucin del bloque de


cdigo que se repite.

20
Pruebe a ejecutarlo introduciendo la primera vez la opcin 0.
21
En consecuencia, la ejecucin del bloque tiene lugar, al menos, una vez.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 17

Ejemplo:
El programa siguiente constituye una variante del ejemplo anterior en el que
el bloque de cdigo se ejecuta una vez y volver a repetirse reiteradamente, o
no, hasta que el usuario teclee 0 como opcin22.
import java.io.*;
//Ejemplo de bucle do ... while.
public class PruebaDoWhile {
public static void main (String [] args) throws NumberFormatException,
IOException {
int opc = 7;
BufferedReader linea=new BufferedReader (new InputStreamReader (System.in));
System.out.println("Empezamos en domingo");
do {
switch (opc) {
case 1: System.out.println ("lunes");
break;
case 2: System.out.println ("martes");
break;
case 3: System.out.println ("miercoles");
break;
case 4: System.out.println ("jueves");
break;
case 5: System.out.println ("viernes");
break;
case 6: System.out.println ("sabado");
break;
case 7: System.out.println ("domingo");
break;
default: System.out.println ("opcin no valida");
break;
};
System.out.print ("Opcin: ");
opc = Integer.parseInt (linea.readLine ());
} while (opc != 0);
}
}

22
Pruebe a ejecutarlo introduciendo la primera vez la opcin 0.
18 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

1.3. PROGRAMACIN MODULAR. SUBPROGRAMAS.


1.3.1. Reflexin previa.

Cualquier producto de Ingeniera (desde un barco hasta una central nuclear, pasando
por una catedral) se concibe como un sistema complejo constituido por un conjunto de
subsistemas ms sencillos, y as sucesivamente hasta acabar en piezas indivisibles.

El plantearse las cosas de esta manera permite que un conjunto de profesionales


especializados pueda realizar la obra, con unos costes y tiempos razonables, y que, una vez
finalizada, se puedan acometer con eficiencia las inevitables tareas de actualizacin y
conservacin.

Inexplicablemente, con demasiada frecuencia, nos cuesta transmitir a algunos


alumnos que la filosofa expuesta es (como no poda ser de otra manera), tambin, aplicable
a las obras producidas mediante la Ingeniera del Software. Sostienen que como, de
momento, las aplicaciones que desarrollan en sus actividades prcticas no son de gran
volumen, se acaba antes programando de un tirn y que el da que les toque trabajar en
un proyecto de centenares de millares de lneas de cdigo ya cambiarn de actitud, etc.
Evidentemente, cada cual es libre de equivocarse voluntariamente siempre que as lo
desee.

1.3.2. Tecnologa para la programacin modular.

Cuando hemos hablado antes de programacin modular lo hemos hecho desde una
perspectiva de disciplina mental. Por supuesto que la tecnologa proporciona un
importante conjunto de facilidades para dar soporte a tales concepciones. Aunque su
explicacin pormenorizada queda fuera de los objetivos y alcance de este curso, citaremos,
simplemente, a grandes rasgos las principales variantes:

Mdulos externos. La fuente de procedencia de tales mdulos es diversa:


construidos previamente por el propio programador (o su empresa), incluidos en el
propio entorno de programacin (paquetes o packages en el caso del entorno de
programacin de Java utilizado en el curso) o adquiridos a terceros23. El
programador de aplicaciones, para utilizar dichos mdulos deber nicamente
incorporarlos, indicar al compilador, dnde est/n ubicado/s y saber de que
funcionalidades dispone y que sintaxis hay que emplear.

23
Internet es una fuente casi inagotable donde obtener este tipo de recursos.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 19

Mdulos desarrollados por el propio programador almacenados como ficheros


independientes de la aplicacin principal. A todos los efectos su funcionamiento es
anlogo al caso de los mdulos externos24.
Mdulos desarrollados por el propio programador y almacenados junto con la
aplicacin principal25 en un nico fichero.
Existen varias alternativas tecnolgicas a la hora de gestionar la memoria del
ordenador cuando ejecuta una aplicacin concebida en forma modular. La ms sencilla es la
que aparece ilustrada en la figura siguiente.

Memoria libre

Zona de datos Zona de


algoritmo

Subprograma (mdulo)
<retorno
Zona de datos > Zona de
algoritmo
-----------
-----------

<Llamada>
-----------
Programa principal
-----------
Figura 1.5. Gestin de la memoria en programas modulares-.
Este tipo de gestin de memoria se denomina esttica26 porque durante todo el tiempo
de ejecucin tanto el programa principal como la totalidad de mdulos estn cargados en
memoria, alojados en espacios independientes.

A su vez, cada uno de los espacios se subdivide en otros dos: zona de datos y zona de
algoritmo (la parte de cdigo -previamente traducido a lenguaje de mquina-).

La ejecucin del conjunto tiene lugar a partir de la primera instruccin del programa
principal. Cuando se llega a una <llamada> se suspende y se pasa al contexto del

24
La mayora de entornos de programacin modernos contemplan el concepto de proyecto en donde se indica
el conjunto de mdulos que configuran el sistema y sus ubicaciones. En el curso, dado su carcter bsico, no
utilizaremos esta posibilidad.
25
Se entiende por aplicacin principal a la parte de cdigo (generalmente poco extensa) que utiliza (llama o
invoca) los diferentes mdulos funcionales.
26
Las alternativas ms evolucionadas son de naturaleza dinmica: el bloque correspondiente al programa
principal est permanentemente en memoria mientras que los subprogramas se cargan cuando se necesitan y
al finalizar su ejecucin se libera la memoria ocupada. No obstante esta tcnica es la nica posible cuando se
utiliza el tratamiento recursivo (ver apartado 1.2.5.5)
20 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

subprograma, hasta que finalice su ejecucin, a partir de entonces se reanuda la ejecucin


del programa principal en el punto en que qued suspendida.

1.3.3. Mecanismos para el paso de informacin27.

Cuando un programa llama a un mdulo deber utilizar un nombre que lo identifique


y, adems, pasarle los datos que necesite. El conjunto de estos datos se denomina
genricamente parmetros o argumentos y se expresa mediante las correspondientes
variables y su tipo. Existen dos modalidades de paso de argumentos:

Por valor. La variable del subprograma recibe inicialmente una copia del valor
almacenado, en el momento de producirse la llamada, en el mdulo principal.
Durante su ejecucin (del subprograma) podr modificarlo pero una vez que
finalice, el programa principal conserva intacto su valor. En Java todos los tipos
primitivos (nmeros enteros, reales, caracteres y booleanos) se pasan siempre por
valor.
Por referencia. En este caso no existe tal variable en el mbito del subprograma. El
mecanismo consiste en que el mdulo principal permite al subprograma actuar
sobre sus propias variables. En consecuencia, cualquier modificacin que se
realice en una variable pasada por referencia tendr efecto en el contexto del
programa (mdulo) principal. En Java todos los datos que no sean de un tipo
primitivo se pasan por valor, pero al ser referencias, los datos en s pueden cambiar
(pero no la posicin de memoria en la que estn guardados).

Adems hay que considerar los siguientes aspectos:

Un subprograma puede declarar sus propias variables locales28.


Es posible, pero no recomendable29 (salvo contadas excepciones), declarar una
variable como accesible para el programa principal y la totalidad de los
subprogramas30. Este tipo de variables se denominan globales31.

27
Lo que se explica en el apartado debe entenderse con carcter general. El lenguaje Java solo
admite el paso de argumentos por valor. Esta afirmacin es extensiva al caso de que el argumento sea un
objeto (por ejemplo, un vector) dado que lo que se pasa como argumento por valor es un puntero (referencia)
a dicho objeto que no puede ser modificado por el mdulo subordinado (aunque s el propio objeto).
28
No hay ningn inconveniente en que dos variables locales de mdulos diferentes tengan el mismo
nombre.
29
Una modificacin de una variable global realizada por un mdulo afectar al resto.
30
En este caso si habra ambigedad en caso de coincidencia de nombres de una variable local y otra
global. Esto no supone ningn error de compilacin y la ejecucin podra producir resultados no esperados (ni
deseados).
31
No tiene sentido pasar como argumentos variables globales. Ya estn accesibles desde todos los
mdulos.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 21

Que el programa funcione (correctness) es una condicin necesaria, pero no suficiente.


Existen otros criterios: eficiencia, seguridad, fiabilidad, mantenibilidad, legibilidad, productividad,
posibilidad de desarrollo en equipo, etc.
En la Ingeniera del Software, debe prestarse atencin especial al uso correcto y eficiente de
los datos (la informacin) tanto o ms que al cdigo (algoritmo). A continuacin se indican algunas
recomendaciones en este sentido.
Proteccin de la informacin: evitar el uso de variables globales.
Eficiencia: no pasar ms argumentos que los estrictamente imprescindibles.
Productividad / mantenibilidad: dotar a los subprogramas de la mayor autonoma posible (no pasar
argumentos que se puedan obtener en el contexto del propio subprograma).

1.3.4. Aplicacin al lenguaje Java.

Lo que en otros lenguajes se llama funcin o procedimiento, en Java se llama mtodo.


La cabecera de un mtodo consiste en un nombre, una lista de parmetros (que puede ser
vaca), y el tipo de resultado (si no devuelve resultado, el mtodo ser de tipo void).

La sintaxis (cabecera o prototipo) en Java es:


<tipo devuelto> <nombre del mtodo> (<lista de argumentos>)

Siendo la sintaxis de <lista de argumentos> la siguiente:


<tipo> <argumento1>, <tipo> <argumento2>, ...

Los nombres de los argumentos son formales. No tienen por qu coincidir con los
nombres reales de las variables utilizadas en la llamada al mtodo32. El compilador solo
verifica que las listas de argumentos empleadas en la llamada (reales) y en la cabecera
(formales) coinciden en nmero, tipo y orden.

Las sintaxis de las llamadas es similar a la de las cabeceras, si bien en este caso se
utiliza una versin reducida de la <lista de argumentos> en la que solo aparecen sus
nombres (reales), separados por comas.

El mtodo est delimitado por las llaves de inicio y fin de bloque ({ y }), y a
continuacin aparece la declaracin de variables locales del subprograma y el algoritmo.

Los mtodos que no sean de tipo void deben acabar con la siguiente sentencia:
return <variableDeTrabajo>;

(siendo <variableDeTrabajo> el nombre de una variable local en donde se recoge el


resultado generado por el mtodo). De esta forma el mtodo devuelve el resultado
generado al mdulo de llamada.

Si el mtodo es de tipo void, se puede prescindir de la instruccin return, o utilizarla


sin ninguna variable asociada (return;).

32
El hacerlo as permite que los subprogramas sean reutilizables.
22 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

Dado que el lenguaje Java solo admite el paso de argumentos por valor no es posible
que el modulo subordinado modifique una variable del mdulo de llamada (salvo que se
trate del valor devuelto por el mtodo). En tales situaciones optamos por crear una clase
esttica que declare dicha variable como global de la clase (lo que no contraviene la
recomendacin general de no utilizar variables globales)33 por lo que carecera de sentido
pasarla como argumento.

Como consecuencia de la utilizacin de la tcnica de subprogramacin, el esquema de


estructura general de un programa en Java visto en la seccin 1.2.1 queda ampliado tal
como se muestra a continuacin.

Sintaxis Semntica
import <nombre> Llamada a una (o varias) componente(s) de la biblioteca.
public class <nombre de la clase general> Nombre de la clase general (obligatorio)
{ Principio de la clase.

<constantes y variables de la clase>

<tipo devuelto> <nombre del mtodo1> (<lista Cabecera del mtodo 1


de argumentos>)
{ Inicio del mtodo 1
<constantes y variables del mtodo>
.... sentencias del mtodo 1

return [<variable de trabajo>];


} fin del mtodo 1

<tipo devuelto> <nombre del mtodo1> (<lista Cabecera del mtodo 2


de argumentos>)
Inicio del mtodo 2
{
<constantes y variables del mtodo> sentencias del mtodo 2
....

return [<variable de trabajo>]; fin del mtodo 2

......

public static void main (String [ ] args) Declaracin del programa principal
{ Inicio del programa principal

<llamadas a los mtodos>


sentencias del programa principal

} Fin del programa principal.


} Fin de la clase.

Tabla 1.5. Estructura de un programa en Java.

33
Algunos programadores optan por la alternativa de declarar dicha variable como vector (objeto) y pasar el
puntero (referencia) correspondiente como argumento (por valor).
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 23

1.3.4.1. Ejemplo.

El siguiente programa pide al usuario una serie de cinco nmeros enteros y muestra
por la pantalla dos de sus estadsticas: valor medio y rango.
import java.io.*;
public class PruebaMetodos {
static float media (int dato1, int dato2, int dato3, int dato4, int dato5) {
float resul;
resul = (dato1 + dato2 + dato3 + dato4 + dato5) / 5;
return resul;
}
static int max (int dato1, int dato2, int dato3, int dato4, int dato5) {
int resul;
resul=dato1;
if (dato2 > resul)
resul = dato2;
if (dato3 > resul)
resul = dato3;
if (dato4 > resul)
resul = dato4;
if (dato5 > resul)
resul = dato5;
return resul;
}
static int min (int dato1, int dato2, int dato3, int dato4, int dato5) {
int resul;
resul = dato1;
if (dato2 < resul)
resul = dato2;
if (dato3 < resul)
resul = dato3;
if (dato4 < resul)
resul = dato4;
if (dato5 < resul)
resul = dato5;
return resul;
}
public static void main(String[] args) throws NumberFormatException,IOException{
int d1, d2, d3, d4, d5, rango;
float media;
BufferedReader linea = new BufferedReader(new InputStreamReader(System.in));
System.out.println ("Introduce cinco nmeros enteros: ");
d1 = Integer.parseInt (linea.readLine ());
d2 = Integer.parseInt (linea.readLine ());
d3 = Integer.parseInt (linea.readLine ());
d4 = Integer.parseInt (linea.readLine ());
d5 = Integer.parseInt (linea.readLine ());
media = media (d1, d2, d3, d4, d5);
System.out.println("El valor medio es: " + media);
rango = max (d1, d2, d3, d4, d5) - min (d1, d2, d3, d4, d5);
System.out.println ("y el rango: " + rango);
}
}
24 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

1.3.5. Recursividad.

1.3.5.1. Concepto.

Se define objeto recursivo como: aquel que forma parte de s mismo o que forma
parte de su propia definicin.

La recursividad es un concepto matemtico que permite formular definiciones


como, por ejemplo, la de nmero natural:
o El 1 es un nmero natural.
o El siguiente de un nmero natural es un nmero natural.
Otro ejemplo sera la definicin de factorial de nmero natural:
o 0! = 1;
o N > 0, N! = N * (N-1)!

1.3.5.2. Aplicacin del concepto de recursividad en programacin.

Los ejemplos anteriores se pueden implementar mediante programas informticos que


proporcionan un mtodo sencillo, til y potente de resolucin de infinidad de problemas.
De hecho, hay algunos cuya solucin no recursiva sera de elevada complejidad y escasa
eficiencia34. Frente a las ventajas indicadas (robustez y legibilidad) de la recursividad frente
al tratamiento iterativo se contrapone el inconveniente del mayor consumo de memoria, por
las razones que se explican a continuacin.

La recursividad en programacin se obtiene mediante subprogramas que se llaman a


s mismos (es decir, una de las sentencias del cuerpo del subprograma coincide con el
nombre del mismo), no obstante sera ms correcto decir que llama a otra copia (instancia)
del mismo, esa copia a otra nueva y as sucesivamente hasta que se alcanza una condicin
denominada de terminacin o de parada.

Una vez que se alcanza la condicin de terminacin, en la instancia n-sima se


retorna (como en todo subprograma) al punto del modulo de llamada de la instancia previa
desde donde sta se realiz, y as sucesivamente, teniendo lugar una fase de vuelta por las
instancias anteriores, hasta llegar al punto del programa principal en que se produjo la
llamada al subprograma recursivo.

La implementacin en ordenador de algoritmos recursivos requiere una tecnologa


dinmica, diferente a la esttica (explicada en el apartado 1.3.2), dado que no se sabe, a
priori, cuantas instancias se van a necesitar. Durante la fase de ida se cargan en la
memoria nuevas copias del subprograma35 hasta alcanzar la terminacin (fase de

34
Un ejemplo en este sentido sera el clsico algoritmo denominado Torres de Hanoi.
35
En caso de un nmero elevado de llamadas recursivas es posible quedarse sin espacio libre en memoria y se
produce un error en tiempo de ejecucin (StackOverflowError).
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 25

transicin). Por el contrario, durante la fase de vuelta se libera la memoria


correspondiente a cada instancia a medida que finaliza su ejecucin (ejecuta el cdigo de
retorno).

En el ejemplo siguiente el programa principal llama a un mtodo recursivo que


devuelve el factorial de un nmero natural introducido por el teclado.

import java.io.*;
public class PruebaRecursividad {
static int factorial (int dato) {
int resul = 1;
if (dato > 0)
resul = dato * factorial (dato - 1);
return resul;
}
public static void main(String[] args) throws NumberFormatException,IOException{
int d, f;
BufferedReader linea = new BufferedReader (new InputStreamReader(System.in));
System.out.print("Introduzca el dato: ");
d = Integer.parseInt (linea.readLine ());
if (d >= 0) {
f = factorial(d);
System.out.println("El factorial de " + d + " es: " + f);
}
else System.out.println("No existe el factorial de un nmero negativo");
}
}

Explicacin:
El programa principal llama al subprograma factorial y le pasa como argumento la
variable d. Cuando ste termine de ejecutarse, el programa de llamada dispondr de
un resultado que podr mostrar por la pantalla.
El subprograma factorial es recursivo.
o Su condicin de terminacin es dato == 0. En la instancia en que se alcance36
(transicin) devolver el valor 1.
o Durante la fase de ida, la ejecucin de cada instancia consiste en multiplicar
el valor del argumento recibido desde la instancia anterior (salvo la primera,
que lo recibe directamente del programa principal) por el factorial del nmero
anterior (factorial(N-1)). La ejecucin de esa instancia queda suspendida hasta
que se le devuelva el valor solicitado.
o En la fase de vuelta cada instancia:
Multiplica el valor devuelto por la instancia siguiente por el que, en su
momento de la fase de ida, recibi como argumento,

36
Su nmero de orden ser uno ms que el dato cuyo factorial se quiere calcular.
26 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

almacena el resultado en la variable local resul,


devuelve el contenido de resul a la instancia anterior (sentencia factorial =
resul) y
termina su ejecucin con } (Se libera la memoria correspondiente).
o Observe que la palabra dato tiene dos significados en el cdigo del
subprograma recursivo:
En la llamada factorial (dato-1) se trata de una variable real. Lo que se pasa
como argumento es el valor actual decrementado en una unidad.
En la declaracin del subprograma static int factorial (int dato) es una
variable formal, debe interpretarse como: lo que se reciba.

1.3.5.3. Consideraciones complementarias.


Terminacin anticipada.
La condicin de terminacin la entendemos como pesimista en el sentido de se
alcanza cuando se han invocado todas las instancias posibles. No obstante en
determinadas circunstancias se puede producir37 una terminacin anticipada. En tal
caso lo que se debe hacer es no realizar nuevas llamadas recursivas.
Utilizacin de mdulos de llamada
En determinadas ocasiones, el subprograma recursivo requiere el uso de argumentos
adicionales, difciles de imaginar desde el programa principal. En estos casos la solucin
recomendada es utilizar un subprograma no recursivo (que es el que se llama desde el
mdulo principal) encargado de preparar los argumentos adicionales necesarios y, a
continuacin, llamar al subprograma recursivo.
Momentos de realizacin del proceso e implicacin en la modalidad del paso de
argumentos.
La ejecucin de la lgica del algoritmo puede realizarse en cualquiera de las fases del
tratamiento recursivo (ida, transicin o vuelta) o distribuido en varias de ellas.
Recursividad indirecta.
Si tenemos dos subprogramas A y B, se utiliza la recursividad indirecta cuando el
subprograma A contiene una referencia al subprograma B, y a su vez el subprograma B
contiene una referencia al A, como se puede ver en el siguiente esquema:
static void A () { static void B () {
<sentencia 1>; <sentencia 1>;
<sentencia 2>; ...
B (); A ();
... ......
<sentencia n>; <sentencia m>;
} }

37
En algunos casos la terminacin anticipada es necesaria para el correcto funcionamiento del programa
mientras que en otros, aunque el programa funcione se debe usar por consideraciones de eficiencia.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 27

1.3.5.4. Ejemplos.

Ejemplo 1. (Utilizacin de un mdulo de llamada).


El programa que se muestra a continuacin utiliza un mtodo que obtiene la suma de
los divisores de un nmero natural. Por ejemplo: la suma de los divisores de 40 (2, 4, 5,
8, 10, 20) es 49.
import java.io.*;
public class Recursividad1 {
static int sumaDivisores (int dato, int presuntoDivisor) {
int resul = 0;
if ((presuntoDivisor*2) <= dato) {
resul = sumaDivisores (dato, presuntoDivisor+1);
if ((dato % presuntoDivisor) == 0)
resul = resul + presuntoDivisor;
}
return resul;
}
static int sumaDivisores (int dato) {
return sumaDivisores (dato, 2);
}
public static void main(String[] args) throws NumberFormatException,IOException{
int d, suma;
BufferedReader linea = new BufferedReader (new InputStreamReader(System.in));
do {
System.out.print ("Introduzca un nmero mayor que cero: ");
d = Integer.parseInt (linea.readLine ());
} while (d <= 0);
suma = sumaDivisores (d);
System.out.print ("La suma de los divisores de " + d + " es " + suma);
}
}

El diseador del programa principal no tiene por qu saber que se necesitan otros
argumentos adicionales al dato (d), sin embargo, el subprograma recursivo realmente
necesita otro argumento (presuntoDivisor, de tipo entero), para probar recursivamente
desde 2 hasta d/2 y controlar la terminacin (pesimista).
Ejemplo 2. (Terminacin anticipada).
El siguiente ejemplo consiste en una funcin booleana (esPrim) que indica si un
nmero (d) que se introduce desde el teclado es primo (true) o no (false).

La condicin de terminacin pesimista es d > dato .


En cada instancia, (fase de ida) se prueba si presuntoDivisor es divisor de dato. En
caso afirmativo dato no es primo y se produce terminacin anticipada con resultado
false, en caso contrario se realiza una llamada recursiva incrementando una unidad el
argumento presuntoDivisor. Si se llega a alcanzar la condicin de terminacin
pesimista significa que el nmero (d) es primo y la funcin devuelve true.
28 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

A continuacin se muestra una posible implementacin.


import java.io.*;
public class Recursividad2 {
static boolean esPrim (int dato, int presuntoDivisor) {
boolean resul;
if ((presuntoDivisor*presuntoDivisor) <= dato)
if ((dato % presuntoDivisor) != 0)
resul = esPrim (dato, presuntoDivisor+1);
else resul = false;
else resul = true;
return resul;
}
static boolean esPrimo (int dato) {
boolean resul;
resul = esPrim (dato, 2);
return resul;
}
public static void main(String[] args) throws NumberFormatException,IOException{
int d;
BufferedReader linea = new BufferedReader (new InputStreamReader(System.in));
do {
System.out.print("Introduzca un nmero mayor que cero: ");
d = Integer.parseInt (linea.readLine());
} while (d <= 0);
if (esPrimo(d))
System.out.println(d + " es primo");
else System.out.println (d + " no es primo");
}
}

Ejemplo 3. (Proceso en la fase de vuelta).


En el siguiente ejemplo se desarrolla un mtodo que devuelve:
o La suma de la primera mitad (los ms pequeos) de los factores primos de un
nmero (d). si el nmero total de factores primos es par. Por ejemplo, el nmero
420 tiene un nmero par (4) de factores primos (2, 3, 5, 7). El mtodo devolver
5 (2+3).
o La suma de la segunda mitad (los ms grandes) de los factores primos de un
nmero (d), si el nmero total de factores primos es impar. Por ejemplo, el
nmero 2310 tiene un nmero impar (5) de factores primos (2. 3, 5, 7, 11). La
funcin devolver 18 (7+11).
Para poder comprobar a la vuelta el nmero de factores primos, sera necesario pasar
la variable que represente el nmero de factores por referencia. Como el valor es entero,
y en Java no es posible pasar tipos primitivos por referencia, crearemos una clase
(Suma), dentro de la cual se utiliza la variable miembro numeroFactores (global dentro
de dicha clase, pero no accesible al resto de mtodos). En la llamada al mtodo
sumaPrimosCondicionada desde el programa principal, es necesario indicar que
pertenece a la clase Suma (haciendo la llamada: Suma.sumaPrimosCondicionada (d)).
A continuacin se muestra el cdigo.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 29

import java.io.*;
public class Recursividad3 {
static boolean esPrim (int dato, int presuntoDivisor) {
boolean resul;
if ((presuntoDivisor*presuntoDivisor) <= dato)
if ((dato % presuntoDivisor) != 0)
resul = esPrim (dato, presuntoDivisor+1);
else resul = false;
else resul = true;
return resul;
}
public static class Suma {
static int numeroFactores = 0; //variable global de la clase Suma
static int sumaPrimos (int dato, int presuntoPrimo) {
int resul, orden;
if ((presuntoPrimo * 2) <= dato)
if ((dato % presuntoPrimo) == 0)
if (esPrim (presuntoPrimo, 2)) {
numeroFactores= numeroFactores + 1;
orden = numeroFactores;
resul = sumaPrimos(dato, presuntoPrimo + 1);
if ((numeroFactores% 2) == 0) {
if (orden <= (numeroFactores / 2))
resul = resul + presuntoPrimo;
}
else {
if (orden > ((numeroFactores / 2) + 1))
resul = resul + presuntoPrimo;
}
}
else resul = sumaPrimos (dato, presuntoPrimo + 1);
else resul = sumaPrimos (dato, presuntoPrimo + 1);
else resul = 0;
return resul;
}
static int sumaPrimosCondicionada (int dato) {
int resul;
resul = sumaPrimos (dato, 2);
return resul;
}
}
public static void main(String[] args) throws NumberFormatException,IOException{
int d, suma;
BufferedReader linea = new BufferedReader (new InputStreamReader(System.in));
do {
System.out.print("Introduzca un nmero mayor que cero: ");
d = Integer.parseInt (linea.readLine());
} while (d <= 0);
suma = Suma.sumaPrimosCondicionada (d);
System.out.println ("El resultado es: " + suma);
}
}

En este caso, el proceso no puede realizarse completamente durante la fase de


ida, dado que hasta la transicin no se conocer el nmero total de factores
30 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

primos, por lo que no se sabe qu hay que sumar. La parte de proceso que se realiza
en ella consiste en:
o Identificar si un nmero (argumento presuntoPrimo, pasado por valor) es
primo y factor de d.
En caso negativo se realiza una nueva llamada recursiva con
presuntoPrimo+1.
En caso afirmativo:
Se contabiliza en la variable numeroFactores global dentro de la clase
Suma, inicializado a 0 (pues se utilizar su valor final en la fase de
vuelta).
Se toma nota del nmero de orden (orden) del factor primo
encontrado (variable local que recoge el valor actual de
numeroFactores)38.

NOTA IMPORTANTE: Evitar el error de intentar pasar a la siguiente instancia el valor


de una variable local.

El proceso de la fase de vuelta est condicionado por el lugar desde el que se


hizo la llamada recursiva:
o Si se hizo en una instancia correspondiente a un valor de presuntoPrimo que
no era factor primo, simplemente se retorna el valor recibido desde la
instancia siguiente hacia la anterior39.
o En caso contrario:
Se recibe el valor devuelto por el mtodo desde la instancia siguiente
(resul).
Si el valor de orden se encuentra dentro del rango adecuado (primeros o
ltimos, segn proceda) se suma al valor de resul el de presuntoPrimo.
Se devuelve el resultado a la instancia anterior.

38
En las instancias correspondientes a valores de presuntoPrimo que no son factores primos el valor de la
variable orden es aleatorio
39
Vamos marcha atrs.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 31

Ejemplo 4. (Recursividad indirecta).


En el siguiente ejemplo, se desarrollan los mtodos esPar y esImpar que utilizan la
recursividad indirecta para indicar si el nmero que se recoge del teclado es par o
impar.

import java.io.*;

public class RecursividadIndirecta {


static boolean esPar (int n) {
boolean resul = true;
if (n != 0)
resul = esImpar (n - 1);
return resul;
}
static boolean esImpar (int n) {
boolean resul = false;
if (n != 0)
resul = esPar (n - 1);
return resul;
}

public static void main (String [ ] args) throws IOException {


int n;
boolean esPar;
BufferedReader linea = new BufferedReader (new InputStreamReader (System.in));
System.out.print ("Escriba un nmero para saber si es par o impar: ");
n = Integer.parseInt (linea.readLine ());
esPar = esPar (n);
if (esPar)
System.out.println ("El nmero " + n + " es par");
else System.out.println ("El nmero " + n + " es impar");
}
32 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

1.4. ESTRUCTURAS DE DATOS.


Una estructura de datos es una agrupacin de stos que se trata como una unidad en
su conjunto. Se construyen a partir de los tipos de datos simples, vistos en la seccin
1.2.3.1.

Las estructuras de datos pueden ser homogneas (todos los datos son del mismo tipo)
o heterogneas (constituidas por datos de tipos diferentes).

Las estructuras de datos homogneas ms representativas son los vectores, las tablas
y, en general, las matrices n-dimensionales. El ejemplo ms representativo de estructuras
de datos heterogneas son los registros

Desde otro punto de vista puede hablarse de estructuras de datos estticas y


dinmicas.

Una estructura esttica se caracteriza porque su tamao es conocido a priori (antes de


la ejecucin del programa). En consecuencia, en el cdigo del programa se declaran
variables de tipo esttico y en la compilacin se reserva en memoria el espacio necesario
para ellas.

Por el contrario, las estructuras de datos dinmicas no tienen un tamao predefinido


y la memoria utilizada para almacenarlas se reserva o libera, en tiempo de ejecucin,
segn se requiera.

1.4.1. Estructuras de datos dinmicas

Se dice que una estructura de datos es dinmica cuando inicialmente (en el momento
de la compilacin) no tiene espacio asignado para almacenar informacin. Durante la
ejecucin del programa el sistema (en tiempo de ejecucin, run time) asigna y libera
espacio en memoria, en funcin de las necesidades.

Los temas 3 (Listas), 4 (rboles) y 5 (Grafos) describen distintos tipos de Estructuras


de Datos Dinmicas.

En algunos lenguajes de programacin, para permitir la implementacin de


estructuras de datos dinmicas es necesario un tipo de datos especial, denominado puntero
(pointer).

El concepto de puntero (pointer) hace referencia a una variable cuyo contenido es la


direccin de otra variable (nodo) que realmente contiene el propio dato que se emplea en el
programa40.

40
Este concepto toma su suporte fsico en el mecanismo de direccionamiento indirecto tal como se maneja en
los lenguajes de bajo nivel.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 33

La figura 1.6. muestra un modelo de funcionamiento.

Variable de trabajo
(apuntada por puntero) Memoria
dinmica

Memoria
puntero
esttica

Figura 1.6. Punteros y variables de trabajo.


El inters del uso de punteros en lenguajes de programacin de alto nivel reside en
que constituyen la base para la generacin de estructuras de datos dinmicas. Esto es, que a
lo largo de la ejecucin de un programa, y como consecuencia de las sucesivas operaciones
de insercin y eliminacin, el sistema en tiempo de ejecucin (run time) reserva y libera
respectivamente unidades (nodos) de una regin de memoria destinada a uso dinmico (a
diferencia de la que se reserva en el momento de la compilacin que contiene el cdigo
mquina y el espacio requerido por las variables estticas). Este espacio (esttico) se
mantiene inalterado durante toda la ejecucin del programa.

La utilizacin de esta posibilidad requiere que el lenguaje de programacin disponga


de operaciones que soliciten (de forma transparente al programador) espacio en la memoria
dinmica para crear nuevos nodos, as como la contraria, para liberar espacio
correspondiente a nodos que ya no se necesitan y poder disponer, en consecuencia, de dicho
espacio para uso posterior. En Java se utiliza la sintaxis:

<tipo> <variable> = new <tipo>; para crear un nodo

La variable puntero (en Java se denominan referencias), se almacena en la memoria


esttica y su tamao es fijo. No as los nodos que pueden ser de diferente naturaleza. Es
decir que en la declaracin de un nodo debe hacerse referencia al tipo de dato al que apunta
para que cuando se cree un nodo se reserve con el tamao necesario. Por ejemplo, al
ejecutar el cdigo en Java:
char [ ] puntVector = new char [100];

se declara una variable (puntVector) de tal forma que, al realizar la operacin new se
reserve el espacio necesario para almacenar un vector de 100 caracteres.

Adems de la operacin ya indicada de reserva (new), las referencias admiten las


siguientes operaciones:
34 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

Asignacin: <puntero1> = <puntero2>. La referencia <puntero2> se copia en


<puntero1>, o dicho en otros trminos: <puntero1> deja de apuntar al nodo a que
apuntaba previamente para pasar a apuntar al nodo apuntado por <puntero2>. Una
vez ejecutada la operacin ambos punteros apuntan al mismo nodo41.
Comparacin: <puntero1> == <puntero2>. Devuelve un valor booleano en funcin
de que ambas referencias sean iguales o no, o dicho en otros trminos: que apunten
o no al mismo nodo.

Aunque, como se ha indicado, una variable de tipo puntero apunta a una zona de
memoria (nodo) existe una situacin excepcional consistente en no apuntar a ninguno. En
Java se utiliza para esto la constante null.

Sobre las variables referencia, se realizan las operaciones propias del tipo de datos a
que pertenezcan.

41
Este tipo de operaciones deber hacerse con especial cuidado pues, si no se han tomado previamente las
precauciones oportunas, podra perderse la informacin almacenada en el nodo inicialmente apuntado por
<puntero1> (se perder si no tenemos otra referencia a esa informacin)
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 35

1.4.2. Estructuras de datos estticas.

Una estructura esttica se caracteriza porque su tamao es conocido a priori (antes de


la ejecucin del programa). En consecuencia, en el cdigo del programa se declaran
variables de tipo esttico y en la compilacin se reserva en memoria el espacio necesario
para ellas.

1.4.2.1. Estructuras de datos homogneas.

En las estructuras de datos homogneas todos los datos son del mismo tipo. Como
ejemplo veremos los vectores, las tablas y, en general, las matrices n-dimensionales.

1.4.2.1.1. Unidimensionales (vectores).


El caso ms sencillo es el vector, que se define como un conjunto de elementos, cada
uno de los cuales puede identificarse mediante su posicin relativa (ndice42). La figura
muestra un ejemplo de vector de 5 nmeros enteros.
0 1 2 3 4
20 40 60 80 100

Tabla 1.6. Vector de nmeros enteros.


El lenguaje Java permite utilizar este tipo de estructuras utilizando la sintaxis43:

Declaracin de variables de tipo vector:


<tipo de datos de los elementos del vector> [] <nombre de la variable>;
Por ejemplo, la lnea: int [] vector1;

Declara una variable llamada vector1 que es un vector de enteros inicialmente vaco.

Para indicar el tamao del vector, se puede hacer directamente en la propia lnea de
declaracin:
Int [] vector1 = new int [5]; //declara un vector de 5 elementos de tipo entero.
Acceso:
o Al conjunto. Por ejemplo asignar un vector a otro del mismo tipo:
vector2 = vector1.
En realidad esta instruccin no copia el contenido de vector1 en vector2, sino que
hace que vector2 apunte a la misma posicin de memoria en la que est el vector1.
o A un elemento del vector:
<variable_tipo_vector> [<ndice>];

42
En Java el ndice es numrico y siempre comienza en 0.
43
Se describen solamente las operaciones bsicas. El manejo de este tipo de estructuras admite una gran
flexibilidad. Consultar el manual del lenguaje para mayor informacin.
36 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

Con lo que se podr realizar cualquier operacin acorde con el tipo del elemento
correspondiente. Por ejemplo, si datos es un vector de nmeros enteros podramos hacer:
datos [3] = datos [3] * 2;
Ejemplo.
A continuacin se retoma el ejemplo expuesto en el apartado 1.3.4.1 (valores medio y
rango de un conjunto de 5 nmeros enteros) utilizando un vector.

import java.io.*;
public class PruebaVectores {
static float media (int [ ] dato) {
float resul = 0;
int i;
for (i = 0; i < 5; i ++)
resul = resul + dato [i];
resul = resul / i;
return resul;
}
static int max (int [] dato) {
int resul,i;
resul = dato[0];
for (i = 1; i<5; i++)
if (dato[i] > resul)
resul = dato[i];
return resul;
}
static int min (int [] dato) {
int resul,i;
resul = dato[0];
for (i = 1; i < 5; i ++)
if (dato [i] < resul)
resul = dato [i];
return resul;
}
public static void main(String [] args)throws NumberFormatException,IOException{
int [ ] d = new int [5];
int i, rango;
float media;
BufferedReader linea = new BufferedReader(new InputStreamReader(System.in));
System.out.println ("Introduce cinco nmeros enteros: ");
for (i = 0; i < 5; i ++)
d[i] = Integer.parseInt (linea.readLine ());
media = media (d);
System.out.println ("El valor medio es: " + media);
rango = max (d) - min (d);
System.out.println ("y el rango: " + rango);
}
}
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 37

1.4.2.1.2. Bidimensionales (matrices).


Una matriz es una estructura de dos dimensiones: horizontal (filas) y vertical
(columnas), que contiene elementos del mismo tipo. Se puede hacer referencia a cada uno
de los elementos (celdas) mediante un ndice de fila y otro de columna.

Por ejemplo, la tabla siguiente (temperaturas) muestra las temperaturas mxima y


mnima a lo largo de una semana (las filas indican el da de la semana y las columnas las
temperaturas mnima y mxima, respectivamente. Por ejemplo, la temperatura mnima del
4 da es: temperaturas (3, 0) = 5 grados).
temperaturas 0 1
0 7 15
1 8 17
2 6 13
3 5 14
4 7 14
5 6 16
6 5 13

Tabla 1.7. Temperaturas a lo largo de una semana


Los lenguajes de programacin permiten utilizar este tipo de estructuras. Para sto en
Java se emplea la siguiente sintaxis:

Declaracin de variables de tipo matriz:


< tipo de datos de los elementos > [ ] [ ] <nombre de la variable>;
Ejemplo: int [ ] [ ] temperaturas;
Acceso:
o Al conjunto. Por ejemplo asignar una matriz a otra del mismo tipo:
matriz2 = matriz1.
Como en el caso de los vectores, esta instruccin no copia el contenido de matriz1 en
matriz2, sino que hace que matriz2 apunte a la misma posicin de memoria que matriz1.
o A un elemento de la matriz:
<variable_tipo_matriz>[<ndice1>] [<ndice2>];
(Con lo que se podr realizar cualquier operacin acorde con el tipo del elemento
correspondiente). Por ejemplo: temperaturas [3] [1] = temperaturas [3] [1] + 2;
Ejemplo.
El siguiente cdigo permite encontrar la temperatura mnima de la semana y el da en
que se produjo la mxima diferencia (en caso de coincidencia de varias se muestra el
primero de ellos). En el ejemplo anterior los resultados seran:
Temperatura mnima: 5 grados.
Da de mxima diferencia de temperaturas: 5 (10 grados).
38 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

import java.io.*;
public class PruebaMatrices {
static BufferedReader linea=new BufferedReader(new
InputStreamReader(System.in));
public static void leerMatriz (int [][] temperaturas) throws
NumberFormatException, IOException{
int i,j;
for (i = 0;i < 7; i ++)
for (j = 0; j < 2; j ++) {
System.out.println ("Valor dia: " + i + " extremo: " + j + ": ");
temperaturas [i] [j] = Integer.parseInt (linea.readLine ());
}
}
public static int min (int [][] temperaturas) {
int resul, i;
resul = temperaturas [0] [0];
for (i = 1; i < 7; i++)
if (temperaturas [i] [0] < resul)
resul = temperaturas [i] [0];
return resul;
}
public static int maxDif (int [] [] temperaturas) {
int resul, i, dif;
resul = 0;
dif = temperaturas [0][1]- temperaturas [0][0];
for (i = 1; i < 7; i++) {
if (temperaturas [i][1] - temperaturas [i][0] > dif) {
dif = temperaturas [i][1] - temperaturas [i][0];
resul = i;
}
}
return resul;
}
public static void main(String[] args) throws NumberFormatException,
IOException{
int [][] temperaturas = new int [7][2];
int minimaTemperatura, diferenciaTemperaturas;
leerMatriz (temperaturas);
minimaTemperatura = min (temperaturas);
diferenciaTemperaturas = maxDif (temperaturas);
System.out.println ("Resultados:");
System.out.println ("Temperatura minima: " + minimaTemperatura);
System.out.println ("Dia extremo: " + diferenciaTemperaturas);
}
}
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 39

1.4.2.1.3. N-dimensionales.
Por extensin, lo explicado para una y dos dimensiones se puede aplicar al caso de
matrices N-dimensionales.

1.4.2.2. Estructuras de datos heterogneas.

Como ya se ha indicado, estn constituidas por un conjunto de tipos de datos (ya sean
datos simples u otras estructuras de datos) de diferente naturaleza. La forma bsica de
estructura de datos heterognea es el registro cuyos elementos se llaman campos (o
atributos)44.

Por ejemplo, la figura siguiente muestra un registro (alumno) cuyos campos son: el
nmero de matrcula (numeroMatricula), apellidos (apellidos), nombre (nombre), direccin
de correo electrnico (eMail), ao de nacimiento (anio) y calificacin (calificacion).

numeroMatricula apellidos nombre eMail ao calificacion


alumno bc2658 Snchez Arellano Estela esanchez@servidor.es 1987 6.75

Tabla 1.8. Registro alumno

Para manejar este tipo de estructuras en Java45, se construye una clase dentro de la
cual se definen los datos que van a formar parte de la estructura, as como uno o varios
constructores, como se puede ver en el siguiente ejemplo (correspondiente a la figura):

class RegistroAlumno {
public String numeroMatricula;
public String apellidos;
public String nombre;
public String eMail;
public int ao;
public float calificacion;
public RegistroAlumno (){
numeroMatricula= null;
apellidos = null;
nombre = null;
eMail= null;
ao = 1980;
calificacion = 0;
}

44
Con frecuencia uno de los campos (o combinacin de ellos) se utiliza como identificativo del registro. A
dicho campo (o conjunto) se le denomina clave (key).
45
Existen otras operaciones. Consultar el manual del lenguaje.
40 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

Acceso:
o Al conjunto. Por ejemplo apuntar con una variable de tipo registro mismo sitio
que apunta otra del mismo tipo:
variable2_RegistroAlumno = variable1_RegistroAlumno;
o A un campo del registro:

<variable>.<campo>;
Con lo que se podr realizar cualquier operacin acorde con el tipo del
elemento correspondiente. Por ejemplo: alumno.eMail = esanchez@servidor.es;

Normalmente, el trabajo con un registro (o con un conjunto pequeo de variables


independientes de tipo registro) ofrece poco juego. Lo habitual es utilizar una coleccin
de registros estructurados en un vector, o mucho mejor, almacenarlos, como un fichero
en un dispositivo de almacenamiento externo (tpicamente disco).

La utilizacin de ficheros en dispositivos de almacenamiento externos se explica en el


apartado 1.5. A continuacin se muestra un ejemplo que utiliza un vector de registros del
tipo anterior cuyo modelo se ilustra grficamente en la figura siguiente:

numeroMatricula apellidos nombre eMail ao calificacion


0 aa1253 Arias Gonzlez Felipe farias@servidor.es 1988 3.50
1 ax0074 Garca Sacedn Manuel mgarcia@servidor.es 1985 8.35
2 mj7726 Lpez Medina Margarita mlopez@servidor.es 1990 7,70
3 lp1523 Ramrez Heredia Jorge jramirez@servidor.es 1998 4,50
4 bc2658 Snchez Arellano Estela esanchez@servidor.es 1989 6.75
5 gb1305 Yuste Pelez Juan jyuste@servidor.es 1990 5,50

Tabla 1.9. Vector de registros.


El programa que se muestra a continuacin se ha incluido en dos ficheros (clases) que
forman parte del mismo paquete (package):

RegistroAlumno, que contiene el constructor del registro (construye un registro vaco),


as como los mtodos aCadena, que devuelve el contenido del registro en un String, y
cargarRegistro, que introduce los datos recogidos por teclado en un registro.
PruebaRegistro, en el que aparece el programa principal e incluye dos mtodos,
cargarTabla, que permite cargar la estructura en la memoria central y mediaCalif, que
utiliza la estructura anterior para calcular la calificacin media.
Primero se muestra la clase RegistroAlumno:
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 41

Import java.io.*;
class RegistroAlumno {
public RegistroAlumno () {
numeroMatricula= null;
apellidos = null;
nombre = null;
eMail= null;
ao = 1980;
calificacion = 0;
}
public String aCadena () {
return numeroMatricula + " " + apellidos + " " + nombre + " " + eMail +
" " + ao + " " + calificacion;
}
public String numeroMatricula;
public String apellidos;
public String nombre;
public String eMail;
public int ao;
public float calificacion;
public void cargarRegistro () throws IOException {
BufferedReader linea = new BufferedReader (new InputStreamReader (System.in));
System.out.println ("Numero de matricula: ");
numeroMatricula = new String (linea.readLine ());
System.out.println ("Apellidos: ");
apellidos = new String (linea.readLine ());
System.out.println ("Nombre: ");
nombre = new String (linea.readLine ());
System.out.println ("Correo electronico: ");
eMail = new String (linea.readLine ());
System.out.println ("Ao de nacimiento: ");
ao = Integer.parseInt (linea.readLine());
System.out.println ("Calificacin: ");
calificacion = Float.parseFloat (linea.readLine());
System.out.println (this.aCadena ());
}
}

Como se ha visto en el apartado 1.2.4., los mtodos aCadena y cargarRegistro son


mtodos de objeto (sin modificador static), y para utilizarlos desde fuera de la clase tendr
que hacerse de la forma <nombreVariable>.<nombreMtodo>. Para poder utilizar los
mtodos de objeto, es necesario que previamente hayamos utilizado el constructor del
objeto sobre la variable correspondiente, como hacemos con las instrucciones:
for (i = 0; i < 6;i++)
alumnos [i]= new RegistroAlumno ();
A continuacin aparece la clase PruebaRegistro, donde se incluye el programa
principal:
42 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

import java.io.*;
public class PruebaRegistro {
static void cargarTabla (RegistroAlumno [ ] alumnos) throws IOException {
int i;
for (i = 0; i < 6; i++) {
System.out.println ("Datos del alumno N: "+ i);
alumnos [i].cargarRegistro ();
}
}
static float mediaCalif (RegistroAlumno [ ] alumnos) {
float resul = 0;
int i;
for (i = 0; i < 6; i++) {
System.out.println(alumnos [i].aCadena ());
resul = resul + alumnos [i].calificacion;
}
return resul/6;
}
public static void main (String [ ] args) throws IOException {
RegistroAlumno [ ] alumnos = new RegistroAlumno [6];
float media;
int i;
for (i = 0; i < 6; i++)
alumnos [i]= new RegistroAlumno ();
cargarTabla (alumnos);
media = mediaCalif (alumnos);
System.out.println ("La media de las calificaciones es: " + media);
}
}
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 43

1.5. UTILIZACIN DE DISPOSITIVOS DE ALMACENAMIENTO


EXTERNO.
Con frecuencia las aplicaciones informticas trabajan sobre datos almacenados de
forma estable en dispositivos de almacenamiento (tpicamente discos magnticos).

Una primera vez el usuario crea un fichero (file) y lo guarda en un disco.


Posteriormente podr utilizar dicho fichero, consultar y modificar los datos, as como
aadir nuevos o eliminar alguno/s de los actuales.

La utilizacin de ficheros en disco es muy amplia y va ms all de los objetivos de


este curso. Simplemente indicar que los ficheros estn constituidos por un conjunto de
registros que definen las caractersticas de cada uno de los elementos (fichas) del
fichero46.

Otro aspecto a considerar es cmo organizar las fichas dentro del dispositivo
(fichero). Con soportes tradicionales la forma de organizacin es nica (por ejemplo,
alfabtica) y secuencial (una ficha tras otra, en el orden predefinido). La Informtica ha
heredado esta idea aunque permite otras modalidades de organizacin y modos de acceso
adicionales a los puramente nicos y secuenciales.

1.5.1. Ficheros de texto.

En un fichero de texto, cada una de sus fichas consiste en una cadena de caracteres
de longitud variable (lneas de texto). Las fichas se almacenan una tras otra sin mantener
ningn criterio de orden entre s. Por ejemplo (marsell.txt):

Allons enfants de la Patrie,


Le jour de gloire est arriv!
Contre nous de la tyrannie,
L'tendard sanglant est lev,(bis)
Entendez-vous dans le campagnes,
Mugir ces froces soldats?
Ils viennent jusque dans nos bras,
gorger nos fils, nos compagnes!

Entre cada una de las lneas existen cdigos invisibles cuyo efecto es hacer saltar al
inicio de la lnea siguiente. Estos cdigos se generan automticamente al pulsar la tecla
Intro. As mismo, para indicar el final del fichero de texto, el usuario deber haber
pulsado la tecla de funcin F6.

La figura siguiente muestra el cdigo ASCII correspondiente al ejemplo.

46
Este concepto est heredado de los antiguos ficheros (o archivadores) que contenan fichas (de papel)
cada una de las cuales representaba una informacin unitaria: ficheros de pelculas, personas, asignaturas.
44 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

Pareja de cdigos (ocultos):


Salto de lnea (LF): X=0A; dec=10
Retorno de carro (CR): X=0D;
dec=13

Figura 1.7. Cdigos de fin de lnea y retorno de carro en un fichero de texto.


La figura siguiente muestra, a ttulo de ejemplo, un programa que crea un fichero
(archivo.txt)47 e introduce en l dos lneas de texto (procedentes del teclado y recogidas,
sucesivamente, en la variable, de tipo String, lineaLeida). Una vez finalizado el proceso el
fichero deber cerrarse para permitir posteriores usos del mismo.

import java.io.*;
public class prueba_fichero_texto {
lineaLeida public static void main(String[] args) throws IOException {
FileWriter fich_s = new FileWriter ("archivo.txt");
Marse.txt BufferedWriter bw = new BufferedWriter (fich_s);
PrintWriter salida = new PrintWriter (bw);
BufferedReader linea = new BufferedReader (new
InputStreamReader(System.in));
String lineaLeida;
System.out.println ("Escriba la primera linea: ");
lineaLeida = new String (linea.readLine());
salida.println (lineaLeida);
System.out.println ("Escriba la segunda linea: ");
lineaLeida = new String (linea.readLine());
salida.println (lineaLeida);
salida.close();
}
}

Figura 1.8. Funcionamiento del programa

47
La ruta, nombre y extensin del fichero se eligen libremente (con las restricciones propias del sistema
operativo). En el ejemplo se han utilizado:
Ruta: (por omisin) la misma que el programa.
Nombre: archivo.
Extensin txt (para poder visualizarlo mediante el bloc de notas notepad- de Windows).
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 45

import java.io.*;
public class PruebaFicheroSalida {

public static void main (String [ ] args) throws IOException {


FileWriter fich_s = new FileWriter ("archivo.txt");
BufferedWriter bw = new BufferedWriter (fich_s);
PrintWriter salida = new PrintWriter (bw);
BufferedReader linea = new BufferedReader (new InputStreamReader(System.in));
String lineaLeida;
System.out.println ("Escriba la primera linea: ");
lineaLeida = new String (linea.readLine ());
salida.println (lineaLeida);
System.out.println ("Escriba la segunda linea: ");
lineaLeida = new String (linea.readLine ());
salida.println (lineaLeida);
salida.close ();
}
}

La figura siguiente ilustra un ejemplo de posible resultado de la ejecucin del


programa anterior.

Figura 1.9. Resultado de la ejecucin del programa


46 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

1.5.1.1. Principales consideraciones semnticas.

El programador no es consciente del fichero fsico con que est trabajando. Se crea
un nombre simblico (por ejemplo fich_s), y sobre l se realizan todas las
operaciones48. Slo existe una excepcin, la sentencia:
FileWriter fich_s = new FileWriter ("archivo.txt");
establece una vinculacin entre el nombre fsico del fichero y el nombre lgico.
Se utiliza una variable de tipo String (en el ejemplo: lineaLeida) como puente
entre la memoria del ordenador y el dispositivo de almacenamiento (disco). Segn
sea el sentido de la transferencia se puede hablar de lectura: disco memoria
(readline) o de escritura memoria disco (println).
Hay que preparar el fichero en disco para utilizarlo (apertura) y dejarlo disponible
para posteriores usos (cierre).

1.5.1.2. Sintaxis de las principales operaciones relacionadas con los ficheros de texto49.

Acceso (Asignacin y apertura) y declaracin de variables:


o Crear un nuevo fichero y destruir, en su caso, un fichero previo.
Posteriormente se podr escribir en l:
FileWriter <nombre lgico> = new FileWriter (<nombre fsico>);
BufferedWriter <buffer escritura> = new BufferedWriter (<nombre lgico>);
PrintWriter <variable> = new PrintWriter (<buffer escritura>);
o Preparar un fichero (que debe existir previamente) para poder leer
posteriormente su contenido:
FileReader <nombre lgico> = new FileReader (<nombre fsico>);
BufferedReader <buffer lectura> = new BufferedReader (<nombre lgico>);
o Escribir en un fichero (previamente creado) nuevas lneas de texto a partir de
la ltima:
FileWriter <nombre lgico> = new FileWriter (<nombre fsico>,true);

Proceso:
o Leer (transferir a la variable correspondiente) el contenido de una lnea del
fichero y prepararse para la siguiente.
<variable tipo String> = <buffer lectura>.readline();
o Escribir (transferir) el contenido de una lnea (<expresin tipo String>) al
fichero y prepararse para la siguiente:
<variable>.println = <expresin tipo String>;

48
Dicho fichero estar gestionado por el sistema operativo. Con frecuencia se cambia de ubicacin los
ficheros (fsicos) y de no seguir esta filosofa, esto implicara re-escribir parte del cdigo cada vez que un
fichero cambiase de ubicacin.
49
Para mayor informacin consultar el manual de programacin.
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 47

Terminacin:
o Dejar el fichero preparado para usos posteriores:
<variable>.close ();
Por ejemplo, si queremos leer un fichero hasta llegar al final lo podemos hacer
utilizando lo siguiente:

import java.io.*;
public class PruebaFicheroEntrada {
public static void main (String [ ] args) throws IOException {
String lineaLeida;
FileReader fichLeido = new FileReader ("archivo.txt");
BufferedReader entrada = new BufferedReader (fichLeido);

System.out.println ("Contenido del fichero: ");


while ((lineaLeida = entrada.readLine ()) != null)
System.out.println (lineaLeida);
entrada.close ();
}
}

1.5.2. Ficheros binarios.

En un fichero binario, las fichas son elementos de tipo registro50. En consecuencia


(entre otras) no se puede visualizar su contenido con un visor de texto del sistema operativo
(por ejemplo, el bloc de notas de Windows).

Para poder guardar objetos (por ejemplo, del tipo RegistroAlumno visto en apartados
anteriores) en un fichero hay que hacerlos serializables. Mediante la serializacin, un
objeto se convierte en una secuencia de bytes con la que se puede reconstruir
posteriormente manteniendo el valor de sus variables. Esto permite guardar un objeto en un
archivo o mandarlo por red. Una clase se serializa aadiendo en su definicin:
implements Serializable

Para poder leer y escribir objetos que se han declarado como serializables se utilizan
las clases ObjectInputStream y ObjectOutputStream, que cuentan con los mtodos
writeObject() y readObject().

Para escribir un objeto en un fichero se utilizar:

ObjectOutputStream <objEscrito> = new ObjectOutputStream (new


FileOutputStream("<nombre fichero>"));
<objEscrito>.writeObject (<variable>);

50
Ver apartado 1.4.2 Estructuras de datos heterogneas.
48 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

Mientras que las instrucciones utilizadas para leerlos despus seran:


ObjectInputStream <objLeido> = new ObjectInputStream (new FileInputStream ("<nombre
fichero>"));
<tipo> <variable> = (<tipo>) <objLeido>.readObject ();

Cuando se ha terminado de leer o escribir el fichero correspondiente es necesario


cerrar el fichero con:
<nombre fichero>.close()

El siguiente ejemplo es una variante del programa de gestin de alumnos visto en el


apartado 1.4.2.2. Sus caractersticas ms importantes son51:
Concepcin modular: un programa principal y un conjunto de subprogramas.
No se utilizan variables globales.
El programa principal:
o Prepara el fichero en disco:
String nombre;
BufferedReader linea = new BufferedReader (new
InputStreamReader(System.in));
System.out.println ("Introducir nombre del fichero: ");
nombre = new String (linea.readLine());

o Su lgica se basa en un planteamiento de tipo men:


Llama al mdulo que realiza la interfaz de usuario: menu (sin
argumentos)
Recibe (variable op) la opcin seleccionada, la analiza (mediante una
estructura case) e invoca al mdulo correspondiente:
crearFichero (fichero).
cargarTabla (alumnos, fichero)
mediaCalif (alumnos)
o Utiliza el menor conjunto posible de informacin (variables). Obsrvese que
el programa principal no necesita para nada utilizar registros
correspondientes a alumnos individuales (tipo RegistroAlumno).
El procedimiento menu. Es autnomo (no necesita recibir ni devolver argumentos).
La funcin mediaCalif (alumnos). El nico argumento que necesita es una tabla de
registros de alumnos (RegistroAlumno []).
El procedimiento cargarTabla (alumnos, fichero). Utiliza como informacin de
entrada un fichero y genera en memoria (alumnos) una estructura RegistroAlumno

51
Por simplicidad no se han considerado situaciones excepcionales (por excepcin). Por ejemplo:
No tiene sentido utilizar la opcin [2]: Cargar tabla de registros, si no existe el fichero en disco.
Tampoco lo tiene utilizar la opcin [3]: Calcular calificacin media, si no se ha ejecutado (con xito)
previamente la opcin [2].
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 49

[] que quedar a disposicin del programa principal. Se encarga de abrir, en modo


lectura, el fichero y cerrarlo al finalizar.
El procedimiento crearFichero (fichero). Genera un fichero binario en disco a partir
de los datos introducidos por el usuario desde el teclado. Abre el fichero en modo
escritura y lo cierra al terminar.
El siguiente esquema muestra grficamente la arquitectura de la aplicacin.

Inicio
menu

Mdulo
Fin
principal op

crearFichero cargarTabla mediaCalif

Figura 1.10. Arquitectura del programa ejemplo.


El cdigo del ejemplo sera:

import java.io.*;
public class PruebaFichES {
static void crearFichero (RegistroAlumno [ ] alumnos, String nombref) throws
IOException {
int i;
FileOutputStream fich = new FileOutputStream (nombref);
ObjectOutputStream objEscrito = new ObjectOutputStream (fich);
for (i = 0; i < 6; i++) {
alumnos [i] = new RegistroAlumno();
System.out.println ("Datos del alumno N: "+ i);
alumnos [i].cargarRegistro ();
objEscrito.writeObject (alumnos [i]);
}
fich.close ();
}
static void cargarTabla (RegistroAlumno [ ] alumnos, String nombref) throws
IOException, ClassNotFoundException {
int i;
FileInputStream fich =new FileInputStream (nombref);
ObjectInputStream objLeido = new ObjectInputStream (fich);

for (i = 0; i < 6; i++) {


alumnos [i] = (RegistroAlumno) objLeido.readObject ();
System.out.println ("Datos del alumno N: " + i);
System.out.println(alumnos [i].aCadena ());
}
fich.close ();
}
50 INTRODUCCIN A LA PROGRAMACIN ESTRUCTURAS DE DATOS

static float mediaCalif (RegistroAlumno [ ] alumnos) {


float resul;
int i;

resul = 0;
for (i = 0; i < 6; i++) {
System.out.println (alumnos [i].aCadena ());
resul = resul + alumnos [i].calificacion;}
return resul/6;
}

static void menu () {


System.out.println ("OPCIONES:");
System.out.println ("Opcion 1: Crear fichero.");
System.out.println ("Opcion 2: Cargar tabla de registros.");
System.out.println ("Opcion 3: Calcular calificacion media.");
System.out.println ("Opcion 0: Salir.");
System.out.println ("\n Introduzca opcion: ");
}

public static void main (String[] args) throws IOException,


ClassNotFoundException {

RegistroAlumno [ ] alumnos = new RegistroAlumno [6];


float media;
int op;
String nombre;
BufferedReader linea = new BufferedReader (new InputStreamReader(System.in));

System.out.println ("Introducir nombre del fichero: ");


nombre = new String (linea.readLine ());
menu();
op = Integer.parseInt (linea.readLine ());
while (op != 0) {
switch (op) {
case 1: crearFichero (alumnos,nombre);
break;
case 2: cargarTabla (alumnos, nombre);
break;
case 3: media = mediaCalif (alumnos);
System.out.println ("La media de las calificaciones es: "+media);
break;
default: System.out.println("opcin no valida");
break;
}
menu ();
op = Integer.parseInt (linea.readLine ());
}
System.out.println ("Adios");
}
}
ESTRUCTURAS DE DATOS INTRODUCCIN A LA PROGRAMACIN 51

TEMA 1. ....................................................................................................................... 1

1.1. Conceptos bsicos. ......................................................................................... 1

1.1.1. Caractersticas especficas del lenguaje Java. ........................................ 3

1.1.2. Entorno de programacin (IDE). ............................................................ 4

1.2. Sintaxis del lenguaje Java............................................................................... 5

1.2.1. Estructura de un programa en Java......................................................... 5

1.2.2. Nomenclatura habitual en Java............................................................... 6

1.2.3. Los datos................................................................................................. 6

1.2.4. Sentencias. ............................................................................................ 10

1.3. Programacin modular. Subprogramas. ....................................................... 18

1.3.1. Reflexin previa. .................................................................................. 18

1.3.2. Tecnologa para la programacin modular. .......................................... 18

1.3.3. Mecanismos para el paso de informacin. ........................................... 20

1.3.4. Aplicacin al lenguaje Java. ................................................................. 21

1.3.5. Recursividad. ........................................................................................ 24

1.4. Estructuras de datos. ..................................................................................... 32

1.4.1. Estructuras de datos dinmicas............................................................. 32

1.4.2. Estructuras de datos estticas. .............................................................. 35

1.5. Utilizacin de dispositivos de almacenamiento externo. ............................. 43

1.5.1. Ficheros de texto. ................................................................................. 43

1.5.2. Ficheros binarios. ................................................................................. 47

You might also like