Vous êtes sur la page 1sur 159

UNIVERSIDAD NACIONAL DEL CENTRO DEL PERÚ

INSTITUTO DE INVESTIGACIÓN

Estructura de Datos con Java

Mg. Abraham Esteban Gamarra Moreno


Mg. Job Daniel Gamarra Moreno

2007

iii
Estructura de Datos con Java

Mg. Abraham Esteban Gamarra Moreno


Magíster en Informática
Dr(c) en Ingeniería de Sistemas
Docente de la Facultad de Ingeniería de Sistemas de la Universidad Nacional del Centro
del Perú
email: aegamarra@yahoo.es

Mg. Job Daniel Gamarra Moreno


Ingeniero de Sistemas
Magíster en Administración, mención Informática para la Gestión.
Dr(c) en Ingeniería de Sistemas
Ex docente de la Facultad de Ingeniería de Sistemas de la Universidad Nacional del Centro
del Perú
email: jdgamarram@hotmail.com

v
Estructura de Datos con Java
Mg. Abraham Esteban Gamarra Moreno
Mg. Job Daniel Gamarra Moreno

© Reservado todos los derechos


Universidad Nacional del Centro del Perú.
Huancayo - Perú

Primera Edición: junio de 2007.

Tiraje: 20 ejemplares

Explicación de la portada.

La portada muestra la relación que establece el uso de las Estructuras de Datos con la re-
presentación de bajo nivel de la información.

Hecho el depósito legal en la Biblioteca Nacional del Perú No. 2007-06054

Derechos Reservados.

Prohibida la reproducción total o parcial por cualquier medio sin permiso de los autores.

Libro Electrónico editado en la Universidad Nacional del Centro del Perú, en Huan-
cayo, Perú.

Huancayo, 08 de Junio de 2007.

Diagramación:
Mg. Abraham Esteban Gamarra Moreno
Mg. Job Daniel Gamarra Moreno

vi ESTRUCTURA DE DATOS EN JAVA


PROLOGO

Este texto trata sobre las bases para el desarrollo de


aplicaciones utilizando estructuras de Datos en el entorno
Java de Sun MicroSystem. Java es un lenguaje para entornos
de desarrollo standalone (independiente); así como para
aplicaciones web.

El objetivo de este libro es mostrar los fundamentos para


la programación y el uso de las estructuras de Datos con
Java; a través del desarrollo de aplicaciones.

Para el desarrollo de los programas se utilizara el JDK


versión 5.

Mg. Abraham Esteban Gamarra Moreno

Mg. Job Daniel Gamarra Moreno

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno vii


CONTENIDO

PROLOGO .......................................................................................................................................... VII

CONTENIDO ........................................................................................................................................IX

SOBRE LOS AUTORES ...................................................................................................................XIII

INTRODUCCION............................................................................................................................... XV

CAPITULO UNO .................................................................................................................................... 1

OBJETOS Y CLASES ............................................................................................................................ 1


1.1. ENTRADA Y SALIDA BASICA .......................................................................................... 1
1.1.1. FLUJOS DE ENTRADA DE BYTE Y CHAR (ENTRADA POR EL TECLADO) ............... 4
1.1.2. FLUJOS DE SALIDA DE BYTE Y CHAR (SALIDA POR EL MONITOR) ....................... 5
1.1.3. USO DE EXCEPCIONES EN LA ENTRADA Y SALIDA DE DATOS............................... 6
1.2. ENTRADA Y SALIDA UTILIZANDO TIPOS DE DATOS PRIMITIVOS ......................... 9
1.2.1. FLUJOS DE ENTRADA A TRAVES DE BUFFEREDREADER (ENTRADA POR EL
TECLADO) .................................................................................................................................... 10
1.2.2. FLUJOS DE SALIDA A TRAVÉS DE LA SUBCLASE PRINTSTREAM (SALIDA POR
EL MONITOR)............................................................................................................................... 11
1.2.3. MANEJO DE LOS TIPOS DE DATOS PRIMITIVOS ..................................................... 12
1.3. ¿QUÉ ES LA PROGRAMACIÓN ORIENTADA A OBJETOS? .......................................................... 20
1.4. UN EJEMPLO SENCILLO DE LA POO ........................................................................................ 22
1.5. MÉTODOS BÁSICOS ............................................................................................................... 24
1.5.1. Constructores .................................................................................................................. 24
1.5.2. Métodos modificadores y de acceso ................................................................................ 25
1.5.3. Salida y toString .............................................................................................................. 26
1.5.4. Métodos static.................................................................................................................. 26
1.5.5. Método main.................................................................................................................... 27
1.6. EJEMPLOS DEL USO DE CLASES ................................................................................... 27
CAPITULO DOS................................................................................................................................... 35

TIPOS DE DATOS ABSTRACTOS (TDA)........................................................................................ 35


2.1. TIPO DE DATOS ...................................................................................................................... 35
2.2. TIPOS DE DATOS ABSTRACTOS (TDA) ................................................................................... 35
2.3. IMPLEMENTACIÓN DE TIPOS DE DATOS ABSTRACTOS ............................................................ 36
CAPITULO TRES ................................................................................................................................ 47

LISTAS ENLAZADAS ......................................................................................................................... 47


3.1. LISTAS ENLAZADAS ............................................................................................................... 47
3.1.1. Definiciones:.................................................................................................................... 47
3.1.2. Operaciones básicas con una lista .................................................................................. 48
3.2. IMPLEMENTACIÓN DE LISTAS USANDO REFERENCIAS A OBJETOS ........................................... 48
3.3. LISTA LINEAL SIMPLEMENTE ENLAZADA ............................................................................... 48
3.3.1. Implementación de la lista lineal con referencias ........................................................... 49
3.4. UNA LISTA LINEAL DOBLEMENTE ENLAZADA........................................................................ 51
3.4.1. Implementación de una la lista doblemente enlazada usando referencias...................... 52
3.5. LISTA CIRCULAR SIMPLEMENTE ENLAZADA........................................................................... 53
3.5.1. Implementación de una la lista circular simplemente enlazada usando referencias....... 53
3.6. LISTA CIRCULAR DOBLEMENTE ENLAZADA............................................................................ 55
Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno ix
3.7. PROGRAMAS EJEMPLO ...........................................................................................................55
3.8. PROBLEMAS PROPUESTOS ......................................................................................................65
CAPITULO CUATRO..........................................................................................................................67

RECURSION .........................................................................................................................................67
4.1. ALGORITMOS RECURSIVOS ....................................................................................................67
4.2. PROBLEMAS PROPUESTOS ......................................................................................................72
CAPITULO CINCO..............................................................................................................................75

PILAS Y COLAS...................................................................................................................................75
5.1. PILAS (LIFO) ........................................................................................................................75
5.1.1. Operaciones básicas ........................................................................................................76
5.1.2. Implementación de pilas con referencias.........................................................................76
5.2. COLAS (FIFO) .......................................................................................................................78
5.2.1. Operaciones.....................................................................................................................78
5.2.2. Implementación de colas con referencias........................................................................79
5.3. PROGRAMAS EJEMPLO ...........................................................................................................81
CAPITULO SEIS ..................................................................................................................................97

ARBOLES ..............................................................................................................................................97
6.1. ÁRBOLES EN GENERAL ..........................................................................................................97
6.2. CARACTERÍSTICAS Y PROPIEDADES DE LOS ÁRBOLES ............................................................98
6.3. ARBOL BINARIO...................................................................................................................100
6.3.1. Definiciones ...................................................................................................................101
6.4. REPRESENTACIÓN DE ÁRBOLES GENERALES COMO BINARIOS ..............................................102
6.5. RECORRIDO DE UN ÁRBOL ...................................................................................................103
6.5.1. Recorrido en Preorden ..................................................................................................104
6.5.2. Recorrido en Inorden.....................................................................................................104
6.5.3. Recorrido en Postorden .................................................................................................104
6.6. IMPLEMENTACIÓN DE UN ÁRBOL MEDIANTE REFERENCIAS ..................................................106
6.6.1. Implementación del recorrido PreOrden.......................................................................107
6.6.2. Implementación del recorrido InOrden .........................................................................108
6.6.3. Implementación del recorrido PostOrden .....................................................................109
6.7. ÁRBOL BINARIO DE BÚSQUEDA ...........................................................................................110
6.7.1. Inserción en un arbol binario de búsqueda ...................................................................111
6.7.2. Borrado en un arbol binario de búsqueda.....................................................................114
6.8. CLASE GENERICA PARA LA IMPLEMENTACIÓN DE ARBOLES CON REFERENCIAS ...................117
CAPITULO SIETE .............................................................................................................................123

ORDENAMIENTO Y BÚSQUEDA ..................................................................................................123


7.1. ORDENAMIENTO ..................................................................................................................123
7.2. CLASES DE ORDENAMIENTO ................................................................................................123
7.3. MÉTODOS DIRECTOS DE ORDENAMIENTO ............................................................................124
7.3.1. Ordenamiento por intercambio directo. Método de la burbuja.....................................124
7.4. MÉTODOS AVANZADOS DE ORDENAMIENTO:.......................................................................127
7.4.1. Ordemamiento con el método de shell...........................................................................127
7.4.2. Ordenamiento rápido (quick sort) .................................................................................129
7.5. PROGRAMA CON LOS ALGORITMOS DE ORDENAMIENTO ......................................................131
7.6. MEZCLA CONTROLADA POR FIN DE ARCHIVO ......................................................................133
7.7. CLASIFICACIÓN DE ARCHIVOS (ORDENAMIENTO EXTERNO) ................................................134
x Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
7.7.1. Clasificación por mezcla directa ................................................................................... 135
7.7.2. Clasificación por mezcla equilibrada............................................................................ 136
7.7.3. Clasificación de raíz...................................................................................................... 137
7.8. BÚSQUEDA .......................................................................................................................... 139
7.8.1. Definiciones................................................................................................................... 139
7.8.2. Clases de búsqueda ....................................................................................................... 139
7.9. BÚSQUEDA SECUENCIAL ..................................................................................................... 140
7.10. BÚSQUEDA BINARIA ............................................................................................................ 140
7.11. PROGRAMA CON LOS ALGORITMOS DE BÚSQUEDA .............................................................. 141
7.12. EFICIENCIA DE LOS ALGORITMOS DE ORDENAMIENTO Y BÚSQUEDA .................................... 143
BIBLIOGRAFÍA ................................................................................................................................. 145

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno xi


Sobre los autores

Mg. Abraham Esteban Gamarra Moreno


Magíster en Informática.
Dr(c) en Ingeniería de Sistemas.
Docente de la Facultad de Ingeniería de Sistemas de la Universidad Nacional del Cen-
tro del Perú.
Docente de la Maestría en Administración en la Universidad Nacional del Centro del
Perú.
Docente de la Maestría en Ingeniería de Sistemas en la Universidad Nacional del Cen-
tro del Perú.
Docente de la Maestría en Ingeniería de Sistemas en la Universidad Nacional Federico
Villarreal.
Asesor y consultor en Informática y Sistemas.

Mg. Job Daniel Gamarra Moreno


Magíster en Administración, mención Informática para la Gestión.
Dr(c) en Ingeniería de Sistemas.
Ex - Docente de la Facultad de Ingeniería de Sistemas de la Universidad Nacional del
Centro del Perú.
Docente de la Maestría en Ingeniería de Sistemas en la Universidad Nacional del Cen-
tro del Perú.
Docente de la Maestría en Administración en la Universidad Nacional del Centro del
Perú.
Asesor y consultor en Informática y Sistemas.

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno xiii


INTRODUCCION

Los lenguajes de programación tienen disponibles tipos de


datos básicos, que en ocasiones son insuficientes en el
desarrollo de nuestras aplicaciones. Entre algunos tipos
de datos que podríamos necesitar están los quebrados, los
números complejos, los polinomios, entre otros; los cuales
no están implementados entre los lenguajes de programación
de propósito general.

Con el uso de las estructuras de datos, podemos implemen-


tar estos nuevos tipos de datos y de esta forma hacer que
se adecuen a nuestras necesidades.

El uso de las estructura de datos se ha difundido en el


lenguaje de programación Pascal y el lenguaje de programa-
ción C, e inclusive existe bibliografía disponible en es-
tos lenguajes; pero en el lenguaje de programación Java la
bibliografía es limitada. El libro pretende utilizar y
programar las estructuras de datos en Java a través de
ejemplos.

En el primer capítulo trata de los fundamentos de la Pro-


gramación Orientada a Objetos en Java, en el segundo capí-
tulo se describe el uso de los Tipos de Datos Abstractos;
el tercer capítulo describe el uso de las listas enlaza-
das. El cuarto capítulo muestra el uso de la recursividad,
el quinto capítulo el uso de las pilas y colas; el sexto

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno xv


capítulo describe el uso de la estructura árbol y el sép-
timo capítulo trata sobre el ordenamiento y búsqueda.

Mg. Abraham Esteban Gamarra Moreno

Mg. Job Daniel Gamarra Moreno

xvi Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


CAPITULO UNO

OBJETOS Y CLASES

1.1. ENTRADA Y SALIDA BASICA


Con frecuencia los programas necesitan ingresar in-
formación desde una fuente externa o enviar infor-
mación hacia un destino externo. La información
puede estar en cualquier lado: en un archivo, en
disco, en algún lugar de la red, en memoria, o en
otro programa. También puede ser de cualquier tipo:
objetos, caracteres, imágenes, o sonidos.

Para ingresar información, un programa abre un flu-


jo en una fuente de información (source: un archi-
vo, memoria, un socket) y lee la información en se-
rie, de esta manera:

De la misma forma, un programa puede enviar infor-


mación a un destino externo abriendo un flujo hacia

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 1


el destino y escribiendo la información en serie,
de esta manera:

No importa de donde viene la información o hacia


donde va y no importa que tipo de datos se está le-
yendo o escribiendo, los algoritmos para leer y es-
cribir datos son en general siempre iguales.

Reading (Lectura) Writing (Escritura)

Abrir el flujo
Abrir el flujo
Mientras haya más información
Mientras haya más información
leer la información
escribir información
cerrar el flujo
cerrar el flujo

El paquete java.io contiene una colección de clases


de flujos que soportan estos algoritmos para lectu-
ra y escritura. Estas clases están divididas en dos
jerarquías de clases basados en el tipo de datos
(si son caracteres o bytes) con el que operan.

Flujo de carácter Flujo de byte

2 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


Hay veces que es más conveniente agrupar a las cla-
ses por su propósito en vez de por el tipo de datos
que leen o escriben. Así, podemos cruzar los grupos
de flujos de acuerdo a como leen y escriben hacia
almacenes de datos o procesan la información a me-
dida que se va leyendo o escribiendo.
Flujo de carácter Flujo de byte

Flujo sumidero de
datos

Flujo de procesa-
miento

Las clases del paquete java.io están divididas en


dos grupos distintos, ambos derivados de la clase
Object del paquete java.lang, según se muestra en
la figura siguiente. El grupo de la izquierda ha
sido diseñado para trabajar con datos de tipo byte
y el de la derecha con datos de tipo char. Ambos
grupos presentan clases análogas que tienen inter-
faces casi idénticas, por lo que se utilizan de la
misma manera (Fig.1.1.).

Figura 1.1 La clase Object y sus derivados


Las clases en negrita son clases abstractas. Una
clase abstracta no permite que se creen objetos de
Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 3
ella. Su misión es proporcionar miembros comunes
que serán compartidos por todas sus subclases.

1.1.1. FLUJOS DE ENTRADA DE BYTE Y CHAR


(ENTRADA POR EL TECLADO)

La clase InputStream es una clase abstrac-


ta que es superclase de todas las clases
que representan un flujo en el que un des-
tino lee bytes de un origen. Cuando una
aplicación define un flujo de entrada, la
aplicación es destino de ese flujo de by-
tes, y es todo lo que se necesita saber.

El método más importante de esta clase es


read. Este método se presenta de tres for-
mas:
public abstract int read() throws IOException

public int read(byte[] b) throws IOException

public int read(byte[] b, int off, int len) throws IOException

La primera versión de read simplemente lee


bytes individuales de un flujo de entrada;
concretamente lee el siguiente byte de da-
tos disponible. Devuelve un entero (int)
correspondiente al valor ASCII del carác-
ter leído.

La segunda versión del método read lee un


número de bytes de un flujo de entrada y
los almacena en una matriz b (más adelante
analizaremos las matrices de datos). De-
vuelve un entero correspondiente al número
de bytes leídos, o bien —l si no hay bytes
disponibles para leer porque se ha alcan-
zado el final del flujo.

La tercera versión del método read lee un


máximo de len bytes a partir de la posi-
ción off de un flujo de entrada y los al-
macena en una matriz b.

4 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


La biblioteca de Java proporciona
el flujo estándar de entrada,
manipulado por la clase system del
paquete java.lang, que es
automáticamente abierto cuando se
inicia un programa y cerrado cuando
este finaliza; este es denominado
system.in.

Se puede utilizar el método read a través


de clase system de la siguiente forma:

Variable = System.in.read()

Análogamente, la clase Reader es una clase


abstracta que es superclase de todas las
clases que representan un flujo para leer
caracteres desde un origen. Sus métodos
son análogos a los de la clase InputS-
tream, con la diferencia de que utilizan
parámetros de tipo char en lugar de byte.
En nuestros ejemplos utilizaremos la clase InputStream a
través de System.

1.1.2. FLUJOS DE SALIDA DE BYTE Y CHAR (SA-


LIDA POR EL MONITOR)

La clase OutputStream es una clase abs-


tracta que es superclase de todas las cla-
ses que representan un flujo en el que un
origen escribe bytes en un destino. Cuando
una aplicación define un flujo de salida,
la aplicación es origen de ese flujo de
bytes (es la que envía los bytes).

El método más importante de esta clase es


write, Este método se presenta de tres
formas:
public abstract void write(int b) throws IOException

public void write(byte[] b) throws IOException

public void write(byte[] b, int off, int len) throws IOException


Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 5
La primera versión de write simplemente
escribe el byte especificado en un flujo
de salida. Puesto que su parámetro es de
tipo int, lo que se escribe es el valor
correspondiente a los 8 bits menos signi-
ficativos, el resto son ignorados.

La segunda versión del método write escri-


be los bytes almacenados en la matriz b en
un flujo de salida (más adelante analiza-
remos las matrices de datos).

La tercera versión del método write escri-


be un máximo de len bytes de una matriz b
a partir de su posición off, en un flujo
de salida.

Cada uno de estos métodos ha sido escrito


para que bloquee la ejecución del programa
que los invoque hasta que toda la salida
solicitada haya sido escrita.

De manera análoga a read utilizaremos la


clase System para llamar al método write,
de la siguiente forma:

System.out.write(parametro)

Análogamente, la clase Writer (tal como se


muestra en la Fig 1.1.) es una clase abs-
tracta que es superclase de todas las cla-
ses que representan un flujo para escribir
caracteres a un destino. Sus métodos son
análogos a los de la clase OutputStream,
con la diferencia de que utilizan paráme-
tros de tipo char en lugar de byte.

1.1.3. USO DE EXCEPCIONES EN LA ENTRADA Y


SALIDA DE DATOS

Cuando durante la ejecución de un programa


ocurre un error que impide su continua-
6 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
ción, por ejemplo, una entrada incorrecta
de datos o una división por cero. Java
lanza una excepción, que cuando no se cap-
tura da lugar a un mensaje acerca de lo
ocurrido y detiene su ejecución (las ex-
cepciones se lanzan, no ocurren). Ahora,
si lo que deseamos es que la ejecución del
programa no se detenga, habrá que captu-
rarla y manejarla adecuadamente en un in-
tento de reanudar la ejecución.

Las excepciones en Java son objetos de


subclases de Throwable. Por ejemplo, el
paquete java.io define una clase de excep-
ción general denominada IOException para
excepciones de entrad y salida.

Puesto que en Java hay muchas clases de


excepciones, un método puede indicar los
tipos de excepciones que posiblemente pue-
de lanzar. Por ejemplo, puede observar que
los métodos read y write que acabamos de
exponer lanzan excepciones del tipo IOEx-
ception. Entonces, cuando utilicemos algu-
no de esos métodos hay que escribir el có-
digo necesario para capturar las posibles
excepciones que pueden lanzar. Esto es al-
go a lo que nos obliga el compilador Java,
del mismo modo que él verifica si una va-
riable ha sido iniciada antes de ser uti-
lizada, o si el número y tipo de argumen-
tos utilizados con un método son correc-
tos, con la única intención de minimizar
los posibles errores que puedan ocurrir.

La forma básica de evitar escribir el có-


digo, cuando se produce una excepción, es
utilizar la siguiente línea en el main:

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

En secciones posteriores analizaremos con


más detenimiento las excepciones.

A continuación se presenta un ejemplo del


uso del read y write para leer y escribir
un byte respectivamente.

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 7


Ejemplo ( 1): Uso de read() y write().

//archivo: lecturabytes.java

import java.io.*;

class lecturabytes
{
public static void main (String[] args)
throws IOException
{
// declaración de las variables
int n;
//lee un byte
n=System.in.read();
//escribe un byte
System.out.write(n);
//escribe un salto de línea
System.out.write('\n');
}
}

La ejecución del programa se muestra de la


siguiente manera:

Una característica aún no mencionada es:


import java.io.*;

el cual le indica al compilador que impor-


te las clases necesarias del paquete ja-
va.io, para poder utilizar la entrada y
salida de Java. El comodín * sustituye a
cualquier nombre del paquete.

Nota: Cuando ejecute el programa usted de-


be ingresar el carácter por el teclado y
luego presionar [ENTER].

8 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


1.2. ENTRADA Y SALIDA UTILIZANDO TIPOS DE
DATOS PRIMITIVOS
La sección anterior permitía la entrada y salida de
un byte o un carácter; pero ahora mostraremos como
se puede manejar la entrada y salida de los tipos
de datos primitivos mostrados en la sección 1.12.1.

Antes de mencionar el uso de los datos primitivos


ubiquémonos en la jerarquía de clases que se mues-
tra en la figura 1.2.

InputStream Reader

OutputStream Writer

Figura 1.2 Clases y subclases derivados de la clase Object


En la figura anterior se pueden observar las clases
abstractas en los recuadros con líneas diagonales y
sus derivadas; una línea discontinua indica que esa
clase no se deriva directamente de Object; esto es,
entre Object y la clase hay otras clases.

Además debemos observar que para la lectura se pue-


de utilizar la subclase BufferedInputStream (deri-
vada de InputStream) para leer bytes; esta clase
hereda el método read, ya explicado anteriormente,
el cual no es muy conveniente para trabajar con
tipos de datos primitivos; por lo tanto sugerimos
utilizar las subclases derivadas de Reader, que
leen cadena de caracteres.

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 9


Para leer una cadena de caracteres del flujo in y
almacenarlo en un objeto String, lo tenemos que
hacer desde un flujo de la clase BufferedReader y
para escribir en el flujo out tenemos los métodos
proporcionados por la clase PrintStream o bien
PrintWriter, que permiten escribir cualquier valor
de cualquier tipo primitivo o referenciado.

1.2.1. FLUJOS DE ENTRADA A TRAVES DE


BUFFEREDREADER (ENTRADA POR EL
TECLADO)

Para realizar la lectura utilizaremos una


combinación de InputStreamReader y Buffe-
readReader, de la siguiente forma:
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader flujoE = new BufferedReader(isr);

La clase InputStreamReader establece un


puente para pasar flujos de bytes a flujos
de caracteres tal como se muestra en la
figura 1.3. Para ello debemos definir el
flujo que hemos denominado isr como se
muestra en el código anterior.

Además el código anterior indica que el


flujoE dirigirá todas las invocaciones de
sus métodos al flujo subyacente isr; este
flujo, en el caso de que el origen sea el
teclado (dispositivo vinculado con Sys-
tem.in), deberá convertir los bytes leídos
del teclado en caracteres. De esta forma
flujoE podrá suministrar un flujo de ca-
racteres al programa destino de los datos.

Programa flujoE isr in Teclado

caracteres bytes

Figura 1.3

10 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


Para realizar la lectura de las cadenas
utilizaremos el método readLine, el cual
nos permite leer una línea de texto. El
método readLine tiene la siguiente sin-
taxis:
public String readLine() throws IOException

1.2.2. FLUJOS DE SALIDA A TRAVÉS DE LA SUB-


CLASE PRINTSTREAM (SALIDA POR EL
MONITOR)

La clase PrintStream se deriva indirecta-


mente de OutputStream, por lo tanto hereda
todos los miembros de ésta: por ejemplo el
método write expuesto anteriormente. Otros
métodos de interés que aporta esta clase
son: print y println. La sintaxis para es-
tos métodos es la siguiente:

print (tipo argumento);

println ([tipo argumento]);

Los métodos print y println son esencial-


mente los mismos; ambos escriben su argu-
mento en el flujo de salida. La única di-
ferencia entre ellos es que println añade
un carácter ‘\n‘ (avance a la línea si-
guiente) al final de su salida, y print
no.

Ejemplo ( 2): Programa que lee e imprime


una cadena.
//archivo: lecturacadenas.java

import java.io.*;

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

{
// Definir un flujo de caracteres de entrada:
flujoE

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 11


InputStreamReader isr = new
InputStreamReader(System.in);
BufferedReader flujoE = new
BufferedReader(isr);

String sdato; // variable para almacenar una


//línea de texto

System.out.print("Introduzca un texto: ");


sdato = flujoE.readLine(); // leer una línea
de
//texto

System.out.print("el texto leido es: ");


System.out.println(sdato); // escribir la
//línea leída
}
}

La ejecución muestra la siguiente pantalla:

1.2.3. MANEJO DE LOS TIPOS DE DATOS PRIMI-


TIVOS

Evidentemente, cualquier operación aritmé-


tica requiere de valores numéricos; pero,
según lo expuesto en el mejor de los casos
sólo se puede obtener una cadena de bytes.
Ahora bien, para que esa cadena de carac-
teres pueda ser utilizada en una expresión
aritmética, tiene que adquirir la catego-
ría de valor numérico, lo que implica con-
vertirla a un valor de alguno de los tipos
primitivos. Esto puede hacerse utilizando
los métodos proporcionados por las clases
que encapsulan los tipos primitivos.

Class Integer

La clase Integer cubre un valor del tipo


de dato primitivo int dentro de un objeto.

12 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


Además, esta clase proporciona varios mé-
todos para convertir un int a String y un
String a int, así como otras constantes y
métodos útiles cuando tratan con un int.

A continuación se tiene algunos atributos


y métodos principales de la clase Integer:
Atributos
Static int MAX_VALUE
Una constante que contiene el máximo
valor en un int: 231-1.
Static int MIN_VALUE
Una constante que contiene el minimo
valor en un int: -231.

Constructores
Integer(int value)
Construye un objeto Integer que representa el
valor especifico del int.
Integer(String s)
Construye un objeto Integer que representa el
valor int indicado por el parámetro String.

Ahora mostramos en el idioma original los Métodos de la


clase Integer1
Métodos
byte byteValue()
Returns the value of this Integer as
a byte.
int compareTo(Integer anotherInteger)
Compares two Integer objects numeri-
cally.
int compareTo(Object o)
Compares this Integer object to an-
other object.
static Integer decode(String nm)
Decodes a String into an Integer.
double doubleValue()
Returns the value of this Integer as
a double.

1
Fuente: JDK HELP
Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 13
boolean equals(Object obj)
Compares this object to the speci-
fied object.
float floatValue()
Returns the value of this Integer as
a float.
static Integer getInteger(String nm)
Determines the integer value of the
system property with the specified name.
static Integer getInteger(String nm, int val)
Determines the integer value of the
system property with the specified name.
static Integer getInteger(String nm, Integer val)
Returns the integer value of the
system property with the specified name.
int hashCode()
Returns a hash code for this Inte-
ger.
int intValue()
Returns the value of this Integer as
an int.
long longValue()
Returns the value of this Integer as
a long.
static int parseInt(String s)
Parses the string argument as a
signed decimal integer.
static int parseInt(String s, int radix)
Parses the string argument as a
signed integer in the radix specified by the
second argument.
short shortValue()
Returns the value of this Integer as
a short.
static String toBinaryString(int i)
Returns a string representation of
the integer argument as an unsigned integer
in base 2.
static String toHexString(int i)
Returns a string representation of
the integer argument as an unsigned integer
in base 16.

14 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


static String toOctalString(int i)
Returns a string representation of
the integer argument as an unsigned integer
in base 8.
String toString()
Returns a String object representing
this Integer's value.
static String toString(int i)
Returns a String object representing
the specified integer.
static String toString(int i, int radix)
Returns a string representation of
the first argument in the radix specified by
the second argument.
static Integer valueOf(String s)
Returns an Integer object holding
the value of the specified String.
static Integer valueOf(String s, int radix)
Returns an Integer object holding
the value extracted from the specified String
when parsed with the radix given by the sec-
ond argument.

Class Float

La clase Float cubre un valor del tipo de


dato primitivo float dentro de un objeto.

Además, esta clase proporciona varios mé-


todos para convertir un float a String y
un String a float, así como otras constan-
tes y métodos útiles cuando tratan con un
float.

A continuación se tiene algunos atributos


y métodos principales de la clase Float2:
Atributos
static float MAX_VALUE
A constant holding the largest posi-
tive finite value of type float.
static float MIN_VALUE
A constant holding the smallest posi-

2
Fuente: HELP JDK 2 Ver 1.4 (Idioma Original)
Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 15
tive nonzero value of type float.
static float NaN
A constant holding a Not-a-Number
(NaN) value of type float.
static float NEGATIVE_INFINITY
A constant holding the negative in-
finity of type float.
static float POSITIVE_INFINITY
A constant holding the positive in-
finity of type float.
static Class TYPE
The Class instance representing the
primitive type float.

Constructores
Float(double value)
Constructs a newly allocated Float object that
represents the argument converted to type float.
Float(float value)
Constructs a newly allocated Float object that
represents the primitive float argument.
Float(String s)
Constructs a newly allocated Float object that
represents the floating-point value of type float repre-
sented by the string.

Métodos
byte byteValue()
Returns the value of this Float as a
byte (by casting to a byte).
static int compare(float f1, float f2)
Compares the two specified float
values.
int compareTo(Float anotherFloat)
Compares two Float objects numeri-
cally.
int compareTo(Object o)
Compares this Float object to an-
other object.
double doubleValue()
16 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
Returns the double value of this
Float object.
boolean equals(Object obj)
Compares this object against the
specified object.
static int floatToIntBits(float value)
Returns a representation of the
specified floating-point value according to
the IEEE 754 floating-point "single format"
bit layout.
static int floatToRawIntBits(float value)
Returns a representation of the
specified floating-point value according to
the IEEE 754 floating-point "single format"
bit layout, preserving Not-a-Number (NaN)
values.
float floatValue()
Returns the float value of this Float
object.
int hashCode()
Returns a hash code for this Float
object.
static float intBitsToFloat(int bits)
Returns the float value correspond-
ing to a given bit represention.
int intValue()
Returns the value of this Float as
an int (by casting to type int).
boolean isInfinite()
Returns true if this Float value is
infinitely large in magnitude, false other-
wise.
static boolean isInfinite(float v)
Returns true if the specified number
is infinitely large in magnitude, false other-
wise.
boolean isNaN()
Returns true if this Float value is a
Not-a-Number (NaN), false otherwise.
static boolean isNaN(float v)
Returns true if the specified number
is a Not-a-Number (NaN) value, false other-
wise.
long longValue()

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 17


Returns value of this Float as a long
(by casting to type long).
static float parseFloat(String s)
Returns a new float initialized to
the value represented by the specified String,
as performed by the valueOf method of class
Float.
short shortValue()
Returns the value of this Float as a
short (by casting to a short).
String toString()
Returns a string representation of
this Float object.
static String toString(float f)
Returns a string representation of
the float argument.
static Float valueOf(String s)
Returns a Float object holding the
float value represented by the argument string
s.

Ejemplo( 3): Programa que lee y visualiza


un entero y un float.
//archivo: lecturanumeros.java

import java.io.*;
//import java.lang.*;

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

{
// Definir un flujo de caracteres de entrada: flujoE
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader flujoE = new BufferedReader(isr);

String sdato; // variable para almacenar una


// línea de texto
int nume; //variable que almacena un número
//entero
float numf; //variable que almacena un número
//float

// lectura e impresion de un numero entero


System.out.print("Introduzca un numero entero: ");
18 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
sdato = flujoE.readLine(); // leer una línea de
// texto

nume=Integer.parseInt(sdato);//convierte cadena a
// entero
nume=nume+5;
System.out.println("el numero + 5 es : "+nume);

// lectura e impresion de un numero float


System.out.print("Introduzca un numero real: ");
sdato = flujoE.readLine(); // leer una línea de
//texto

numf=Float.parseFloat(sdato);//convierte cadena a
//float
numf=numf+5;
System.out.println("el numero + 5 es : "+numf);

}
}

La salida del programa es:

Ejemplo ( 4): Programa que calcula el área


de un triángulo.
//archivo: operarit.java

import java.io.*;

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

{
// Definir un flujo de caracteres de entrada: flujoE
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader flujoE = new BufferedReader(isr);

String sdato; // variable para almacenar una


//línea de texto

float b,h; //base y altura


float area;
System.out.print("Introduzca base: ");
sdato = flujoE.readLine(); // leer una línea de
Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 19
// texto
b=Float.parseFloat(sdato);//convierte cadena a
//float
System.out.print("Introduzca altura: ");
sdato = flujoE.readLine(); // leer una línea de
//texto
h=Float.parseFloat(sdato);//convierte cadena a
//float

//calcula el area del triangulo


area=b*h/2;
System.out.println("el area del triangulo es : "+area);
}
}

La salida del programa es:

1.3. ¿QUÉ ES LA PROGRAMACIÓN ORIENTADA A


OBJETOS?
El corazón de la programación orientada a objetos
(POO) es el objeto. Un objeto es un tipo de datos
con estructura y estado. Cada objeto tiene defini-
da. Operaciones que pueden acceder a ese estado o
manipularlo. En Java los objetos se distinguen de
los valores de los tipos primitivos, pero ésta es
más bien una característica de Java que de la pro-
gramación orientada a objetos. Además de ejecutar
acciones generales, podemos hacer lo siguiente:

• Crear nuevos objetos, posiblemente con un va-


lor inicial.

• Copiar o comprobar la igualdad.

• Realizar E/S sobre esos objetos.

20 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


También vimos el objeto como una unidad atómica que
el usuario no debería pretender diseccionar. La ma-
yoría de nosotros ni siquiera pensaría en jugar con
los bits que representan a un número en coma flo-
tante, y consideraríamos completamente ridículo el
intentar incrementar nosotros mismos un número en
coma flotante alterando su representación interna.

El principio de atomicidad se conoce como oculta-


miento de la información. El usuario no tiene acce-
so directo a las panes del objeto o a su implemen-
tación; solamente se puede acceder a ellas de forma
indirecta a través de métodos proporcionados junto
con el objeto. Podemos pensar que cada objeto viene
con el aviso “No abrir - partes no utilizables por
el usuario”. En la vida real, la mayoría de la gen-
te que intenta arreglar las cosas a pesar de tales
avisos, termina produciendo más perjuicio que bene-
ficio. En este sentido, la programación imita al
mundo real. El agrupamiento de datos y las opera-
ciones que se aplican sobre ellos, forman un agre-
gado, mientras que el ocultamiento de los detalles
del agregado, se conoce como encapsulación.

Un objetivo importante de la programación orientada


a objetos es soportar la reutilización de código.
Al igual que los ingenieros usan las misma compo-
nentes repetidamente en sus diseños los programado-
res deberían ser capaces de reutilizar objetos en
lugar de implementarlos repetidamente. Cuando tene-
mos una implementación del objeto exacto que nece-
sitamos usar, la reutilización es simple. El pro-
blema está en utilizar un objeto disponible cuando
no es exactamente el que se necesita sino solamente
uno muy parecido.

Los lenguajes orientados a objetos proporcionan va-


rios, mecanismos para satisfacer este objetivo. Uno
es el uso del código genérico. Si la implementación
es idéntica independientemente del tipo de los ob-
jetos sobre los que se aplica, no hay necesidad de
rescribir completamente el código: en lugar de
ello, se escribe el código genéricamente, de forma
que funcione para cualquier tipo. Por ejemplo, la
lógica usada para ordenar un vector de objetos es
independiente del tipo de los objetos que se están
ordenando, de modo que se podría usar un algoritmo
genérico.

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 21


El mecanismo de herencia nos permite extender la
funcionalidad de un objeto. En otras palabras, po-
demos crear tipos nuevos con las propiedades de los
tipos originales restringidos (o extendidos). La
herencia nos permite avanzar un largo trecho hacia
el objetivo deseado de reutilización de código.

Otro principio importante de la programación orien-


tada a objetos es el polimorfismo. Un tipo referen-
cia polimórfico puede referenciar objetos de varios
tipos diferentes. Cuando se aplican métodos al tipo
polimórfico, se selecciona automáticamente la ope-
ración apropiada para el objeto referenciado en ese
momento. En Java, esto se implementa como parte de
la herencia. El polimorfismo nos permite implemen-
tar clases que comparten una lógica común. El uso
de la herencia para crear estas jerarquías distin-
gue la programación orientada a objetos de la más
simple programación basada en objetos. En Java.
los algoritmos genéricos se implementan como parte
de la herencia.

Un objeto en Java es una instancia de una clase.


Una clase es similar a una estructura en C o un re-
gistro en Pascal o Ada. Excepto por el hecho de que
hay dos mejoras importantes. En primer lugar, las
componentes pueden ser funciones o datos, las cua-
les se conocen respectivamente por métodos y atri-
butos. En segundo lugar. se puede restringir la vi-
sibilidad de dichas componentes. Puesto que los mé-
todos que manipulan el estado del objeto son compo-
nentes de la clase, se accede a ellos mediante el
operador punto, al igual que a los atributos. En la
terminología de la programación orientada a obje-
tos, cuando hacemos una llamada a un método, esta-
mos pasando un mensaje al objeto.

1.4. UN EJEMPLO SENCILLO DE LA POO


Recuerde que cuando está diseñando una clase, es
importante ser capaz de ocultar los detalles inter-
nos al usuario de la clase. Esto se consigue de dos
formas. En primer lugar, la clase puede definir su
funcionalidad mediante componentes de la clase,
llamadas métodos. Algunos de estos métodos descri-
ben cómo se crea e inicializa una instancia de la
22 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
estructura, otros cómo se realiza las comprobacio-
nes de igualdad o cómo se lleva a cabo la salida.
Otras funciones serían específicas a la estructura
particular. La idea es que los atributos internos
que representan el estado del objeto no deberían
ser manipulados directamente por el usuario de la
clase, sino solamente a través de los métodos. Esta
idea se puede reforzar ocultando componentes al
usuario. Para hacer esto podemos especificar que se
almacenen en una sección privada. El compilador
hará cumplir la regla que convierte a las componen-
tes de la sección privada en inaccesibles para el
usuario del objeto. En general todas las componen-
tes de datos deberían ser privadas.

En la siguiente programa se muestra una declaración


de clase para un objeto celdaEntero. La declaración
consta de dos partes: una pública y otra privada.
La sección pública representa la porción visible al
usuario del objeto. Puesto que esperamos ocultar
los datos, en general solamente deberían aparecer
métodos y constantes en la sección pública. En
nuestro ejemplo, tenemos métodos que leen y escri-
ben en el objeto celdaEntero. La sección privada
contiene los datos: ésta es invisible para el usua-
rio del objeto. Se debe acceder al atributo valo-
rAlmacenado a través de las rutinas públicas leer y
escribir; main no puede acceder directamente a
ella.
public class IntCell{
/**
* Retorna el valor almacenado
* @return valor almacenado
*/
public int read( ){
return storedValue;
}

/**
* Valor a almacenar
* @param x numero a almacenar
*/
public void write( int x ){
storedValue = x;
}

private int storedValue;


}
La clase TestCeldaEntero muestra cómo se usan los
objetos de la clase celdaEntero.
public class TestIntCell{
public static void main( String [] args ){
IntCell m = new IntCell( );

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 23


m.write( 5 );
System.out.println("Contenido de la celda: " + m.read( ) );
}
}
Puesto que leer y escribir son componentes de la
clase celdaEntero, se puede acceder a ellas usando
el operador punto. También se podría acceder al
atributo valorAlmacenado usando el operador punto,
pero debido a que es privada, el acceso sería ile-
gal.

A continuación resumimos la terminología. La clase


define componentes, que pueden ser atributos (da-
tos) o métodos (funciones). Los métodos pueden ac-
tuar sobre los atributos y pueden llamar a otros
métodos. El modificador de visibilidad public sig-
nifica que la componente es accesible para cual-
quiera a través del operador punto. El modificador
de visibilidad private significa que la componente
solamente es accesible a través de otros métodos de
esa clase. Si no hay modificador de visibilidad,
tenemos acceso amistoso. Hay un cuarto modificador
conocido como protected.

1.5. MÉTODOS BÁSICOS


Algunos métodos son comunes a todas las clases. En
esta sección se estudia los métodos modificadores y
de acceso, y tres métodos especiales: los construc-
tores, toString y equals. También se habla de los
métodos estáticos, uno de los cuales es main.

1.5.1. CONSTRUCTORES

Como se ha mencionado anteriormente, una


propiedad básica de los objetos es que se
pueden definir, posiblemente con un valor
inicial. En Java, los métodos que contro-
lan cómo se crea e inicializa un objeto
reciben el nombre de constructores. Gra-
cias a la sobrecarga, en una clase se pue-
de definir diversos constructores.

Si no se proporciona ningún constructor,


como en el caso de la clase CeldaEntero,
se genera un constructor por defecto que
24 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
inicializa cada atributo usando los co-
rrespondientes valores por defecto. Esto
significa que los atributos de tipo primi-
tivo se inicializan a cero y los tipos re-
ferencia se inicializan a la referencia
null. Por tanto, en el caso de celdaEnte-
ro, la componente valorAlmacenado es 0.

Para escribir un constructor, proporciona-


mos un método con el mismo nombre que la
clase y sin resultado. En la clase Date
(incluido mas adelante) hay dos construc-
tores:
// Constructor con cero parámetros
public Date(){
month = 1;
day = 1;
year = 1998;
}

// Constructor con tres parámeteros


public Date(int theMonth, int theDay, int theYear){
month = theMonth;
day = theDay;
year = theYear;
}

Usando estos constructores, podemos cons-


truir objetos Date de las dos formas si-
guientes:
Date f1=new Date();
Date f2=new Date(15,4,1998);

Una vez que se escribe un constructor, ya


no se utiliza un constructor por defecto
sin parámetros. Si desea volver a contar
con él, tiene que escribirlo explícitamen-
te. Así, el primer constructor es obliga-
torio para poder construir el objeto que
referencia f1.

1.5.2. MÉTODOS MODIFICADORES Y DE ACCESO

Los atributos de una clase se declaran


normalmente como privados. En consecuen-
cia, las rutinas que no pertenecen a la
clase no pueden acceder directamente
ellos. Sin embargo, algunas veces nos gus-
taría examinar el valor de un atributo, e
incluso podríamos querer cambiarlo direc-
tamente.

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 25


Una alternativa para hacer esto es decla-
rar los atributos como públicos. Ésta es,
sin embargo, una elección pobre, pues vio-
la el principio de ocultamiento de infor-
mación. En su lugar podemos proporcionar
métodos para examinar y cambiar cada atri-
buto. Un método que examina pero no cambia
el estado de un objeto es un método de ac-
ceso. Un método que cambia el estado es un
modificador (porque modifica el estado del
objeto).

Casos particulares de métodos de acceso y


modificadores trabajan solamente sobre un
atributo. Estos métodos de acceso usual-
mente tendrán nombres que empiezan por ob-
tener, como obtenerMes, mientras que los
modificadores tendrán nombres que comien-
zan por cambiar, como cambiarMes.

La ventaja de usar un modificador es que


de esta forma podemos asegurar que los
cambios realizados en el estado del objeto
son consistentes. Así, un modificador que
cambie el atributo day en un objeto Date
nos garantizará que solamente se generan
fechas legales.

1.5.3. SALIDA Y TOSTRING

Normalmente queremos mostrar el estado de


un objeto usando print. Esto se consigue
definiendo un método toString en la clase.
Dicho método devuelve un valor de tipo
String apto para producir una salida. La
clase Date muestra una implementación bá-
sica del método toString para dicha clase.

1.5.4. MÉTODOS static

Un método estático es un método que no ne-


cesita un objeto que lo controle. El méto-
do estático más común es main. En las cla-
ses String, Integer y Math se puede encon-
trar otros métodos estáticos. Algunos
26 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
ejemplos son String.valueOf, Inte-
ger.parseInt, Math.sin y Math.max. El ac-
ceso a los métodos estáticos utiliza las
mismas reglas de visibilidad que los atri-
butos estáticos.

Recuerde que algunos atributos de la clase


usan el modificador static. Usándolo, en
conjunción con la palabra final, obtenemos
las constantes. Sin la palabra final, te-
nemos atributos estáticos, que tienen otro
significado distinto, estudiado mas ade-
lante.

1.5.5. MÉTODO main

Cuando se usa el comando java para ejecu-


tar el intérprete, se llama al método main
de la clase del fichero referenciado por
el comando. Por tanto, cada clase puede
tener su propia función main sin ningún
problema. Sin embargo, aunque así se puede
probar la funcionalidad, colocar main en
una clase proporciona a esta función más
visibilidad que la que estaría permitida
en general. Por tanto, llamadas de main a
métodos no públicos tendrán éxito en la
prueba, aunque serán ilegales en un entor-
no más general.
1.6. EJEMPLOS DEL USO DE CLASES
Ejemplo (5): Clase cuenta (Versión 1). Muestra el
uso de las funciones miembro con parámetros, por lo
que se debe pasar valores a estas funciones.

// Archivo: Cuenta.java

import java.lang.Math;
class Cuenta
{ private float saldo;

public void asignar(float s)


{ saldo=s;
}

public void escribir()


{ System.out.println("El saldo es: "+saldo);
}

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 27


public void deposito(float d)
{ saldo=saldo+d;
}

public void retiro(float r)


{ // no se verifica si el saldo es mayor que el retiro
saldo=saldo-r;
}
}
// Archivo CuentaAppl.java

import java.io.*;

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

{
// Definir un flujo de caracteres de entrada: flujoE
InputStreamReader isr = new
InputStreamReader(System.in);
BufferedReader flujoE = new BufferedReader(isr);

String sdato; // variable para almacenar una línea de


texto

float sal,dep,ret; //saldo inicial, depósito y retiro

//Creación de un objeto Cuenta: c


Cuenta c=new Cuenta();

//lectura de datos
System.out.print("Introduzca saldo inicial: ");
sdato = flujoE.readLine(); // leer una línea de texto
sal=Float.parseFloat(sdato);//convierte cadena a float

c.asignar(sal);
c.escribir();

System.out.print("Introduzca deposito: ");


sdato = flujoE.readLine(); // leer una línea de texto
dep=Float.parseFloat(sdato);//convierte cadena a float

c.deposito(dep);
c.escribir();

System.out.print("Introduzca retiro: ");


sdato = flujoE.readLine(); // leer una línea de texto
ret=Float.parseFloat(sdato);//convierte cadena a float

c.retiro(ret);
c.escribir();
}
28 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
}

Ejemplo (6): Clase cuenta (Versión 2). Muestra el


uso de las funciones miembro sin parámetros, por lo
que se debe leer los valores desde la misma fun-
ción. Observe el uso de throws IOException en las
funciones.

// Archivo: Cuenta1.java

import java.io.*;

class Cuenta1
{ private float saldo;

public void asignar() throws IOException


{
// Definir un flujo de caracteres de entrada: flujoE
InputStreamReader isr = new
InputStreamReader(System.in);
BufferedReader flujoE = new BufferedReader(isr);

String sdato; // variable para almacenar una línea de


texto
//lectura de datos
System.out.print("Introduzca saldo inicial: ");
sdato = flujoE.readLine(); // leer una línea de texto
saldo=Float.parseFloat(sdato);//convierte cadena a float
}

public void escribir()


{
System.out.println("El saldo es: "+saldo);
}

public void deposito() throws IOException


{
// Definir un flujo de caracteres de entrada: flujoE
InputStreamReader isr = new
InputStreamReader(System.in);
BufferedReader flujoE = new BufferedReader(isr);

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 29


String sdato; // variable para almacenar una línea de
texto
float dep;

System.out.print("Introduzca deposito: ");


sdato = flujoE.readLine(); // leer una línea de texto
dep=Float.parseFloat(sdato);//convierte cadena a float
saldo=saldo+dep;
}

public void retiro() throws IOException


{
// Definir un flujo de caracteres de entrada: flujoE
InputStreamReader isr = new
InputStreamReader(System.in);
BufferedReader flujoE = new BufferedReader(isr);
String sdato; // variable para almacenar una línea de
texto
float ret;

System.out.print("Introduzca retiro: ");


sdato = flujoE.readLine(); // leer una línea de texto
ret=Float.parseFloat(sdato);//convierte cadena a float

// no se verifica si el saldo es mayor que el retiro


saldo=saldo-ret;
}
}

// Archivo Cuenta1Appl.java

import java.io.*;
class Cuenta1Appl
{
public static void main (String[] args)
throws IOException
{
//Creación de un objeto Cuenta1
Cuenta1 c=new Cuenta1();

c.asignar();
c.escribir();

c.deposito();
c.escribir();

c.retiro();
c.escribir();
}
}

30 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


Ejemplo (7): Clase cuenta (Versión 3). Muestra el
uso de las funciones miembro sin parámetros, por lo
que se debe leer los valores desde la misma fun-
ción. Observe el uso de try. . .catch en lugar de
throws IOException en las funciones.

// Archivo: Cuenta2.java

import java.io.*;

class Cuenta2
{ private float saldo;

public void asignar()


{ try
{
// Definir un flujo de caracteres de entrada: flujoE
InputStreamReader isr = new
InputStreamReader(System.in);
BufferedReader flujoE = new BufferedReader(isr);

String sdato; // variable para almacenar una línea de


//texto
//lectura de datos
System.out.print("Introduzca saldo inicial: ");
sdato = flujoE.readLine(); // leer una línea de texto
saldo=Float.parseFloat(sdato);//convierte cadena a
float
}
catch (IOException ignorada)
{}
}

public void escribir()


{
System.out.println("El saldo es: "+saldo);
}

public void deposito()


{ try
{
// Definir un flujo de caracteres de entrada: flujoE
InputStreamReader isr = new
InputStreamReader(System.in);
Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 31
BufferedReader flujoE = new BufferedReader(isr);
String sdato; // variable para almacenar una línea de
//texto
float dep;

System.out.print("Introduzca deposito: ");


sdato = flujoE.readLine(); // leer una línea de texto
dep=Float.parseFloat(sdato);//convierte cadena a float
saldo=saldo+dep;
}
catch (IOException ignorada)
{}
}

public void retiro()


{ try
{
// Definir un flujo de caracteres de entrada: flujoE
InputStreamReader isr = new
InputStreamReader(System.in);
BufferedReader flujoE = new BufferedReader(isr);
String sdato; // variable para almacenar una línea de
//texto
float ret;

System.out.print("Introduzca retiro: ");


sdato = flujoE.readLine(); // leer una línea de texto
ret=Float.parseFloat(sdato);//convierte cadena a float

// no se verifica si el saldo es mayor que el retiro


saldo=saldo-ret;
}
catch (IOException ignorada)
{}
}
}

// Archivo Cuenta2Appl.java

import java.io.*;
class Cuenta2Appl
{
public static void main (String[] args)

{
//Creación de un objeto Cuenta2: c
Cuenta2 c=new Cuenta2();

c.asignar();
c.escribir();

c.deposito();
c.escribir();

32 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


c.retiro();
c.escribir();
}
}

Ejemplo (8): Uso de la clase complejo.

// Archivo: Complejo.java
import java.lang.Math;

class Complejo
{ private float real;
private float imaginario;

Complejo()
{ real=0;
imaginario=0;
}

public void asignar(float r, float i)


{ real=r;
imaginario=i;
}

public void escribir()


{
System.out.println("El complejo es: "+real+" +
"+imaginario+" i");
}

public float absoluto(Complejo c)


{ float va;
va=c.real*c.real+c.imaginario*c.imaginario;
va=(float) Math.sqrt(va);
return va;
}
}

// Archivo ComplejoAppl.java

Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno 33


import java.io.*;

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

{
// Definir un flujo de caracteres de entrada: flujoE
InputStreamReader isr = new
InputStreamReader(System.in);
BufferedReader flujoE = new BufferedReader(isr);

String sdato; // variable para almacenar una línea de


texto

float re,im; //real, imaginario


float valabs;//valor absoluto

//Creación de un objeto complejo: c1


Complejo c1=new Complejo();

//lectura de datos
System.out.print("Introduzca parte real: ");
sdato = flujoE.readLine(); // leer una línea de texto
re=Float.parseFloat(sdato);//convierte cadena a float
System.out.print("Introduzca parte imaginaria: ");
sdato = flujoE.readLine(); // leer una línea de texto
im=Float.parseFloat(sdato);//convierte cadena a float

// uso del objeto c1


c1.asignar(re,im);
c1.escribir();
valabs=c1.absoluto(c1);
System.out.println("El valor absoluto es : "+valabs);

}
}

34 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


CAPITULO DOS

TIPOS DE DATOS ABSTRACTOS (TDA)

2.1. TIPO DE DATOS


Llamaremos Tipo de Datos de una variable al conjun-
to de valores que dicha variable puede asumir.

El tipo de una variable en un programa para un len-


guaje de alto nivel requiere de una declaración de
tipo la cual tiene 2 objetivos:

ƒ Separar el espacio de memoria que los valores


de la variable requieren. Por ejemplo 1 byte
para un carácter, 2 bytes para un entero, 4
bytes para un real, etc.

ƒ Interpretar correctamente el contenido de la


memoria a la variable que accede.

2.2. TIPOS DE DATOS ABSTRACTOS (TDA)


Un tipo de datos abstracto (TDA) consiste en:

ƒ Un modelo matemático y

ƒ Un conjunto de operaciones definidas en el mo-


delo

ESTRUCTURA DE DATOS EN JAVA 35


2.3. IMPLEMENTACIÓN DE TIPOS DE DATOS
ABSTRACTOS
Una implementación de un TDA es la representación
(usando estructuras de datos) y la traducción en
sentencias de un lenguaje de programación de:

ƒ La declaración de que una o más variables son


de aquel tipo y

ƒ Una función para cada una de las operaciones


del TDA.

EJEMPLO UNO
Ningún computador puede almacenar exactamente al
número racional 1/3, por ejemplo. Sin embargo puede
ser necesario operar sólo en aritmética racional.

Es posible hacer esto, para lo cual primero defini-


mos el TDA RACIONAL:

El concepto matemático es el de par ordenado de nú-


meros enteros:

p
( p, q ) para , q≠0
q

Operaciones:

Igualdad de números racionales


(p,q) = (p’, q’) ⇔ p q’ = p’ q

Adición en los racionales


(p , q) + (p’ , q’) = (p q’ + p’q , q q’)

Multiplicación de racionales
(p , q) . (p’ , q’) = (p p’ , q q’)

36 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


IMPLEMENTACIÓN USANDO ARREGLOS

// La clase Leer debe estar en alguna carpeta de


// las especificadas por la variable de
// entorno CLASSPATH.

public class CRacional{


static int max=2;
int[] rational=new int[max];

CRacional(){
rational[0]=0;
rational[1]=0;
}

public void leer(){


int i;

for (i=0;i<max;i++){
System.out.print("ingrese elemento "+(i+1)+":");
rational[i]=Leer.datoInt();
}
}

public String toString(){


if (rational[0]==rational[1])
return ""+rational[0]/rational[1];
else if (rational[1]==1)
return ""+rational[0];
else
return rational[0]+"/"+rational[1];
}

public CRacional sumar(CRacional y){


CRacional su=new CRacional();

su.rational[0]=rational[0]*y.rational[1]+rational[1]*y.rational[0];
su.rational[1]=rational[1]*y.rational[1];
su.simplificar();
return su;
}

public CRacional multiplicar(CRacional y){


CRacional mu=new CRacional();

mu.rational[0]=rational[0]*y.rational[0];
mu.rational[1]=rational[1]*y.rational[1];
mu.simplificar();
return mu;
}

public void simplificar(){


int a,b,res;

a=rational[0];
b=rational[1];
while(b!=0){
res=a % b;
a=b;
b=res;
}
rational[0]/=a;
rational[1]/=a;
}

// La clase Leer debe estar en alguna carpeta de las especificadas


// por la variable de entorno CLASSPATH.

ESTRUCTURA DE DATOS EN JAVA 37


public class CRacionalApp{
public static void main(String[] args){
CRacional a=new CRacional();
CRacional b=new CRacional();
CRacional s=new CRacional();
CRacional m=new CRacional();

System.out.println("ingrese primer racional");


a.leer();
System.out.println("ingrese segundo racional");
b.leer();
s=a.sumar(b);
m=a.multiplicar(b);

System.out.println("contenido del 1er racional "+a);


System.out.println("contenido del 2do racional "+b);
System.out.println("contenido de la suma es "+s);
System.out.println("contenido de la multiplicacion es "+m);
}
}

IMPLEMENTACIÓN USANDO ATRIBUTOS

// La clase Leer debe estar en alguna carpeta de las especificadas


// por la variable de entorno CLASSPATH.
public class CRacional{
int num,den;

CRacional(){
num=0;
den=0;
}

public void leer(){


System.out.print("Numerador : ");
num=Leer.datoInt();
System.out.print("Denominador : ");
den=Leer.datoInt();

public String toString(){


if (num==den)
return ""+num/den;
else if (den==1)
return ""+num;
else
return num+"/"+den;
}

public CRacional sumar(CRacional y){


CRacional su=new CRacional();

su.num=num*y.den+den*y.num;
su.den=den*y.den;
su.simplificar();
return su;
}

public CRacional multiplicar(CRacional y){


CRacional mu=new CRacional();

mu.num=num*y.num;
mu.den=den*y.den;
mu.simplificar();
38 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
return mu;
}

public void simplificar(){


int a,b,res;

a=num;
b=den;
while(b!=0){
res=a % b;
a=b;
b=res;
}
num/=a;
den/=a;
}
}

// La clase Leer debe estar en alguna carpeta de las especificadas


// por la variable de entorno CLASSPATH.
public class CRacionalApp{

public static void main(String[] args){


CRacional a=new CRacional();
CRacional b=new CRacional();
CRacional s=new CRacional();
CRacional m=new CRacional();

System.out.println("ingrese primer racional");


a.leer();
System.out.println("ingrese segundo racional");
b.leer();
s=a.sumar(b);
m=a.multiplicar(b);

System.out.println("contenido del 1er racional "+a);


System.out.println("contenido del 2do racional "+b);
System.out.println("contenido de la suma es "+s);
System.out.println("contenido de la multiplicacion es "+m);
}
}

EJEMPLO DOS
Se tiene un TDA enterazo que guarda un numero ente-
ro, cada cifra es un elemento de un arreglo de en-
teros. Se pide desarrollar un programa para las
operaciones suma y resta.
// La clase Leer debe estar en alguna carpeta de las especificadas
// por la variable de entorno CLASSPATH.
public class CEnterazo{
static int max=4;
int[] enterazo=new int[max];

CEnterazo(){
for(int i=0;i<max;i++) enterazo[i]=0;
}

public void leer_numero(){


int i;

System.out.println("Ingrese cifra por cifra del numero ("+(max-1)+"


digitos) :");

ESTRUCTURA DE DATOS EN JAVA 39


for(i=1;i<max;i++) enterazo[i]=Leer.datoInt();
}

public String toString(){


String x;
int i;

x="";
for(i=0;i<max;i++) x=x+enterazo[i];
return x;
}
//halla la resta de dos enteros si el primero
//es mayor que el segundo

public CEnterazo resta(CEnterazo y){


int i;
CEnterazo re=new CEnterazo();

for(i=max-1;i>=0;i--)
if (enterazo[i]>=y.enterazo[i])
re.enterazo[i]=enterazo[i]-y.enterazo[i];
else{
re.enterazo[i]=(enterazo[i]+10)-y.enterazo[i];
y.enterazo[i-1]=y.enterazo[i-1]+1;
}//fin de else (x[i]>y[i])
return re;
}

public CEnterazo suma(CEnterazo y){


int i,a=0;
CEnterazo su=new CEnterazo();

for(i=max-1;i>=0;i--){
su.enterazo[i]=enterazo[i]+y.enterazo[i]+a;
if (su.enterazo[i]>=10){
a=su.enterazo[i]/10;//calcula acarreo
su.enterazo[i]=su.enterazo[i]%10;//halla lo que se queda
}
else a=0;
}
return su;
}
}

// La clase Leer debe estar en alguna carpeta de las especificadas


// por la variable de entorno CLASSPATH.
public class CEnterazoApp{

public static void main(String[] args){


CEnterazo n1=new CEnterazo();
CEnterazo n2=new CEnterazo();
CEnterazo r=new CEnterazo();

n1.leer_numero();
System.out.println("El primer numero es :"+n1);

n2.leer_numero();
System.out.println("El segundo numero es :"+n2);

r=n1.suma(n2);
System.out.println("La suma es :"+r);

r=n1.resta(n2);
System.out.println("La resta es :"+r);
}
}

40 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


EJEMPLO TRES
Se tiene un TDA binario que guarda un número en ba-
se 2, cada cifra es un elemento de un arreglo de
enteros. Se pide desarrollar un programa para con-
vertir el número a base 16.
//archivo: CBinario.java
class CBinario
{
static int max=8;
int [] binario=new int [max];

public void leer_numero()


{
int i;
System.out.println("Ingrese cifra por cifra del numero ("+(max)+"
digitos) :");
for(i=0;i<max;i++)
do
{ System.out.print((i+1)+" cifra: ");
binario[i]=Leer.datoInt();
} while(binario[i]!=0 && binario[i]!=1);

public String toString()


{
String x;
int i;

x="";
for(i=0;i<max;i++) x=x+binario[i];
return x;
}

public String base16()


{
String x="";
int [] n16=new int [2];
int i,n10=0,base=16;
//convertir a base 10
for(i=0;i<max;i++)
n10=n10+ binario[i]* (int) Math.pow(2,(max-1)-i);
//convertir a base 16
int j=1;
while(n10>0)
{
n16[j]=n10%base;
n10=n10/base;
j--;
}
for(i=0;i<n16.length;i++)
switch(n16[i])
{
case 10: x=x+"A";break;
case 11: x=x+"B";break;
case 12: x=x+"C";break;
case 13: x=x+"D";break;
case 14: x=x+"E";break;
case 15: x=x+"F";break;
default : x=x+n16[i];
}

return x;
}
}
ESTRUCTURA DE DATOS EN JAVA 41
//archivo: CBinarioApp.java
// La clase Leer debe estar en alguna carpeta de las especificadas
// por la variable de entorno CLASSPATH.
public class CBinarioApp{

public static void main(String[] args)


{
CBinario n1=new CBinario();

n1.leer_numero();
System.out.println("El numero es :"+n1);

System.out.println("El numero en base 16 es :"+n1.base16());


}
}

EJEMPLO CUATRO
Implementación de la operación diferencia de un TDA
conjunto de 5 elementos enteros cada conjunto. El
conjunto se representa por un arreglo de enteros,
el conjunto diferencia si tiene menos de 5 elemen-
tos es completada con ceros.
// La clase Leer debe estar en alguna carpeta de las especificadas
// por la variable de entorno CLASSPATH.

public class CConjunto{


static int N=5;
int[] Conjunto=new int[N];

CConjunto(){
for(int i=0;i<N;i++) Conjunto[i]=0;
}

CConjunto(int a,int b,int c,int d,int e){

Conjunto[0]=a;
Conjunto[1]=b;
Conjunto[2]=c;
Conjunto[3]=d;
Conjunto[4]=e;
}

public CConjunto diferencia(CConjunto b){

42 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


int i, j=0;//j indice de d
int v;//elemento a buscar

CConjunto d=new CConjunto();

for(i=0;i<N;i++){
v=Conjunto[i];//toma elemento de a para buscar en b
if(b.busca(v)==-1)//no existe elemento en b
{
d.Conjunto[j]=Conjunto[i];
j++;

}
}
//agrega los ceros a d
for(i=j;i<N;i++) d.Conjunto[i]=0;
return d;
}

public int busca(int v){


int i=0;

while(i<N-1 && Conjunto[i]!=v) i++;


if(Conjunto[i]==v) return i; //si encuentra retorna el índice
else return -1; //si no encuentra retorna -1
}

public String toString(){


String x;
int i;

x="";
for(i=0;i<N;i++)
if (Conjunto[i]!=0) x=x+Conjunto[i]+" ";
return x;
}
}

// La clase Leer debe estar en alguna carpeta de las especificadas


// por la variable de entorno CLASSPATH.

public class CConjuntoApp{

public static void main(String[] args){


CConjunto a=new CConjunto(6,7,5,4,2);
CConjunto b=new CConjunto(8,3,4,9,6);
CConjunto d=new CConjunto();

System.out.println("Primer conjunto : "+a);


System.out.println("Segundo conjunto: "+b);
d=a.diferencia(b);
System.out.println("Diferencia : "+d);
}
}

Auto evaluación formativa


Escriba programas que encuentren la solución a los si-
guientes problemas:

PROBLEMA UNO

ESTRUCTURA DE DATOS EN JAVA 43


Escriba un programa que permita operar con números
complejos a+bi, en donde:

abs(a + bi) Î sqrt(a2 + b2)

(a+bi) + (c+di) Î (a + c) + (b + d)i

(a+bi) * (c+di) Î (a*c – b*d) + (a*d +


b*c)i

-(a + bi) Î (-a) + (-b)i

PROBLEMA DOS
Escriba un programa que permita operar con números
complejos definido en su forma polar, en donde:

⎛b⎞
a + bi = r (cosθ + isenθ ) r = a2 + b2 θ = arctan⎜ ⎟
⎝a⎠

Operaciones

Suma:

r1 (cosθ 1 + i sen θ 1 ) + r2 (cosθ 2 + i sen θ 2 ) =


(r1 cosθ 1 + r2 cosθ 2 ) + i(r1 sen θ 1 + r2 sen θ 2 )

Producto:

r1 (cosθ 1 + i sen θ 1 ) * r2 (cosθ 2 + i sen θ 2 ) =


(r1 * r2 ) * (cos(θ 1 + θ 2 ) + i sen(θ 1 + θ ) )

División:

r1 (cosθ 1 + i sen θ 1 ) r1
= (cos(θ 1 − θ 2 ) + i sen(θ 1 − θ ) )
r2 (cosθ 2 + i sen θ 2 ) r2

44 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


Potencia:

(r (cosθ + i sen θ ) )n = r n (cos(nθ ) + i sen(nθ ))

Raíz (tiene n raíces):

θ + 2kπ θ + 2kπ
n r (cosθ + i sen θ ) = n r (cos( ) + i sen( ))
n n
k = 0,1,2,..., n − 1
π = 3.1416

ESTRUCTURA DE DATOS EN JAVA 45


CAPITULO TRES

LISTAS ENLAZADAS

3.1. LISTAS ENLAZADAS


El concepto matemático es el de lista de elementos
de un conjunto L.

3.1.1. DEFINICIONES:

a) Una lista sobre L es una secuencia de


cero o más elementos de L:
a1, a2, ...., an

b) Si n=0, L no tiene elementos y será


llamada la lista nula o vacía.

c) Si n>=1, L tiene n elementos y diremos


que su longitud es n.

d) a1 es el primer elemento de L y an es
el último elemento de L.

e) Para i= 1, 2, ... , n-1, ai precede a


ai+1

f) Para i= 2, 3, … , n, ai sigue a ai-1


ESTRUCTURA DE DATOS EN JAVA 47
g) El orden en la secuencia determina la
posición de cada elemento.

3.1.2. OPERACIONES BÁSICAS CON UNA LISTA

Suponemos que L es una lista y a continua-


ción se dan algunas operaciones sobre lis-
tas.
Función que convierte a L en la lista vacía o
L.ANULA()
nula.
Función que retorna la posición/dirección del
L.PRIMERO() primer elemento de la lista L, si ésta es no
vacía.
Función que retorna la posición/dirección del
L.LOCALIZA(x) primer elemento de L que es igual a x o de-
vuelve nulo si tal elemento no existe.
Función que elimina el elemento x de la lista
L.SUPRIME(x)
L.
Función que inserta x en la lista L en forma
L.INSERTA(x)
ordenada ascendente.

3.2. IMPLEMENTACIÓN DE LISTAS USANDO


REFERENCIAS A OBJETOS
Ahora definimos el concepto de estructuras dinámi-
cas de datos. Mediante este método, los elementos
de una lista se "enlazan" usando referencias, dando
lugar a la estructura de datos llamada lista enla-
zada. Es decir, las variables pueden crearse y des-
truirse durante la ejecución del programa. Depen-
diendo de como se enlazan los elementos de una lis-
ta, ésta será:

3.3. LISTA LINEAL SIMPLEMENTE ENLAZADA


La lista lineal simplemente enlazada tiene la si-
guiente disposición:

L Nulo
Donde la clase de un nodo es:

Información
Tipo de datos que Una referencia que se utiliza para estable-
se quiere almacenar cer el enlace con el otro nodo de la lista.
en la lista.

48 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


L es un puntero al inicio de la lista (referencia
al primer elemento de la lista) y cada flecha re-
presenta una referencia; además nulo representa el
fin de la lista. La lista enlazada completa se ac-
cesa desde el apuntador externo L. La clase en Java
puede ser:
public class ListaSimple {
int info;
ListaSimple top; // Puntero al Inicio
ListaSimple sig; // Puntero al siguiente
………
}

3.3.1. IMPLEMENTACIÓN DE LA LISTA LINEAL


CON REFERENCIAS
//programa que realiza la implementación del
//TDA lista con referencias.

// Utiliza la clase Leer que debe de estar almacenada


// en la misma carpeta
public class ListaSimple {
int info;
ListaSimple top; // Puntero al Inicio
ListaSimple sig; // Puntero al siguiente

ListaSimple(){
top=sig=null;
}

public void anula(){


top=null;
}

public void inserta(int x){


ListaSimple comienzo, nuevo, p, q;

comienzo=top;
// Crear nuevo dato
nuevo=new ListaSimple();
p=new ListaSimple();
nuevo.info=x;
// Primer dato
if (comienzo==null){
comienzo=nuevo;
nuevo.sig=null;
}
else //valor antes de comienzo
if (x<comienzo.info){
nuevo.sig=comienzo;
comienzo=nuevo;
}
else {
// Nuevo se halla entre p y q luego
// de enlazarlos
q=comienzo;
while (q!=null && (x>=q.info)){
p=q;
q=q.sig;
}
p.sig=nuevo;
nuevo.sig=q;
}
top=comienzo;
}

ESTRUCTURA DE DATOS EN JAVA 49


public void contenido(){
ListaSimple p;

System.out.println("Impresion de la lista");
p=top;
while(p!=null){
System.out.print("\t"+p.info);
p=p.sig;
}
System.out.println();;
}

public void suprime(int val){


ListaSimple q,p;

p=new ListaSimple();

q=top;
if (q==null)
System.out.println("Lista vacia");
else{
while (q!=null && val!=q.info){
p=q;
q=q.sig;
}
if (q==null)
System.out.println("valor no encontrado");
else
if (q==primero())
top=top.sig;
else
p.sig=q.sig;
}
}

public ListaSimple primero(){


return (top);
}

//localiza x en la lista y devuelve la dirección


//donde esta x
public ListaSimple localiza(int x){
ListaSimple p;
boolean encontrado;

encontrado=false;
p=top;
while(p!=null && !encontrado)
if (x==p.info)
encontrado=true;
else
p=p.sig;
if (encontrado)
return p;
else
return null;
}
}

La Clase DemoListaSimple utiliza la clase ListaSim-


ple y muestra sus operaciones:
public class DemoListaSimple{
public static void main(String []args){
ListaSimple vector=new ListaSimple();
ListaSimple p=new ListaSimple();

50 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


ListaSimple L=new ListaSimple();
int x=0,sw,opcion;

sw=1;
do{
System.out.println("\n\n\n\nProcesamiento de una Lista “+”
simplemente enlazada\n");
System.out.println("0. Salir");
System.out.println("1. Anula lista");
System.out.println("2. Suprime el elemento para un valor dado");
System.out.println("3. Inserta un elemento a la lista");
System.out.println("4. Contenido de la lista");
System.out.println("5. Localiza un elemento en la lista");
System.out.print("Opcion ==> ");
opcion=Leer.datoInt();
switch(opcion){
case 0:sw=0;break;
case 1:L.anula();break;
case 2:
System.out.print("Digite valor a suprimir ==> ");
x=Leer.datoInt();
L.suprime(x);
break;
case 3:
System.out.print("Digite valor a insertar ==> ");
x=Leer.datoInt();
L.inserta(x);
break;
case 4:
L.contenido();break;
case 5:
System.out.print("Digite valor a localizar ==> ");
x=Leer.datoInt();
p=L.localiza(x);
if (p==null)
System.out.println("No existe valor");
else
System.out.println("El valor encontrado es "+
p.info);
break;
}
}while(sw==1);
}
}

3.4. UNA LISTA LINEAL DOBLEMENTE ENLAZADA.


Nulo
L
Nulo

Donde la clase de un nodo es:


Tipo de datos que
se quiere almacenar
Información
en la lista.
Referencias que se utilizan para establecer
el enlace con el otro nodo de la lista.

L es un puntero al inicio de la lista (re-


ferencia al primer elemento de la lista)

ESTRUCTURA DE DATOS EN JAVA 51


3.4.1. IMPLEMENTACIÓN DE UNA LA LISTA DO-
BLEMENTE ENLAZADA USANDO REFERENCIAS
public class ListaDoble{
int info;
ListaDoble top; // Puntero al Inicio
ListaDoble bottom; // Puntero al final
ListaDoble ant; // Puntero al anterior
ListaDoble sig; // Puntero al siguiente
public ListaDoble(){
top=bottom=ant=sig=null;
}

public void anula(){


top=bottom=null;
}

public void inserta(int x){


ListaDoble nuevo;

// Crear nuevo dato


nuevo=new ListaDoble();
nuevo.info=x;
// Primer dato
if(top==null){
nuevo.ant=null;
nuevo.sig=null;
top=bottom=nuevo;
}else{
bottom.sig=nuevo;
nuevo.sig=null;
nuevo.ant=bottom;
bottom=nuevo;
}
}

public void ContenidoAvanza(){


ListaDoble p;

System.out.println("Impresion de la lista");
p=top;
if(p!=null){
while (p!=null){
System.out.print(""+p.info+"\t");
p=p.sig;
}
}
System.out.println();
}

public void ContenidoRetrocede(){


ListaDoble p;

System.out.println("Impresión de la lista");
p=bottom;
if(p!=null){
while (p!=null){
System.out.print(""+p.info+"\t");
p=p.ant;
}
}
System.out.println();
}
}

52 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


La Clase DemoListaDoble utiliza la clase ListaDoble
y muestra sus operaciones:
public class DemoListaDoble{
public static void main(String []args){
ListaDoble L=new ListaDoble();
int x=0,sw,opcion;

sw=1;
do{
System.out.println("\n\n\n\nProcesamiento de una lista
doblemente enlazada\n");
System.out.println("0. Salir");
System.out.println("1. Anula lista");
System.out.println("2. Inserta un elemento a la lista");
System.out.println("3. Contenido de la lista: Avance");
System.out.println("4. Contenido de la lista: Retrocede");
System.out.print("Opcion ==> ");
opcion=Leer.datoInt();
switch(opcion){
case 0:sw=0;break;
case 1:L.anula();break;
case 2:
System.out.print("Digite valor a insertar ==> ");
x=Leer.datoInt();
L.inserta(x);
break;
case 3:
L.ContenidoAvanza();break;
case 4:
L.ContenidoRetrocede();break;
}
}while(sw==1);
}
}

3.5. LISTA CIRCULAR SIMPLEMENTE ENLAZADA.

3.5.1. IMPLEMENTACIÓN DE UNA LA LISTA CIR-


CULAR SIMPLEMENTE ENLAZADA USANDO
REFERENCIAS
public class ListaSimpleCirc {
int info;
ListaSimpleCirc top; // Puntero al ultimo
ListaSimpleCirc sig; // Puntero al siguiente

ListaSimpleCirc(){
top=sig=null;
}

public void anula(){


top=null;
}

public void inserta(int x){


ListaSimpleCirc nuevo;

// Crear nuevo dato


ESTRUCTURA DE DATOS EN JAVA 53
nuevo=new ListaSimpleCirc();
nuevo.info=x;
// Primer dato
if (top==null) top=nuevo;
else nuevo.sig=top.sig;
top.sig=nuevo;
top=nuevo;
}

public void contenido(){


ListaSimpleCirc p;

System.out.println("Impresion de la lista");
p=top;
if(p!=null){
while(top!=p.sig){
System.out.print(""+p.info+"\t");
p=p.sig;
}
//p=p.sig;

System.out.println(p.info);
}
}

La Clase DemoListaSimpleCirc utiliza la clase Lis-


taSimpleCirc y muestra sus operaciones:
public class DemoListaSimpleCirc{
public static void main(String []args){
ListaSimpleCirc L=new ListaSimpleCirc();
int x=0,sw,opcion;

sw=1;
do{
System.out.println("\n\n\n\nProcesamiento de una lista circular
simplemente enlazada\n");
System.out.println("0. Salir");
System.out.println("1. Anula lista");
System.out.println("2. Inserta un elemento a la lista");
System.out.println("3. Contenido de la lista");
System.out.print("Opcion ==> ");
opcion=Leer.datoInt();
switch(opcion){
case 0:sw=0;break;
case 1:L.anula();break;
case 2:
System.out.print("Digite valor a insertar ==> ");
x=Leer.datoInt();
L.inserta(x);
break;
case 3:
L.contenido();break;
}
}while(sw==1);
}
}

54 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


3.6. LISTA CIRCULAR DOBLEMENTE ENLAZADA.

3.7. PROGRAMAS EJEMPLO

PROGRAMA EJEMPLO UNO


Se tiene una lista simplemente enlazada, que guarda
cada elemento de una expresión matemática, en cada
nodo de la lista. Se pide hacer una función que
calcule la expresión teniendo en cuenta que las
operaciones se realizan de izquierda a derecha.

Ejemplo: Si la expresión es 3+2-2*5/3

L
3 + 2 -

2 * 5 / 3 NULL

Vea Capitulo 3, carpeta expresión.

Archivo: ListaSimple.java
//programa que realiza la implementación del
//TDA lista con referencias.

// Utiliza la clase Leer que debe de estar almacenada


// en la misma carpeta
public class ListaSimple {
char info;
ListaSimple top; // Puntero al Inicio
ListaSimple sig; // Puntero al siguiente

ListaSimple(){
top=sig=null;
}

public void anula(){


top=null;
}

public void inserta(char x){


ListaSimple comienzo, nuevo, p, q;
ESTRUCTURA DE DATOS EN JAVA 55
comienzo=top;
// Crear nuevo dato
nuevo=new ListaSimple();
p=new ListaSimple();
nuevo.info=x;
// Primer dato
if (comienzo==null){
comienzo=nuevo;
nuevo.sig=null;
}
else //valor antes de comienzo
{
// Nuevo se halla entre p y q luego
// de enlazarlos
q=comienzo;
while (q!=null)
{
p=q;
q=q.sig;
}
p.sig=nuevo;
nuevo.sig=q;
}
top=comienzo;
}

public void contenido(){


ListaSimple p;

System.out.println("Impresion de la lista");
p=top;
while(p!=null){
System.out.print(" "+p.info);
p=p.sig;
}
System.out.println();;
}

public float calcular(){


ListaSimple p,operador,op2;
int resp=0;

p=top;
resp=Character.digit(p.info,10);
operador =p.sig;
op2=operador.sig;
while(operador!=null)
{
switch(operador.info)
{
case '+': resp=resp+Character.digit(op2.info,10);break;
case '-': resp=resp-Character.digit(op2.info,10);break;
case '*': resp=resp*Character.digit(op2.info,10);break;
case '/': resp=resp/Character.digit(op2.info,10);break;
}

operador=op2.sig;
if(operador!=null)
op2=operador.sig;
}
return(resp);
}

public ListaSimple primero(){


return (top);
}

56 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


}

Archivo: DemoListaSimple.java
public class DemoListaSimple{
public static void main(String []args)
{

ListaSimple L=new ListaSimple();


char [] exp;
String expr;
int i;

System.out.print("Digite expresion ==> ");


expr=Leer.datoString();
exp=expr.toCharArray();
for(i=0;i<exp.length;i++)
L.inserta(exp[i]);

L.contenido();

System.out.print("la respuesta es ==> "+L.calcular());


System.out.println("");
}
}

PROGRAMA EJEMPLO DOS


Escribir un programa que almacene cada término de
un polinomio de la forma f(x) de grado “n”, en cada
nodo de una lista. El programa debe permitir eva-
luar la función dado un valor para x.

//Archivo TerminoPolinomio.java
//programa que realiza la implementación del
//TDA Polinomio con referencias.

// Utiliza la clase Leer que debe de estar almacenada


// en la misma carpeta
public class TerminoPolinomio {
float coef,expo;

TerminoPolinomio top; // Puntero al Inicio


TerminoPolinomio sig; // Puntero al siguiente

TerminoPolinomio(){
top=sig=null;
}

public void anula(){


top=null;
}

public void inserta(float c, float e){


TerminoPolinomio comienzo, nuevo, p, q;

comienzo=top;
// Crear nuevo dato
nuevo=new TerminoPolinomio();
p=new TerminoPolinomio();
ESTRUCTURA DE DATOS EN JAVA 57
nuevo.coef=c;
nuevo.expo=e;

// Primer dato
if (comienzo==null){
comienzo=nuevo;
nuevo.sig=null;
}
else //valor antes de comienzo
if (e<comienzo.expo){
nuevo.sig=comienzo;
comienzo=nuevo;
}
else {
// Nuevo se halla entre p y q luego
// de enlazarlos
q=comienzo;
while (q!=null && (e>=q.expo)){
p=q;
q=q.sig;
}
p.sig=nuevo;
nuevo.sig=q;
}
top=comienzo;
}

public void contenido(TerminoPolinomio p){

if (p!=null)
{System.out.print(p.coef+"X^"+p.expo +"+");
contenido(p.sig);
}

public float evalua(float x, TerminoPolinomio p)


{

if (p==null)
return 0;
else
return p.coef*(float)Math.pow(x,p.expo)+evalua(x,p.sig);

}
}

// Archivo DemoTerminoPolinomio.java

public class DemoTerminoPolinomio{


public static void main(String []args){
TerminoPolinomio p=new TerminoPolinomio();
TerminoPolinomio L=new TerminoPolinomio();
int sw,opcion;
float c,e,x;

sw=1;
do{
System.out.println("\n\n\n\nProcesamiento de una Lista
simplemente enlazada\n");
System.out.println("0. Salir");
System.out.println("1. Anula polinomio");
System.out.println("2. Inserta un elemento al polinomio");
58 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
System.out.println("3. Contenido del polinomio");
System.out.println("4. Evaluacion polinomio");

System.out.print("Opcion ==> ");


opcion=Leer.datoInt();
switch(opcion){
case 0:sw=0;break;
case 1:L.anula();break;
case 2:
System.out.print("Digite coeficiente del termino ==> ");
c=Leer.datoFloat();
System.out.print("Digite exponente del termino ==> ");
e=Leer.datoFloat();
L.inserta(c,e);
break;
case 3:
System.out.println("Impresion de la lista\n");
L.contenido(L.top);break;
case 4:
System.out.print("Digite valor de x ==> ");
x=Leer.datoFloat();
System.out.println("La evaluacion de la funcion es : "+
L.evalua(x,L.top));
break;

}
}while(sw==1);
}
}

PROGRAMA EJEMPLO TRES


Se tienen dos listas simplemente enlazadas. Se pide
hacer una función que reciba ambas listas y las fu-
sione sin crear nuevos nodos utilizando la interca-
lación de los nodos de ambas listas. Si las listas
recibidas son:

L1
3 6 7 9 NULL
L2
5 8 NULL
Se obtiene:

L1
3 5 6 7

8 9 NULL
L2
NULL
Utilizando la herencia se ha creado la clase Lis-
taUnir a partir de la clase ListaSimple (Para hacer
correr el programa ambas clases deben estar en el
ESTRUCTURA DE DATOS EN JAVA 59
mismo directorio o sus rutas en la variable CLASS-
PATH)
public class ListaUnir extends ListaSimple{

public void unir(ListaSimple L2){


ListaSimple p=new ListaSimple();
ListaSimple q=new ListaSimple();
ListaSimple fin=new ListaSimple();
ListaSimple inicio1=new ListaSimple();
ListaSimple inicio2=new ListaSimple();
ListaSimple inicio=new ListaSimple();

inicio=null;
inicio1=top;
inicio2=L2.top;
while(inicio1!=null && inicio2!=null){
if(inicio1.info>=inicio2.info){
p=inicio2;
while (p!=null && inicio1.info >= p.info){
q=p;
p=p.sig;
}
if(inicio==null){
inicio=inicio2;
q.sig=inicio1;
inicio2=p;
fin=inicio1;
inicio1=inicio1.sig;
}
else{
fin.sig=inicio2;
inicio2=p;
q.sig=inicio1;
fin=inicio1;
inicio1=inicio1.sig;
}
}
else
{
p=inicio1;
while (p!=null && inicio2.info >= p.info){
q=p;
p=p.sig;
}
if(inicio==null){
inicio=inicio1;
q.sig=inicio2;
inicio1=p;
fin=inicio2;
inicio2=inicio2.sig;
}
else{
fin.sig=inicio1;
inicio1=p;
q.sig=inicio2;
fin=inicio2;
inicio2=inicio2.sig;
}
}
}
if (inicio1!=null || inicio2!=null){
if(inicio1!=null)fin.sig=inicio1;
else fin.sig=inicio2;
}
if(inicio==null)
if(inicio1==null) inicio=inicio2;
else inicio=inicio1;
60 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
top=inicio;
}

public void ingreso(String mensaje,ListaSimple L){


int x;

while(true){
System.out.print(mensaje);
x=Leer.datoInt();
if (x==0) break;
L.inserta(x);
}
}

public static void main(String []args){


ListaUnir L1=new ListaUnir();
ListaUnir L2=new ListaUnir();

L1.ingreso("Digite valor a insertar L1 (0=fin)=> ",L1);


L2.ingreso("Digite valor a insertar L2 (0=fin)=> ",L2);
L1.contenido();
L2.contenido();
L1.unir(L2);
L1.contenido();
}
}

PROGRAMA EJEMPLO CUATRO


Para descartar descartar los datos repetidos se mo-
difica el método “unir”. Si las listas recibidas:

L1
3 6 7 9 NULL
L2
5 6 8 NULL
Se obtiene:

L1
3 5 6 7

8 9 NULL
L2
NULL
Utilizando la herencia se ha creado la clase Lis-
taUnirNoRepite a partir de la clase ListaSimple
(Para hacer correr el programa ambas clases deben
estar en el mismo directorio o sus rutas en la va-
riable CLASSPATH)
public class ListaUnirNoRepite extends ListaSimple{

ESTRUCTURA DE DATOS EN JAVA 61


public void unir(ListaSimple L2){
ListaSimple p=new ListaSimple();
ListaSimple q=new ListaSimple();
ListaSimple fin=new ListaSimple();
ListaSimple inicio1=new ListaSimple();
ListaSimple inicio2=new ListaSimple();
ListaSimple inicio=new ListaSimple();

inicio=null;
inicio1=top;
inicio2=L2.top;
while(inicio1!=null && inicio2!=null){
if(inicio1.info>=inicio2.info){
p=inicio2;
while (p!=null && inicio1.info >= p.info){
q=p;
p=p.sig;
}
if(inicio==null){
inicio=inicio2;
q.sig=inicio1;
inicio2=p;
fin=inicio1;
inicio1=inicio1.sig;
}
else{
fin.sig=inicio2;
inicio2=p;
q.sig=inicio1;
fin=inicio1;
inicio1=inicio1.sig;
}
}
else
{
p=inicio1;
while (p!=null && inicio2.info >= p.info){
q=p;
p=p.sig;
}
if(inicio==null){
inicio=inicio1;
q.sig=inicio2;
inicio1=p;
fin=inicio2;
inicio2=inicio2.sig;
}
else{
fin.sig=inicio1;
inicio1=p;
q.sig=inicio2;
fin=inicio2;
inicio2=inicio2.sig;
}
}
}
if (inicio1!=null || inicio2!=null){
if(inicio1!=null)fin.sig=inicio1;
else fin.sig=inicio2;
}
if(inicio==null)
if(inicio1==null) inicio=inicio2;
else inicio=inicio1;
top=inicio;
EliminaRepetido();
}

public void EliminaRepetido(){


ListaSimple q=new ListaSimple();

62 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


ListaSimple p=new ListaSimple();
ListaSimple r=new ListaSimple();

q=top;
if (q==null)
System.out.println("Lista vacia");
else{
p=q;
q=q.sig;
while (q!=null){
if (p.info==q.info){
r=q.sig;
p.sig=r;
q=r;
}else{
p=q;
q=q.sig;
}
}
}
}

public void ingreso(String mensaje,ListaSimple L){


int x;

while(true){
System.out.print(mensaje);
x=Leer.datoInt();
if (x==0) break;
L.inserta(x);
}
}

public static void main(String []args){


ListaUnirNoRepite L1=new ListaUnirNoRepite();
ListaUnirNoRepite L2=new ListaUnirNoRepite();

L1.ingreso("Digite valor a insertar L1 (0=fin)=> ",L1);


L2.ingreso("Digite valor a insertar L2 (0=fin)=> ",L2);
L1.contenido();
L2.contenido();
L1.unir(L2);
L1.contenido();
}
}

ESTRUCTURA DE DATOS EN JAVA 63


PROGRAMA EJEMPLO CINCO
Se tiene 2 listas enlazadas, se pide hacer una fun-
ción que elimine las ocurrencias de L1 en L2.

Se presenta la función elimina ocurrencias y todas


las funciones necesarias para que ejecute el pro-
grama correctamente. El programa no funciona si la
ocurrencia esta al inicio de la segunda lista.

Utilizando la herencia se ha creado la clase Lis-


taEliOcurre a partir de la clase ListaSimple (Para
hacer correr el programa ambas clases deben estar
en el mismo directorio o sus rutas en la variable
CLASSPATH)
public class ListaEliOcurre extends ListaSimple{

void eliminaOcurrencia(ListaSimple L2){


ListaSimple c1=new ListaSimple();
ListaSimple c2=new ListaSimple();
ListaSimple q=new ListaSimple();
ListaSimple p=new ListaSimple();
ListaSimple r=new ListaSimple();
ListaSimple s=new ListaSimple();

c1=top;
c2=L2.top;
if (c1==null)
System.out.println("lista vacia");
else{
s=c2;
while(s!=null){
q=c1;
p=null;
while(q!=null && s.info>q.info){
p=q;
q=q.sig;
r=q.sig;
}
if(s.info==q.info){
if (p==null){
p=q;
q=q.sig;
c1=q;
}else p.sig=r;
}
s=s.sig;
}
}
top=c1;
}

public void ingreso(String mensaje,ListaSimple L){


int x;

while(true){
System.out.print(mensaje);
x=Leer.datoInt();
if (x==0) break;
L.inserta(x);
}
64 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
}

public void EliminaRepetido(){


ListaSimple q=new ListaSimple();
ListaSimple p=new ListaSimple();
ListaSimple r=new ListaSimple();

q=top;
if (q==null)
System.out.println("Lista vacia");
else{
p=q;
q=q.sig;
while (q!=null){
if (p.info==q.info){
r=q.sig;
p.sig=r;
q=r;
}else{
p=q;
q=q.sig;
}
}
}
}

public static void main(String []args){


ListaEliOcurre L1=new ListaEliOcurre();
ListaEliOcurre L2=new ListaEliOcurre();

L1.ingreso("Digite valor a insertar L1 (0=fin)=> ",L1);


L2.ingreso("Digite valor a insertar L2 (0=fin)=> ",L2);
L1.EliminaRepetido();
L2.EliminaRepetido();
L1.contenido();
L2.contenido();
L1.eliminaOcurrencia(L2);
L1.contenido();
}
}

3.8. PROBLEMAS PROPUESTOS

PROBLEMA UNO
Construir una lista enlazada circular simple por la
disciplina FIFO (cola).

PROBLEMA DOS
Dada una lista enlazada simple buscar el nodo que
contenga el dato D e insertar antes de él un nuevo
nodo con el dato E. En caso de no encontrarse se
insertará al final.

PROBLEMA TRES
Dada dos listas enlazadas ordenadas, combinarlas en
una sola lista ordenada. La nueva lista ordenada
reemplaza a las listas anteriores.
ESTRUCTURA DE DATOS EN JAVA 65
CAPITULO CUATRO

RECURSION

4.1. ALGORITMOS RECURSIVOS


La recursión es un concepto fundamental en Matemá-
ticas y en la Ciencia de la Computación, en este
último caso particularmente cuando se manipulan
ciertas estructuras de datos de naturaleza recursi-
va o como paso previo para obtener una solución no
recursiva.

Un objeto es llamado recursivo si parcialmente con-


siste o está definido en términos de sí mismo.

Las características esenciales en la recursión son:

ƒ La condición de terminación. Sin ella, se ten-


dría un número infinito de llamadas recursi-
vas.

ƒ Un parámetro que varía en cada llamada recur-


siva y que después de un número finito de va-
lores debe conducir a la condición de termina-
ción.

ESTRUCTURA DE DATOS EN JAVA 67


PROGRAMA EJEMPLO UNO

Factorial de un número natural


El factorial de un número natural n es otro número
natural denotado por n! y definido como sigue:

a) n! = n (n-1)! , si n > 0
b) 0! = 1
De acuerdo con está definición, el cálculo de fac-
torial de 4! es como sigue:

4! = 4 * (3!) por (b)


4! = 4 * 3* (2!) por (b)
4! = 4 * 3* 2 * (1!) por (b)
4! = 4 * 3* 2 * 1* (0!) por (b)
4! = 4 * 3* 2 * 1* 1 por (b)
4! = 120
La implementación de una función factorial recursi-
va en el Lenguaje C++ es:
public class factorial{
public static long factorial(long n){
if (n==0) return(1);
else return(n*factorial(n-1));
}

public static void main(String []args){


long n;

System.out.print("Ingrese un número: ");


n=Leer.datoLong();
System.out.println("El factorial es "+factorial(n));
}
}

PROGRAMA EJEMPLO DOS

Multiplicación de números naturales.


El producto a*b en donde a y b son enteros positi-
vos, se define como a sumado a sí mismo b veces
(definición iterativa).

Una definición recursiva equivalente es:

a) a*b = a, si b=1
b) a*b = a * (b-1) + a si b>1
De acuerdo con esta definición, si se desea evaluar
6 * 2 se tiene:
68 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
6 *3 = 6 * 2 + 6
= 6 * 1+ 6 + 6
= 6 + 6 + 6
public class producto{
public static int producto(int a, int b){
if (b==1) return(a);
else return(producto(a,b-1)+a);
}

public static void main(String []args){


int a,b,p;

System.out.print("Ingrese 1er número: ");


a=Leer.datoInt();
System.out.print("Ingrese 2do número: ");
b=Leer.datoInt();
p=producto(a,b);
System.out.println("El producto es "+p);
}
}

PROGRAMA EJEMPLO TRES


Suma de los n numeros consecutivos: 1+2+3+…+n
public class sumaConsecutivos{
public static int suma(int n){
if (n==0) return(0);
else return(suma(n-1)+n);
}

public static void main(String []args){


int n,s;

System.out.print("Ingrese un número: ");


n=Leer.datoInt();
s=suma(n);
System.out.println("La suma es "+s);
}
}

PROGRAMA EJEMPLO CUATRO


Calcula el máximo común divisor

Solución 1
public class mcd1{
public static int mcd(int a,int b){
if (b>a) return mcd(b,a);
if (b==0) return a;
else return mcd(b,a%b);
}

public static void main(String []args){


int n1,n2;
char resp;

do{
System.out.print("Primer número : ");
n1=Leer.datoInt();
System.out.print("Segundo número: ");
n2=Leer.datoInt();
System.out.println("MCD de "+n1+" y "+n2+" es "
+mcd(n1,n2));
System.out.println();
ESTRUCTURA DE DATOS EN JAVA 69
System.out.print("Continuar (s/n)? ");
resp=Leer.datoChar();
}while(resp!='n'&& resp!='N');
}
}

Solución 2
public class mcd2{

public static int mcd(int x,int y){

if (x>=y && x%y==0) return y;


else{
if (x<y) return mcd(y,x);
else return mcd(y,x%y);
}
}

public static void main(String []args){


int n1,n2;
char resp;

do{
System.out.print("Primer número : ");
n1=Leer.datoInt();
System.out.print("Segundo número: ");
n2=Leer.datoInt();
System.out.println("MCD de "+n1+" y "+n2+" es "
+mcd(n1,n2));
System.out.println();
System.out.print("Continuar (s/n)? ");
resp=Leer.datoChar();
}while(resp!='n'&& resp!='N');
}
}

PROGRAMA EJEMPLO CINCO


Se tiene una lista simplemente enlazada que almace-
na un polinomio (un término en cada nodo de la lis-
ta). Se pide implementar una función recursiva,
que devuelva el valor de la evaluación de la fun-
ción, esta función debe recibir la lista que con-
tiene al polinomio y los parámetros que usted con-
sidere conveniente.

Ejemplo: Si la función es f(x)=3x2+2x+3; la evalua-


ción de f(1)= 3(1)2+2(1)+3 es 8.

Nota: El polinomio a recibir puede ser de cualquier


grado y suponga que ya se tiene la lista creada.

Solución
//Archivo TerminoPolinomio.java
//programa que realiza la implementación del
70 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
//TDA Polinomio con referencias.

// Utiliza la clase Leer que debe de estar almacenada


// en la misma carpeta
public class TerminoPolinomio {
float coef,expo;

TerminoPolinomio top; // Puntero al Inicio


TerminoPolinomio sig; // Puntero al siguiente

TerminoPolinomio(){
top=sig=null;
}

public void anula(){


top=null;
}

public void inserta(float c, float e){


TerminoPolinomio comienzo, nuevo, p, q;

comienzo=top;
// Crear nuevo dato
nuevo=new TerminoPolinomio();
p=new TerminoPolinomio();
nuevo.coef=c;
nuevo.expo=e;

// Primer dato
if (comienzo==null){
comienzo=nuevo;
nuevo.sig=null;
}
else //valor antes de comienzo
if (e<comienzo.expo){
nuevo.sig=comienzo;
comienzo=nuevo;
}
else {
// Nuevo se halla entre p y q luego
// de enlazarlos
q=comienzo;
while (q!=null && (e>=q.expo)){
p=q;
q=q.sig;
}
p.sig=nuevo;
nuevo.sig=q;
}
top=comienzo;
}

public void contenido(TerminoPolinomio p){

if (p!=null)
{System.out.print(p.coef+"X^"+p.expo +"+");
contenido(p.sig);
}

public float evalua(float x, TerminoPolinomio p)


{

if (p==null)
return 0;
else
return p.coef*(float)Math.pow(x,p.expo)+evalua(x,p.sig);

}
}

ESTRUCTURA DE DATOS EN JAVA 71


// Archivo DemoTerminoPolinomio.java

public class DemoTerminoPolinomio{


public static void main(String []args){
TerminoPolinomio p=new TerminoPolinomio();
TerminoPolinomio L=new TerminoPolinomio();
int sw,opcion;
float c,e,x;

sw=1;
do{
System.out.println("\n\n\n\nProcesamiento de una Lista
simplemente enlazada\n");
System.out.println("0. Salir");
System.out.println("1. Anula polinomio");
System.out.println("2. Inserta un elemento al polinomio");
System.out.println("3. Contenido del polinomio");
System.out.println("4. Evaluacion polinomio");

System.out.print("Opcion ==> ");


opcion=Leer.datoInt();
switch(opcion){
case 0:sw=0;break;
case 1:L.anula();break;
case 2:
System.out.print("Digite coeficiente del termino ==> ");
c=Leer.datoFloat();
System.out.print("Digite exponente del termino ==> ");
e=Leer.datoFloat();
L.inserta(c,e);
break;
case 3:
System.out.println("Impresion de la lista\n");
L.contenido(L.top);break;
case 4:
System.out.print("Digite valor de x ==> ");
x=Leer.datoFloat();
System.out.println("La evaluacion de la funcion es : "+
L.evalua(x,L.top));
break;

}
}while(sw==1);
}
}

4.2. PROBLEMAS PROPUESTOS

PROBLEMA UNO
Desarrollar un procedimiento o función recursiva
para hallar las combinaciones de n números combina-
dos en grupos de r elementos. Recomendación: Utili-
ce las siguientes propiedades:

C 0n = 1

72 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


n − r +1
C rn = * C rn−1
r

PROBLEMA DOS
Escribir un programa que utilizando una función re-
cursiva imprima los “n” numeros consecutivos. Ver
carpeta imprimen.
public class impresion {
public static void imp(int n){
if(n!=0)
{
imp(n-1);
System.out.println(n);
//imp(n-1);
}
}
public static void main(String arg[])
{
int n;
System.out.println("ingrese numero");
n=Leer.datoInt();
System.out.println("La impresion es:");
imp(n);
System.out.println("\n");
}
}

PROBLEMA TRES
Diseñar un método recursivo para encontrar las ci-
fras de un numero entero. Ver carpeta imprimen.
public class impresion3 {
public static void imp(int n){
int r;
if(n!=0)
{

r=n%10;
//System.out.print(";"+r);
imp(n/10);
System.out.println(r);
}
}
public static void main(String arg[])
{
int n;
System.out.println("ingrese numero");
n=Leer.datoInt();
System.out.println("La impresion es:");
imp(n);
System.out.println("\n");
}
}

ESTRUCTURA DE DATOS EN JAVA 73


PROBLEMA CUATRO
Diseñar un método recursivo para que recorra e im-
prima los elementos de una lista simplemente enla-
zada.

PROBLEMA CINCO
Considere un arreglo (matriz) unidimensional de en-
teros. Escriba algoritmos recursivos para calcular:

a) El mayor elemento del arreglo.

b) La suma de los elementos del arreglo.

PROBLEMA SEIS
La función de Ackerman se define en forma recursiva
para enteros no negativos de la siguiente manera:

a(m,n)=n+1 Æ si m=0

a(m,n)=a(m-1,n) Æ si m≠0, n=0

a(m,n)=a(m-1,a(m,n-1) Æ si m≠0,n ≠0

Escriba un algoritmo recursivo para la función de


Ackerman.

74 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


CAPITULO CINCO

PILAS Y COLAS

5.1. PILAS (LIFO)


Una pila es un tipo especial de lista en la que to-
das las inserciones y supresiones se realizan sola-
mente por uno de los extremos, el cual será llamado
cima o parte superior.

A continuación se presenta el esquema gráfico de


una pila:

D Cima (parte superior)


C
B
A

En la figura, el elemento D ha sido el último en


entrar a la pila. Si ahora quisiéramos suprimir un
elemento de la pila, éste debe ser D. Esto justifi-
ca el nombre de Lista lifo (last in, first out =
último en entrar, primero en salir) para una pila.

Las pilas se utilizan en gran cantidad en software


de sistemas, incluyendo compiladores e intérpretes.

ESTRUCTURA DE DATOS EN JAVA 75


5.1.1. OPERACIONES BÁSICAS
P.ANULA() Función que convierte a la pila P en la pila vacía.
Función que retorna el elemento de la parte supe-
P.CIMA()
rior de la pila P.
Función que inserta al elemento x en la parte
P.APILA(x) superior de la pila P, cuya posición viene a ser la
nueva cima de la pila.
Función que suprime al elemento superior de la
P.DESAPILA()
pila P.

5.1.2. IMPLEMENTACIÓN DE PILAS CON REFEREN-


CIAS

La implementación de pilas con referen-


cias, se basa en la siguiente figura:

5 6 NULL

Cima Fin
(Inicio)
// Utiliza la clase Leer que
// deben estar almacenadas en la misma carpeta

class pila {

int info;
pila sig;
pila inicio;
pila fin;

pila(){
inicio = fin = sig = null;
}

public void anula(){


inicio = fin = null;
}

public void apila(int x)


{
pila nuevo;

nuevo = new pila();


if(nuevo==null)
System.out.println("Error de asignacion");
else{
nuevo.info = x;

// Pone al principio de la pila


if(inicio!=null) nuevo.sig = inicio;
inicio = nuevo;
if(fin==null) fin = inicio;
}
}

76 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


public void desapila()
{

if(inicio==null)
System.out.println("Pila vacía");
else // Quitar del principio de la pila
inicio = inicio.sig;
}

public int cima()


{
if (inicio==null)
{
//si la pila es vacia retorna -1
System.out.println("Pila vacía");
return(-1);
}
else//retorna el valor de la cima
return (inicio.info);
}

public void contenido(){


pila p;

System.out.println("impresión de la pila");
p=inicio;
while(p!=null){
System.out.println(p.info);
p=p.sig;
}
System.out.println();
}
}

La Clase DemoPila utiliza la clase pila y


muestra sus operaciones:
public class DemoPila{
public static void main(String []args)
{
pila P=new pila();

int x=0,pos=0,sw,opcion;

sw=1;
do{
System.out.println("\n\n\n\nProcesamiento de una
Pila\n");
System.out.println("0. Salir");
System.out.println("1. Anula pila");
System.out.println("2. Apila");
System.out.println("3. Contenido de la pila");
System.out.println("4. Desapila");
System.out.println("5. Cima");
System.out.print("Opcion ==> ");
opcion=Leer.datoInt();
switch(opcion){
case 0: sw=0;break;
case 1: P.anula();break;
case 2: System.out.print("Valor a insertar
==>");
x=Leer.datoInt();
P.apila(x);
break;
case 3: P.contenido();break;
case 4: P.desapila();

break;

case 5:
x=P.cima();
if(x==-1)
ESTRUCTURA DE DATOS EN JAVA 77
System.out.println("Pila Vacía
");
else
System.out.println("Valor de la
cima es: "+x);
break;
}
}while(sw==1);
}
}

5.2. COLAS (FIFO)

Una cola es otro tipo especial de lista, en la cual


los elementos se insertan por un extremo llamado
FINAL y se suprime por el otro llamado FRENTE:

a, b, c, d, e

Frente Fin
Esto ocasiona que el primer elemento en entrar es
el primero en salir; de aquí el nombre de lista fi-
fo (first in, first out) que también se le da a una
cola.

5.2.1. OPERACIONES
Las operaciones básicas que caracterizan a una cola
son las siguientes:

Función que convierte a la cola C en cola


C.ANULA()
vacía.
Función que retorna el 1er. elemento de la
C.FRENTE() cola C. Esta función no está definida si la
cola es vacía.
Función que inserta al elemento x en el
C.INSERTA_COLA(x)
final de C.
Función que suprime el elemento del fren-
C.SUPRIME_COLA() te de la cola C. No se realiza si la cola es
vacía.

78 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


5.2.2. IMPLEMENTACIÓN DE COLAS CON REFEREN-
CIAS

La implementación de colas con referen-


cias, se basa en la siguiente figura:

5 6 NULL

Frente Fin
(Inicio)
// Utiliza la clase Leer que
// deben estar almacenadas en la misma carpeta
public class cola {
int info;
cola sig;
cola inicio;
cola fin;

cola(){
inicio = fin = sig = null;
}

public void anula(){


inicio = fin=null;;
}

public void inserta_cola(int x)


{
cola nuevo;

nuevo = new cola();


if(nuevo==null)
System.out.println("Error de asignación");
else{
nuevo.info = x;

// Poner al final de la cola


if(fin!=null) fin.sig = nuevo;
fin = nuevo;
nuevo.sig = null;
if(inicio==null) inicio = fin;
}
}

public void suprime_cola()


{
if(inicio==null)
System.out.println("Cola vacía");
else // Quitar del principio de la cola
inicio = inicio.sig;
}

public int frente()


{
if (inicio==null)
{ // si la cola es vacía retorna -1
System.out.println("Cola vacía");
return -1;
}//retorna el valor del que esta al frente
else return (inicio.info);
}

ESTRUCTURA DE DATOS EN JAVA 79


public void contenido(){
cola p;

System.out.println("impresión de la cola");
p=inicio;
while(p!=null){
System.out.print(p.info+"-->");
p=p.sig;
}
System.out.println("null");
}
}

La Clase DemoCola utiliza la clase cola y


muestra sus operaciones:
public class DemoCola{
public static void main(String []args)
{
cola C=new cola();

int x=0,pos=0,sw,opcion;

sw=1;
do{
System.out.println("\n\n\n\nProcesamiento de una
cola\n");
System.out.println("0. Salir");
System.out.println("1. Anula cola");
System.out.println("2. Inserta cola");
System.out.println("3. Contenido de la cola");
System.out.println("4. Suprime cola");
System.out.println("5. Frente");
System.out.print("Opcion ==> ");
opcion=Leer.datoInt();
switch(opcion){
case 0: sw=0;break;
case 1: C.anula();break;
case 2: System.out.print("Valor a insertar
==>");
x=Leer.datoInt();
C.inserta_cola(x);
break;
case 3: C.contenido();break;
case 4: C.suprime_cola();
break;
case 5: x=C.frente();
if(x==-1)
System.out.println("Cola vacía");
else
System.out.println("Valor del frente
es: "+x);
break;
}
}while(sw==1);
}
}

80 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


5.3. PROGRAMAS EJEMPLO

PROGRAMA EJEMPLO UNO


El siguiente programa almacena datos de la cola de
clientes en un banco. La función leer_datos almace-
na en los datos de la cola del banco, para lo cual
utiliza la función inserta_cola, los datos que se
almacenan son: el nombre del cliente, su tiempo de
atención en ventanilla, su tiempo de espera en la
cola. Con la función calcular_prom_ta_may_te se
calcula el tiempo promedio de atención, el mayor
tiempo de espera.
// Utiliza la clase Leer que
// deben estar almacenadas en la misma carpeta

public class ColaPromedio{


String nom;
float tia; //Tiempo de atención
float tie; //Tiempo de espera
ColaPromedio sig;
ColaPromedio inicio;
ColaPromedio fin;

ColaPromedio(){
nom="";
tia=tie=0;
inicio=fin=sig=null;
}

public void anula(){


inicio=fin=null;
}

public void inserta_cola(String n,float ta,float te)


{
ColaPromedio nuevo;

nuevo = new ColaPromedio();


if(nuevo==null)
System.out.println("Error de asignacion");
else{
nuevo.nom=n;
nuevo.tia=ta;
nuevo.tie=te;

// Poner al final de la cola


if(fin!=null) fin.sig = nuevo;
fin = nuevo;
nuevo.sig = null;
if(inicio==null) inicio = fin;
}
}

public void contenido(){


ColaPromedio p;

System.out.println("\n\nImpresión de la cola");
p=inicio;
while(p!=null){
System.out.print(p.nom+" "+p.tia+" "+p.tie+" --> ");
p=p.sig;
}
System.out.println("null");
ESTRUCTURA DE DATOS EN JAVA 81
}

public void leer_datos(){


String n;
float ta,te;

while (true) {
System.out.print("Nombre (* para finalizar) ==> ");
n=Leer.datoString();
if(n.equals("*")) break;
System.out.print("Tiempo de atencion ==> ");
ta=Leer.datoFloat();
System.out.print("Tiempo de espera ==> ");
te=Leer.datoFloat();
inserta_cola(n,ta,te);

}
}

public void calcular_prom_ta_may_te(){


ColaPromedio p;
float mayte=-1,sumata=0.0f;
int cant=0; //cantidad de elementos

System.out.println("\n\nImpresion calculos");
p=inicio;
while(p!=null){
sumata+=p.tia;
if (p.tie>mayte) mayte=p.tie;
cant++;
p=p.sig;
}
System.out.println("Promedio de tiempo de atencion "+
sumata/cant);
System.out.println("Mayor tiempo de espera "+mayte);
}

public static void main(String []args){


ColaPromedio C=new ColaPromedio();

C.leer_datos();
C.contenido();
C.calcular_prom_ta_may_te();
}
}

PROGRAMA EJEMPLO DOS


Programa que almacena los datos de atletas de una
competencia de maraton. Se almacena los siguientes
datos en una cola: el tiempo de inicio, el tiempo
de llegada (ambos son minutos transcurridos después
de las 9 am). Además se debe calcular el tiempo
transcurrido y mostrar a los atletas ordenados de
menor a mayor por el tiempo transcurrido.

Sólo utilice las operaciones de Lista y Cola para


dar solución a este ejercicio.

Vea la solución en la carpeta maratón.


82 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
Cola.java
// Utiliza la clase Leer
// deben estar almacenadas en la misma carpeta

public class Cola{


int norden;
String nom;
// el tiempo tiene en cuenta la cantidad de minutos
// que existen despues de las 9 am
float tii; //Tiempo de inicio
float till; //Tiempo de llegada
float tt; //Tiempo transcurrido
Cola sig;
Cola inicio;
Cola fin;

Cola(){
nom="";
norden=0;
tt=tii=till=0;
inicio=fin=sig=null;
}

public void anula(){


inicio=fin=null;
}

public int frente()


{
if (inicio==null)
return (-1);
else
return (norden);
}

public Cola datosfrente()


{
return (inicio);
}

public void inserta_cola(int no,String n,float ti,float tll)


{
Cola nuevo;

nuevo = new Cola();

nuevo.norden=no;
nuevo.nom=n;
nuevo.tii=ti;
nuevo.till=tll;
nuevo.tt=nuevo.till-nuevo.tii;

// Poner al final de la cola


if(fin!=null) fin.sig = nuevo;
fin = nuevo;
nuevo.sig = null;
if(inicio==null) inicio = fin;

public void suprime_cola()


{
if(inicio==null)
System.out.println("Cola vacía");
else // Quitar del principio de la cola
inicio = inicio.sig;
}

public void contenido(){


Cola p;
ESTRUCTURA DE DATOS EN JAVA 83
System.out.println("\n\nImpresión de la cola");
p=inicio;
while(p!=null){
System.out.print(p.nom+" "+p.tii+" "+p.till+" --> ");
p=p.sig;
}
System.out.println("null");
}

public void leer_datos(){


String n;
float ti,tll;
int no=0;
while (true)
{
System.out.print("Nombre (* para finalizar) ==> ");
n=Leer.datoString();
if(n.equals("*")) break;
no++;
System.out.print("Tiempo de inicio ==> ");
ti=Leer.datoFloat();
System.out.print("Tiempo de llegada ==> ");
tll=Leer.datoFloat();

inserta_cola(no,n,ti,tll);

}
}

ListaSimple.java
//programa que realiza la implementación del
//TDA lista con referencias.

// Utiliza la clase Leer que debe de estar almacenada


// en la misma carpeta
public class ListaSimple {
int norden;
String nom;
// el tiempo tiene en cuenta la cantidad de minutos
// que existen despues de las 9 am
float tii; //Tiempo de inicio
float till; //Tiempo de llegada
float tt; //Tiempo transcurrido
ListaSimple top; // Puntero al Inicio
ListaSimple sig; // Puntero al siguiente

ListaSimple(){
top=sig=null;
}

public void anula(){


top=null;
}

public void inserta(int no,String n,float ti,float tll,float t){


ListaSimple comienzo, nuevo, p, q;

comienzo=top;
// Crear nuevo dato
nuevo=new ListaSimple();
p=new ListaSimple();

84 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


nuevo.norden=no;
nuevo.nom=n;
nuevo.tii=ti;
nuevo.till=tll;
nuevo.tt=t;

// Primer dato
if (comienzo==null){
comienzo=nuevo;
nuevo.sig=null;
}
else //valor antes de comienzo
if (t<comienzo.tt){
nuevo.sig=comienzo;
comienzo=nuevo;
}
else {
// Nuevo se halla entre p y q luego
// de enlazarlos
q=comienzo;
while (q!=null && (t>=q.tt)){
p=q;
q=q.sig;
}
p.sig=nuevo;
nuevo.sig=q;
}
top=comienzo;
}

public void contenido(){


ListaSimple p;

System.out.println("Impresion de la lista");
p=top;
while(p!=null){
System.out.print(p.nom+" "+p.tii+" "+p.till+" "+p.tt+" --> ");
p=p.sig;
}
System.out.println();;
}

public ListaSimple primero(){


return (top);
}

MaratonAppl.java
// programa que almacena los datos de atletas de una
// competencia de maraton. Se almacena los siguientes datos en
// una cola: el tiempo de inicio, el tiempo de llegada (ambos son minutos
// transcurridos después de las 9 am). Además se debe calcular el tiempo
// transcurrido y mostrar a los atletas ordenados de menor a mayor por el
// tiempo transcurrido.
// Sólo utilice las operaciones de Lista y Cola para dar solución a este
// ejercicio.

public class MaratonAppl


{
public static void main(String []args)
{
int norden;
String nom;

ESTRUCTURA DE DATOS EN JAVA 85


// el tiempo tiene en cuenta la cantidad de minutos
// que existen despues de las 9 am
float tii; //Tiempo de inicio
float till; //Tiempo de llegada
float tt; //Tiempo transcurrido
Cola C=new Cola();
Cola Ctemp=new Cola();
ListaSimple L=new ListaSimple();

C.leer_datos();
C.contenido();

while(C.frente()!=-1)
{
Ctemp=C.datosfrente();
norden=Ctemp.norden;
nom=Ctemp.nom;
tii=Ctemp.tii;
till=Ctemp.till;
tt=Ctemp.tt;

L.inserta(norden,nom,tii,till,tt);
C.suprime_cola();
}

L.contenido();
}
}

La ejecución es:

PROGRAMA EJEMPLO TRES


Programa que evalúa el ámbito de una expresión li-
mitado por: (, ), [, ], { y }. El programa verifica
que cada ámbito comience con un delimitador de

86 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


apertura y termine con su correspondiente limitador
de cierre.

Para el programa se usa una pila para registrar los


delimitadores. Cuando se encuentra un símbolo para
abrir un ámbito, se agrega a la pila. Cuando se en-
cuentra un símbolo para cerrar un ámbito, se exami-
na la pila. Si está vacía, el signo no tiene el
símbolo correspondiente para abrir y, por tanto, la
cadena no es válida. Sin embargo, si la pila no es-
tá vacía, removemos el elemento de la pila y veri-
ficamos si el elemento removido corresponde al sím-
bolo para cerrar el ámbito. Si coinciden, prosegui-
mos. En caso contrario, la cadena no es válida.
Cuando se llega al fin de la cadena, la pila debe
estar vacía; de otra forma, se han abierto uno o
más ámbitos que no se han cerrado y la cadena no es
válida.
// Utiliza la clase Leer y que
// deben estar almacenadas en la misma carpeta
public class pila {
char info;
pila sig;
pila inicio;
pila fin;

pila(){
inicio=fin=sig=null;
}

public void anula(){


inicio=fin=null;
}

public void apila(char x)


{
pila nuevo;

nuevo = new pila();


if(nuevo==null)
System.out.println("Error de asignacion");
else{
nuevo.info=x;

// Pone al principio de la pila


if(inicio!=null) nuevo.sig=inicio;
inicio=nuevo;
if(fin==null) fin=inicio;
}
}

public void desapila()


{
if(inicio==null)
System.out.println("Pila vacía");
else // Quitar del principio de la pila
inicio=inicio.sig;
}

public char cima()


{
if (inicio==null)

ESTRUCTURA DE DATOS EN JAVA 87


{ // Si la pila es vacia devolver *
System.out.println("Pila vacía");
return ('*');
} // retorna caracter
else return (inicio.info);
}

public void contenido(){


pila p;

System.out.println("impresión de la pila");
p=inicio;
while(p!=null){
System.out.println(p.info);
p=p.sig;
}
System.out.println();
}

public void evalua_exp(String expresion){


int i=0;
boolean valid;
char car,car1,car2;

car=car1=car2='\0';
valid=true;
anula();

while(expresion.length()>i && valid){


car=expresion.charAt(i);
if (car=='(' ||
car=='[' ||
car=='{')

apila(car);

if (car==')' ||
car==']' ||
car=='}')
if(inicio==null)
valid=false;
else {
switch(car){
case ')':
car1='(';break;
case ']':
car1='[';break;
case '}':
car1='{';break;
}
car2=cima();
desapila();
if(car1!=car2) valid=false;
}
i++;
}
if(inicio!=null)
valid=false;
if (valid)
System.out.println("\nExpresion valida");
else
System.out.println("\nExpresion no valida");
}
}
La Clase EvaluaExpr utiliza la clase pila y analiza
una expresión:
public class EvaluaExpr{
88 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
public static void main(String []args){
pila P=new pila();
String expresion;

System.out.print("Expresion : ");
expresion=Leer.datoString();
P.evalua_exp(expresion);
}
}

PROGRAMA EJEMPLO CUATRO


Modificación del programa anterior, donde la lectu-
ra de la expresión se hace del archivo de tex-
to.txt. Sólo se ha modificado la clase EvaluaExpr
a:
import java.io.*;

public class EvaluaExpr{


public static void main(String []args){
pila P=new pila();
String expresion;

FileReader archivo;
BufferedReader archivoIn = null;

try{
archivo=new FileReader("test.txt");
archivoIn=new BufferedReader(archivo);
while((expresion=archivoIn.readLine())!=null){
System.out.println("\n\n\nExpresion : "+expresion);
P.evalua_exp(expresion);
}
}
catch(IOException e){
System.out.println(e);
}
finally{
try{
if(archivoIn!=null)
archivoIn.close();
}
catch(IOException e){
}
}
}
}

Para ejecutar el programa antes debe crear el ar-


chivo de texto test.txt en el mismo directorio de
la clase. La primera y la tercera son expresiones
válidas, la segunda no.
{x+(y-[a+b])*c-[(d+e)]}/(h-(j-(k-[l-n])))
{x+(y-[a+b])*c-[(d+e]}/(h-(j-(k-[l-n])))
(4+5)*{-[(4+2)-3]*3+5}

PROGRAMA EJEMPLO CINCO


Se tiene una pila que almacena valores enteros, se
pide implementar una función que utilice esta pila.
ESTRUCTURA DE DATOS EN JAVA 89
Además en la función se debe leer dos números ente-
ros, donde se buscaran los valores que sean igual
al primer número y reemplazarlos por el segundo nú-
mero.

Nota: Sólo se pueden utilizar las operaciones mos-


tradas en la clase pila o modificarlas si cree con-
veniente. Para realizar la búsqueda y reemplazar
los valores no se puede utilizar la forma: p=p.sig
o while (p!=null).

Ejemplo: Si num1=3 y num2=10 se tiene:

3 10
4 4
5 Æ 5
3 10
7 7
2 2

Vea la carpeta reemplazar.

Pila.java
// Utiliza la clase Leer que
// deben estar almacenadas en la misma carpeta

class pila {

int info;
pila sig;
pila inicio;
pila fin;

pila(){
inicio = fin = sig = null;
}

public void anula(){


inicio = fin = null;
}

public void apila(int x)


{
pila nuevo;

nuevo = new pila();


if(nuevo==null)
System.out.println("Error de asignacion");
else{
nuevo.info = x;

// Pone al principio de la pila


if(inicio!=null) nuevo.sig = inicio;
inicio = nuevo;
if(fin==null) fin = inicio;
90 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
}
}

public void desapila()


{

if(inicio==null)
System.out.println("Pila vacía");
else // Quitar del principio de la pila
inicio = inicio.sig;
}

public int cima()


{
if (inicio==null)
return -1;
else
return (inicio.info);
}

public void contenido(){


pila p;

System.out.println("impresión de la pila");
p=inicio;
while(p!=null){
System.out.println(p.info);
p=p.sig;
}
System.out.println();
}

public pila reemplazar(pila p1, int num1, int num2)


{ pila p2=new pila();

p2.anula();
// reemplaza num1 de la pila con num2
while (p1.cima()!=-1 )
{
if (p1.cima()==num1)
p2.apila(num2);
else
p2.apila(p1.cima());

p1.desapila();
}

// invierte pila
p1.anula();
while (p2.cima()!=-1 )
{
p1.apila(p2.cima());
p2.desapila();
}

return p1;
}
}

Demopila.java
public class DemoPila{
public static void main(String []args)
{
pila P=new pila();

int x=0,pos=0,sw,opcion;

sw=1;

ESTRUCTURA DE DATOS EN JAVA 91


do{
System.out.println("\n\n\n\nProcesamiento de una Pila\n");
System.out.println("0. Salir");
System.out.println("1. Anula pila");
System.out.println("2. Apila");
System.out.println("3. Contenido de la pila");
System.out.println("4. Desapila");
System.out.println("5. Cima");
System.out.println("6. Reemplazar");
System.out.print("Opcion ==> ");
opcion=Leer.datoInt();
switch(opcion){
case 0: sw=0;break;
case 1: P.anula();break;
case 2: System.out.print("Valor a insertar ==>");
x=Leer.datoInt();
P.apila(x);
break;
case 3: P.contenido();break;
case 4:
P.desapila();
break;
case 5:
x=P.cima();
if (x!=-1)
{ System.out.print("Valor de la cima es: "+x);
break;
}
else
System.out.print("Pila vacia ");
case 6:
int num1,num2;
System.out.println("Ingrese 1er numero ==> ");
num1=Leer.datoInt();
System.out.println("Ingrese 2do numero ==> ");
num2=Leer.datoInt();
P=P.reemplazar(P,num1,num2);
P.contenido();
break;

}
}while(sw==1);
}
}

PROGRAMA EJEMPLO SEIS


Se tiene una cola que almacena enteros positivos y
negativos. Se pide implementar una función que uti-
lice esta cola y almacene los positivos en una pila
y los negativos en otra pila. Luego desde las pilas
desapile los elementos y almacene los elementos en
otras dos colas.

Una posible ejecución es:

92 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


Vea la carpeta positivos_negativos

Cola.java

// Utiliza la clase Leer


// deben estar almacenadas en la misma carpeta

public class Cola{


int info;

Cola sig;
Cola inicio;
Cola fin;

Cola(){
inicio=fin=sig=null;
}

public void anula(){


inicio=fin=null;
}

public int frente()


{
if (inicio==null)
return (-10000);
else
return (inicio.info);
}

public void inserta_cola(int n)


ESTRUCTURA DE DATOS EN JAVA 93
{
Cola nuevo;

nuevo = new Cola();

nuevo.info=n;

// Poner al final de la cola


if(fin!=null) fin.sig = nuevo;
fin = nuevo;
nuevo.sig = null;
if(inicio==null) inicio = fin;
}

public void suprime_cola()


{
if(inicio==null)
System.out.println("Cola vacia");
else // Quitar del principio de la cola
inicio = inicio.sig;
}

public void contenido(){


Cola p;

System.out.println("\n\nImpresion de la cola");
p=inicio;
while(p!=null){
System.out.print(p.info+" --> ");
p=p.sig;
}
System.out.println("");
}

public void leer_datos(){


int n;

while (true)
{
System.out.print("Ingrese numero(10000 para finalizar) ==> ");
n=Leer.datoInt();
if(n==10000) break;

inserta_cola(n);
}
}

Pila.java

// Utiliza la clase Leer que


// deben estar almacenadas en la misma carpeta

class pila {

int info;
pila sig;
pila inicio;
pila fin;

pila(){
inicio = fin = sig = null;
94 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
}

public void anula(){


inicio = fin = null;
}

public void apila(int x)


{
pila nuevo;

nuevo = new pila();

nuevo.info = x;
// Pone al principio de la pila
if(inicio!=null) nuevo.sig = inicio;
inicio = nuevo;
if(fin==null) fin = inicio;

public void desapila()


{

if(inicio==null)
System.out.println("Pila vacia");
else // Quitar del principio de la pila
inicio = inicio.sig;
}

public int cima()


{
if (inicio==null)
return(-10000);
else
return (inicio.info);
}

public void contenido(){


pila p;

System.out.println("impresión de la pila");
p=inicio;
while(p!=null){
System.out.println(p.info);
p=p.sig;
}
System.out.println();
}
}

DemoCola.java
public class DemoCola{
public static void main(String []args)
{
int n;
Cola C=new Cola();
Cola C1=new Cola();
Cola C2=new Cola();

pila P1=new pila();


pila P2=new pila();

C.leer_datos();
C.contenido();

while(C.frente()!=-10000)
{
n=C.frente();

ESTRUCTURA DE DATOS EN JAVA 95


if(n<0)
P1.apila(n);//negativos
else
P2.apila(n);//positivos

C.suprime_cola();
}

P1.contenido();
P2.contenido();

//ingrese elementos a la cola1


while(P1.cima()!=-10000)
{
n=P1.cima();
C1.inserta_cola(n);
P1.desapila();
}

C1.contenido();

//ingrese elementos a la cola2


while(P2.cima()!=-10000)
{
n=P2.cima();
C2.inserta_cola(n);
P2.desapila();
}

C2.contenido();
}
}

96 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


CAPITULO SEIS

ARBOLES

6.1. ÁRBOLES EN GENERAL


Un árbol es una estructura jerárquica aplicada so-
bre una colección de elementos u objetos llamados
nodos; uno de los cuales es conocido como raíz.
Además se crea una relación o parentesco entre los
nodos dando lugar a términos como padre, hijo, her-
mano, antecesor, sucesor, ancestro, etc.

Se usa principalmente cuando hay relaciones entre


los objetos que implican un orden jerárquico entre
ellos. En particular, son ampliamente usados en:

ƒ Teoría de compiladores, para el análisis gra-


matical y sintáctico.

ƒ Bases de Datos Relacionales

ƒ Teoría de algoritmos para diseñar métodos de


ordenamiento y búsqueda eficiente.

ƒ Gestión de memoria externa, etc.

ESTRUCTURA DE DATOS EN JAVA 97


A

B C
E G

D F H
I J K L

Ilustración 1. Diagrama de Venn.


(A (B (D (I), E, F (J, K)), C (G, H (L))))

Ilustración 2. Anidación de paréntesis.

B C

D E F G H

I J K L

Ilustración 3. Grafo.
Gráficamente puede representarse una estructura ár-
bol de diferentes formas y todas ellas equivalen-
tes; por ejemplo: se representa por medio de Dia-
gramas de Venn, por medio de anídación de parénte-
sis y por medio de grafos. Esta última representa-
ción es la que comúnmente se utiliza; y ha origina-
do el término árbol por su parecido abstracto con
el vegetal (raíz, ramas, hojas). Es de notar que en
esta representación la raíz se dibuja arriba, aun-
que en el vegetal se encuentre abajo.

6.2. CARACTERÍSTICAS Y PROPIEDADES DE LOS


ÁRBOLES
Las siguientes son las características y propieda-
des más importantes de los árboles en general:

98 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


ƒ Todo árbol que no es vacío, tiene un único no-
do raíz.

ƒ Un nodo X es descendiente directo de un nodo


Y, si el nodo X es apuntado por el nodo Y. En
este caso es común utilizar la expresión X es
hijo de Y.

ƒ Un nodo X es antecesor directo de un nodo Y,


si el nodo X apunta al nodo Y. En este caso es
común utilizar la expresión X es padre de Y.

ƒ Se dice que todos los nodos que son descen-


dientes directos (hijos) de un mismo nodo (pa-
dre), son hermanos.

ƒ Todo nodo que no tiene ramificaciones (hijos),


se conoce con el nombre de terminal u hoja.

ƒ Todo nodo que no es raíz, ni terminal u hoja


se conoce con el nombre de interior.

ƒ Grado es el número de descendientes directos


de un determinado nodo. Grado del árbol es el
máximo grado de todos los nodos del árbol.

Ejemplo

B C

D E F G H

I J K L

Dado el árbol de la se obtiene:

ƒ A es la raíz del árbol.

ƒ B es hijo de A. C es hijo de A. D es hijo de


B. E es hijo de B. L es hijo de H.

ƒ A es padre de B. B es padre de D. D es padre


de I. C es padre de G. H es padre de L.

ESTRUCTURA DE DATOS EN JAVA 99


ƒ B y C son hermanos. D, E y F son hermanos. G y
H son hermanos. J y K son hermanos.

ƒ I, E, J, K, G y L son nodos terminales u


hojas.

ƒ B, D, F, C y H son nodos interiores.

ƒ El grado del nodo A es 2. El grado del nodo B


es 3. El grado del nodo C es 2. El grado del
nodo D es 1. El grado del nodo E es 0.

ƒ El grado del árbol es 3.

6.3. ARBOL BINARIO


Un árbol binario (ordenado):

ƒ Es un conjunto finito de elementos que está


vacío o divido en tres subconjuntos separados.

ƒ El primer subconjunto contiene un elemento


único llamado raíz del árbol.

ƒ Los otros 2 subconjuntos son por sí mismo ár-


boles binarios y se les conoce como subárboles
izquierdo y derecho del árbol original.

A cada elemento de un árbol binario se denomina no-


do del árbol.

El siguiente árbol contiene 9 nodos donde:

B C

D E F

G H I

ƒ A es la raíz, B es el subárbol izquierdo y C


es el subárbol derecho.

100 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


ƒ El subárbol derecho de la raiz E es vacío, así
como también el subárbol izquierdo de la raíz
C está vacío.

ƒ Los subárboles derecho e izquierdo que están


vacíos son de la raíz D, G, H e I.

6.3.1. DEFINICIONES

Sea A un árbol no vacío con raiz r y sea


ri la raíz de cada subárbol no vacío Ai de
A.
ƒ Se dice que r es el padre de ri y que
ri es un hijo de r.

ƒ El camino del nodo n1 al nodo nk es


la sucesión de nodos n1, n2,...,nk
tales que ni es el padre de ni+1.
para i=1, 2,..., k-1.

n1
n2
N3
……
nk
ƒ El camino n1, n2,...,nk tiene longi-
tud k-1 (igual número de aristas que
conectan los nodos)

ƒ Si existe un camino del nodo n al no-


do m, se dice que n es un antecesor
de m y que m es descendiente de n. Si
la longitud del camino es positiva,
se habla de antecesor y descendientes
propios.

ƒ Una hoja de A es un nodo sin descen-


dientes propios.

ƒ La altura de un nodo es la longitud


del camino más largo del nodo a una
hoja.

ESTRUCTURA DE DATOS EN JAVA 101


ƒ La altura de A es la altura de la
raiz r.

ƒ La profundidad de un nodo es la lon-


gitud del único camino de la raíz al
nodo.

6.4. REPRESENTACIÓN DE ÁRBOLES GENERALES


COMO BINARIOS
A

B C D

E F G H I J K

L M N O

Ilustración 4. Árbol general.


Los mecanismos necesarios para convertir un árbol
general en un árbol binario. Considérese el árbol
general de la Ilustración 4. Los pasos que se deben
aplicar para lograr la conversión del árbol general
al árbol binario son los siguientes:

ƒ Deben enlazarse los hijos de cada nodo en for-


ma horizontal, los hermanos (Ilustración 5).

ƒ Debe enlazarse en forma vertical el nodo padre


con el hijo que se encuentra más a la izquier-
da. Además, debe eliminarse el vínculo de ese
padre con el resto de sus hijos (Ilustración
5).

ƒ Debe rotarse el diagrama resultante, aproxima-


damente 45 grados hacía la ízquierda, y así se
obtendrá el árbol bínarío correspondiente
(Ilustración 6).

102 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


A

B C D

E F G H I J K

L M N O

Ilustración 5. Árbol binario luego de aplicar los dos primeros pasos.

A
B
E
L
F
C
G
M D
H
N
I

J
O
K

Ilustración 6. Árbol binario luego de girar 45 grados hacia la izquierda.

6.5. RECORRIDO DE UN ÁRBOL


La utilidad práctica de un árbol se debe a la posi-
bilidad de almacenar información en sus nodos. En
este caso, es obvio que, para conocer dicha infor-
mación se debe recorrer el árbol visitando cada uno
de sus nodos.

ESTRUCTURA DE DATOS EN JAVA 103


6.5.1. RECORRIDO EN PREORDEN

Conocido tambien como orden previo u orden


de primera profundidad. El recorrido se
basa en:
ƒ Visitar la raíz.

ƒ Recorrer el subárbol izquierdo en


preorden.

ƒ Recorrer el subárbol derecho en pre-


orden.

6.5.2. RECORRIDO EN INORDEN

Llamado tambien como orden simétrico. Su


recorrido es:
ƒ Recorrer el subárbol izquierdo en in-
orden.

ƒ Visitar la raíz.

ƒ Recorrer el subárbol derecho en inor-


den.

6.5.3. RECORRIDO EN POSTORDEN

El orden posterior u postorden se hace de


la siguiente manera:
ƒ Recorrer el subárbol izquierdo en
postorden.

ƒ Recorrer el subárbol derecho en post-


orden.

ƒ Visitar la raíz.

Observación:

104 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


Existe un método "mecánico" para listar los nodos de un
árbol en cada uno de los recorridos descritos. Es el si-
guiente:

ƒ Empezando por la raíz, y avanzando en sentido contra-


rio a las agujas de un reloj, trazar una trayectoria
que se mantenga lo más cerca posible del árbol. En-
tonces:

o En Preorden un nodo se lista la primera vez que


se pasa por él.

o El Inorden, una hoja se lista la primera vez que


se pasa por ella y un nodo interior se lista la
segunda vez que se pasa por él.

o En Postorden, un nodo se lista la última vez que


se pasa por él.

Ejemplo Uno

B C

D E F G

Ilustración 7. Árbol binario.


PreOrden : A B D E C F G

InOrden : D B E A F C G

PostOrden : D E B F G C A

Ejemplo Dos

ESTRUCTURA DE DATOS EN JAVA 105


A

B C

D E F

G H I J

Ilustración 8. Árbol binario.


PreOrden : A B D G K C E H I F J

InOrden : G K D B A H E I C F J

PostOrden : K G D B H I E J F C A

6.6. IMPLEMENTACIÓN DE UN ÁRBOL MEDIANTE


REFERENCIAS
Para implementar un árbol mediante referencias se
puede utilizar la siguiente clase:
public abstract class CArbolBinB{
// Atributos del árbol binario
protected CNodo raíz = null; // raíz del árbol

// Nodo de un árbol binario


private class CNodo{
// Atributos
private Object datos; // referencia a los datos
private CNodo izquierdo; // raíz del subárbol izquierdo
private CNodo derecho; // raíz del subárbol derecho

// Métodos
public CNodo(){} // constructor
}

// Métodos
……………………………
}

Gráficamente un nodo esta compuesto por el campo


donde se almacena la información (datos) y dos pun-
teros para los subárboles izquierdo y derecho.

106 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


DATOS
Referencia izq Referencia der
El árbol de la Ilustración 7 se representaría como:

B C

X D X X E X X F X X G X

6.6.1. IMPLEMENTACIÓN DEL RECORRIDO PREOR-


DEN
public void preorden(CNodo raíz){
CNodo actual=null;

actual=raíz;
if(actual!=null){
procesar(actual.datos);
preorden(actual.izquierdo);
preorden(actual.derecho);
}
}

Para el árbol de la Ilustración 7 su reco-


rrido es:
Nodo
vi
Nodo Pila: Rama pen-
si- Rama a
Paso ac- diente a visi-
ta visitar
tual tar
d
o
1 A A AÆizq=B AÆder=C (1)
2 B B BÆizq=D BÆder=E (2)
3 D D DÆizq=NULL DÆder=NULL (3)
4 NULL
5 (3) NULL
6 (2) E E EÆizq=NULL EÆder=NULL (4)
7 NULL
8 (4) NULL
9 (1) C C CÆizq=F CÆder=G (5)
10 F F FÆizq=NULL FÆder=NULL (6)
11 NULL
12 (6) NULL
13 (5) G G GÆizq=NULL GÆder=NULL (7)
14 NULL
15 (7) NULL

ESTRUCTURA DE DATOS EN JAVA 107


En la columna PILA: RAMA PENDIENTE DE VI-
SITAR, la llamada (N) indica el orden en
el cual las ramas pendientes de visitar
fueron introducidas en la pila. En la co-
lumna NODO ACTUAL la llamada (N) indica la
rama extraída de la pila.

El orden en que los nodos fueron visitados


es: A B D E C F G.

6.6.2. IMPLEMENTACIÓN DEL RECORRIDO INORDEN


public void inorden(CNodo raíz){
CNodo actual=null;

actual=raíz;
if(actual!=null){
inorden(actual.izquierdo);
procesar(actual.datos);
inorden(actual.derecho);
}
}

Para el árbol de la Ilustración 7 su reco-


rrido es:
Nodo
Rama a Pila: Rama pendien-
Paso Nodo actual visi-
visitar te a visitar
tado
(1)
AÆder=C (
1 A AÆizq=B
A 2
)
(3)
BÆder=E (
2 B BÆizq=D
B 4
)
(5)
DÆder=NULL (
3 D DÆizq=NULL
D 6
)
4 NULL D (6)
5 (5) NULL B (4)
(7)
EÆder=NULL (
6 (3) E EÆizq=NULL
E 8
)
7 NULL E (8)
8 (7) NULL A (2)
(9)
(
CÆder=G
9 (1) C CÆizq=F 1
C
0
)
108 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
Nodo
Rama a Pila: Rama pendien-
Paso Nodo actual visi-
visitar te a visitar
tado
(11)
(
FÆder=NULL
10 F FÆizq=NULL 1
F
2
)
11 NULL F (12)
12 (11) NULL C (10)
(13)
(
GÆder=NULL
13 (9) G GÆizq=NULL 1
G
4
)
14 NULL G (14)
15 (13) NULL

6.6.3. IMPLEMENTACIÓN DEL RECORRIDO POSTOR-


DEN
public void posorden(CNodo raíz){
CNodo actual=null;

actual=raíz;
if(actual!=null){
posorden(actual.izquierdo);
posorden(actual.derecho);
procesar(actual.datos);
}
}

Para el árbol de la Ilustración 7 su reco-


rrido es:
Nodo
Rama a Pila: Rama pendien-
Paso Nodo actual visi-
visitar te a visitar
tado
(1)
A (
1 A AÆizq=B
AÆder=C 2
)
(3)
B (
2 B BÆizq=D
BÆder=E 4
)
(5)
D
(
3 D DÆizq=NULL DÆder=N
6
ULL
)
4 NULL
5 (6) NULL D (5)
(7)
E
(
6 (4) E EÆizq=NULL EÆder=N
8
ULL
)
7 NULL
8 (8) NULL E (7)
ESTRUCTURA DE DATOS EN JAVA 109
Nodo
Rama a Pila: Rama pendien-
Paso Nodo actual visi-
visitar te a visitar
tado
9 B (3)
(9)
(
C
10 (2) C CÆizq=F 1
CÆder=G
0
)
(11)
F (
11 F FÆizq=NULL FÆder=N 1
ULL 2
)
12 NULL
13 (12) NULL F (11)
(13)
G (
14 (10) G GÆizq=NULL GÆder=N 1
ULL 4
)
15 NULL
16 NULL G (13)
17 C (9)
18 A (1)
6.7. ÁRBOL BINARIO DE BÚSQUEDA
El árbol binario de búsqueda es una estructura so-
bre la cual se pueden realizar eficientemente las
operaciones de búsqueda, inserción y eliminación.
Comparando esta estructura con otras, pueden obser-
varse ciertas ventajas. Por ejemplo, en un arreglo
es posible localizar datos eficientemente si los
mismos se encuentran ordenados, pero las operacio-
nes de inserción y eliminación resultan costosas.
En las listas, las operaciones de inserción y eli-
minación se pueden llevar a cabo con facilidad, sin
embargo la búsqueda es una operación bastante cos-
tosa que incluso nos puede llevar a recorrer todos
los elementos de ella para localizar uno en parti-
cular.

Formalmente se define un árbol binario de búsqueda


de la siguiente manera: "Para todo nodo T del árbol
debe cumplirse que todos los valores de los nodos
del subárbol izquierdo de T deben ser menores o
iguales al valor del nodo T. De forma similar, to-
dos los valores de los nodos del subárbol derecho
de T deben ser mayores o iguales al valor del nodo
T".
110 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
La Ilustración 9 contiene un árbol binario de bús-
queda.

120

87 140

43 99 130

22 65 93 135

56

Ilustración 9. Árbol binario de búsqueda


Observe que si en dicho árbol se sustituye el valor
140 del nodo por 160, 99 por 105 y 43 por 55; el
árbol continúa siendo un árbol binario de búsqueda.
Ahora bien, si en dicho árbol se remplaza el valor
87 del nodo por 125, entonces el árbol deja de ser
un árbol binario de búsqueda puesto que viola el
principio que dice que: "Todos los nodos del subár-
bol izquierdo del nodo T deben ser menores o igua-
les al nodo T" (en este caso 125 no es menor a
120).

También es posible observar que si se efectúa un


recorrido inorden sobre un árbol de búsqueda se ob-
tendrá una clasificación de los nodos en forma as-
cendente. El recorrido inorden del árbol de la
Ilustración 9 produce el siguiente resultado:

22 43 56 65 87 93 99 120 130 135 140

6.7.1. INSERCIÓN EN UN ARBOL BINARIO DE


BÚSQUEDA

La inserción es una operación que se puede


realizar eficientemente en un árbol bina-
rio de búsqueda. La estructura crece con-
forme se inserten elementos al árbol. Los
pasos que deben realizarse para insertar
un elemento a un árbol binario de búsqueda
son los siguientes:
ESTRUCTURA DE DATOS EN JAVA 111
1. Debe compararse la clave a insertar
con la raíz del árbol. Si es mayor,
debe avanzarse hacia el subárbol dere-
cho. Si es menor, debe avanzarse hacia
el subárbol izquierdo.

2. Repetir sucesivamente el paso 1 hasta


que se cumpla alguna de las siguientes
condiciones:
2.1. El subárbol derecho es igual a
vacío, o el subárbol izquierdo
es igual a vacío; en cuyo caso
se procederá a insertar el ele-
mento en el lugar que le corres-
ponde.

2.2. La clave que quiere insertarse


es igual a la raíz del árbol; en
cuyo caso no se realiza la in-
serción.

Ejemplo

Para insertare las siguientes claves en un


árbol binario de búsqueda que se encuentre
vacío: 120, 87, 43, 65, 140, 99, 130, 22,
56.

Los resultados parciales que ilustran cómo


funciona el procedimiento se presentan a
continuación:

112 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


Inserción: clave 120 Inserción: clave 87

120

120

87

Inserción: Clave 43 Inserción: Clave 65

120 120

87 87

43 43

65

Inserción: Clave 140 Inserción: Clave 99

120 120

87 140 87 140

43 43 99

65 65

Inserción: Clave 130 Inserción: Clave 22

120 120

87 140 87 140

43 99 130 43 99 130

65 22 65

ESTRUCTURA DE DATOS EN JAVA 113


Inserción: Clave 56

120

87 140

43 99 130

22 65

56

Las líneas gruesas indican el elemento que


acaba de insertarse.

6.7.2. BORRADO EN UN ARBOL BINARIO DE BÚS-


QUEDA

La operación de borrado es un poco más


complicada que la de inserción. Ésta con-
siste en eliminar un nodo del árbol sin
violar los principios que definen justa-
mente un árbol binario de búsqueda. Se de-
be distinguir los siguientes casos:

1. Si el elemento a borrar es terminal u


hoja, simplemente se suprime.

2. Si el elemento a borrar tiene un solo


descendiente, entonces tiene que sus-
tituirse por ese descendiente.

3. Si el elemento a borrar tiene los dos


descendientes, entonces se debe susti-
tuir por el nodo que se encuentra más
a la izquierda en el subárbol derecho
o por el nodo que se encuentra más a
la derecha en el subárbol izquierdo.

114 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


Ejemplo

Supóngase que se desea eliminar las si-


guientes claves: 22, 99, 87, 120, 140,
135, 56; del árbol binario de búsqueda de
la Ilustración 10.
120

87 140

43 99 130

22 65 93 135

56

Ilustración 10. Árbol binario de búsqueda donde se elimirá sus nodos.

Los resultados parciales que ilustran cómo


funciona el procedimiento se presentan a
continuación:
Eliminación: Clave 22 Eliminación: Clave 99

120 120

87 140 87 140

43 99 130 43 99 130

22 65 93 135 65 93 135

56 56

ESTRUCTURA DE DATOS EN JAVA 115


Eliminación: Clave 87 Eliminación: Clave 120

120 120

87 140 65 140

43 93 130 43 93 130

65 135 56 135

56

Eliminación: Clave 140 Eliminación: Clave 135, 56

93 93

65 140 65 130

43 130 43 135

56 135 56

93

65 130

43

Las flechas con líneas gruesas indican el


elemento a eliminar.

116 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


6.8. CLASE GENERICA PARA LA IMPLEMENTACIÓN
DE ARBOLES CON REFERENCIAS

Clase abstracta para el árbol binario de búsqueda


// Clase abstracta: árbol binario de búsqueda. Para utilizar los
// métodos proporcionados por esta clase, tendremos que crear
// una subclase de ella y redefinir los métodos:
// comparar, procesar y visitarInorden.

public abstract class CArbolBinB{


// Atributos del árbol binario
protected CNodo raíz = null; // raíz del árbol

// Nodo de un árbol binario


private class CNodo{
// Atributos
private Object datos; // referencia a los datos
private CNodo izquierdo; // raíz del subárbol izquierdo
private CNodo derecho; // raíz del subárbol derecho

// Métodos
public CNodo(){} // constructor
}

// Posibles errores que se pueden dar relativos a un nodo


public static final int CORRECTO=000;
public static final int NO_DATOS=100;
public static final int YA_EXISTE=101;
public static final int NO_EXISTE=102;

// Métodos del árbol binario


public CArbolBinB(){} // constructor

// El método siguiente debe ser redefinido en una subclase para


// que permita comparar dos nodos del árbol por el atributo
// que necesitemos en cada momento.
public abstract int comparar(Object obj1,Object obj2);

// El método siguiente debe ser redefinido en una subclase para


// que permita especificar las operaciones que se deseen
// realizar con el nodo visitado.
public abstract void procesar(Object obj);

// El método siguiente debe ser redefinido en una subclase para


// que invoque a insertar con los argumentos deseados.
public abstract void visitarInorden();
public abstract void visitarPosorden();
public abstract void visitarPreorden();

public Object buscar(Object obj){


// El método buscar permite acceder a un determinado nodo.
CNodo actual = raíz;
int nComp=0;

// Buscar un nodo que tenga asociados los datos dados por obj
while(actual!=null){
if ((nComp=comparar(obj,actual.datos))==0)
return(actual.datos); // CORRECTO (nodo encontrado)
else if(nComp<0) // buscar en el subárbol izquierdo
actual = actual.izquierdo;
else // buscar en el subárbol derecho
actual = actual.derecho;
}
return null; // NO_EXISTE
}

public int insertar(Object obj){


ESTRUCTURA DE DATOS EN JAVA 117
// El método insertar permite añadir un nodo que aún no está
// en el árbol.
CNodo último=null,actual=raíz;
int nComp=0;

if (obj==null) return NO_DATOS;

// Comienza la búsqueda para verificar si ya hay un nodo con


// estos datos en el árbol
while(actual!=null){
if ((nComp = comparar(obj,actual.datos ))==0)
break; // se encontró el nodo
else{
último = actual;
if ( nComp < 0 ) // buscar en el subárbol izquierdo
actual = actual.izquierdo;
else // buscar en el subárbol derecho
actual = actual.derecho;
}
}

if (actual==null){ // no se encontró el nodo, añadirlo


CNodo nuevoNodo=new CNodo();
nuevoNodo.datos=obj;
nuevoNodo.izquierdo=nuevoNodo.derecho=null;

// El nodo a añadir pasará a ser la raíz del árbol total si


// éste está vacío, del subárbol izquierdo de "último" si la
// comparación fue menor,o del subárbol derecho de "último" si
// la comparación fue mayor.
if (último==null) // árbol vacío
raíz = nuevoNodo;
else if(nComp<0)
último.izquierdo = nuevoNodo;
else
último.derecho = nuevoNodo;

return CORRECTO;
} // fin del bloque if (actual==null)
else // el nodo ya existe en el árbol
return YA_EXISTE;
}

public Object borrar(Object obj){


// El método borrar permite eliminar un nodo del árbol.
CNodo último=null,actual=raíz;
CNodo marcado=null,sucesor=null;
int nAnteriorComp=0, nComp = 0;

if (obj==null) return null; // NO_DATOS

// Comienza la búsqueda para verificar si hay un nodo con


// estos datos en el árbol.
while(actual!=null){
nAnteriorComp=nComp; // resultado de la comparación anterior
if((nComp=comparar(obj,actual.datos))==0)
break; // se encontró el nodo
else{
último = actual;
if ( nComp < 0 ) // buscar en el subárbol izquierdo
actual = actual.izquierdo;
else // buscar en el subárbol derecho
actual = actual.derecho;
}
} // fin del bloquewhile (actual!=null)

if(actual!=null){ // se encontró el nodo


marcado = actual;
if ((actual.izquierdo==null && actual.derecho==null))

118 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


// se trata de un nodo terminal (no tiene descendientes)
sucesor=null;
else if(actual.izquierdo==null ) // nodo sin subárbol izquierdo
sucesor=actual.derecho;
else if(actual.derecho==null) // nodo sin subárbol derecho
sucesor=actual.izquierdo;
else{// nodo con subárbol izquierdo y derecho
// Referencia al subárbol derecho del nodo a borrar
sucesor=actual=actual.derecho;
// Descender al nodo más a la izquierda en el subárbol
// derecho de este nodo (el de valor más pequeño) y hacer
// que el subárbol izquierdo del nodo a borrar sea ahora
// el subárbol izquierdo de este nodo.
while(actual.izquierdo!=null)
actual=actual.izquierdo;
actual.izquierdo=marcado.izquierdo;
}

// Eliminar el nodo y rehacer los enlaces


if(último!= null){
if(nAnteriorComp<0)
último.izquierdo = sucesor;
else
último.derecho = sucesor;
}
else
raíz = sucesor;

return marcado.datos; // CORRECTO


// "marcado" será enviado a la basura
}
else // el nodo buscado no está en el árbol
return null; // NO_EXISTE
}

public void inorden( CNodo r,boolean nodoRaíz){


// El método recursivo inorden visita los nodos del árbol
// utilizando la forma inorden; esto es, primero se visita
// el subárbol izquierdo, después se visita la raíz, y por
// último, el subárbol derecho.
// Si el segundo parámetro es true, la visita comienza
// en la raíz independientemente del primer parámetro.

CNodo actual=null;

if(nodoRaíz)
actual=raíz; // partir de la raíz
else
actual=r; // partir de un nodo cualquiera
if(actual!=null){
inorden(actual.izquierdo,false ); // visitar subárbol izq.
// Procesar los datos del nodo visitado
procesar(actual.datos);
inorden(actual.derecho,false); // visitar subárbol dcho.
}
}

public void preorden(CNodo r,boolean nodoRaíz){


// El método recursivo preorde visita los nodos del árbol
// utilizando la forma preorden; esto es, primero se visita
// la rai, despues el subárbol izquierdo, y por
// último, el subárbol derecho.
// Si el segundo parámetro es true, la visita comienza
// en la raíz independientemente del primer parámetro.

CNodo actual=null;

if(nodoRaíz)
actual=raíz; // partir de la raíz
else
actual=r; // partir de un nodo cualquiera
if(actual!=null){

ESTRUCTURA DE DATOS EN JAVA 119


// Procesar los datos del nodo visitado
procesar(actual.datos);
preorden(actual.izquierdo,false ); // visitar subárbol izq.
preorden(actual.derecho,false); // visitar subárbol dcho.
}
}

public void posorden( CNodo r,boolean nodoRaíz){


// El método recursivo inorden visita los nodos del árbol
// utilizando la forma inorden; esto es, primero se visita
// el subárbol izquierdo, después el subárbol derecho, y por
// último, se visita la raíz.
// Si el segundo parámetro es true, la visita comienza
// en la raíz independientemente del primer parámetro.

CNodo actual=null;

if(nodoRaíz)
actual=raíz; // partir de la raíz
else
actual=r; // partir de un nodo cualquiera
if(actual!=null){
posorden(actual.izquierdo,false ); // visitar subárbol izq.
posorden(actual.derecho,false); // visitar subárbol dcho.
// Procesar los datos del nodo visitado
procesar(actual.datos);
}
}
}

Clase derivada de la clase abstracta CArbolBinB


// Clase derivada de la clase abstracta CArbolBinB.Redefine los
// métodos: comparar, procesar, visitarInorden y visitarPosorden
// y visitarPreorden

public class CArbolBinarioDeBusqueda extends CArbolBinB{


// Permite comparar dos nodos del árbol por el atributo
// nombre.
public int comparar(Object obj1, Object obj2){
String str1 = new String(((CDatos)obj1).obtenerNombre());
String str2 = new String(((CDatos)obj2).obtenerNombre());
return str1.compareTo(str2);
}

// Permite mostrar los datos del nodo visitado.


public void procesar(Object obj){
String nombre = new String(((CDatos)obj).obtenerNombre());
double nota = ((CDatos)obj).obtenerNota();
System.out.println(nombre+" "+nota);
}

// Visitar los nodos del árbol.


public void visitarInorden(){
// Si el segundo argumento es true, la visita comienza
// en la raíz independientemente del primer argumento.
inorden(null, true);
}

public void visitarPosorden(){


// Si el segundo argumento es true, la visita comienza
// en la raíz independientemente del primer argumento.
posorden(null, true);
}

public void visitarPreorden(){


// Si el segundo argumento es true, la visita comienza
// en la raíz independientemente del primer argumento.
preorden(null, true);
120 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
}
}

Clase CDatos
public class CDatos{
// Atributos
private String nombre;
private double nota;

// Métodos
public CDatos(){} // constructor sin parámetros
public CDatos(String nom,double n){ // constructor con parámetros
nombre = nom;
nota = n;
}

public void asignarNombre(String nom){


nombre = nom;
}

public String obtenerNombre(){


return nombre;
}

public void asignarNota(double n) {


nota = n;
}

public double obtenerNota(){


return nota;
}
}

Clase Test
Esta clase premite crear el arbol binario.
// Crear un árbol binario de búsqueda

public class Test{


public static void main(String[] args){
CArbolBinarioDeBusqueda arbolbb=new CArbolBinarioDeBusqueda();

// Leer datos y añadirlos al árbol


String nombre;
double nota;
int i=0,cod;
System.out.println("Introducir datos. Finalizar con Ctrl+Z.");
System.out.print("nombre: ");
while ((nombre = Leer.dato())!= null){
System.out.print("nota: ");
nota = Leer.datoDouble();
cod=arbolbb.insertar(new CDatos(nombre,nota));
if (cod == CArbolBinarioDeBusqueda.YA_EXISTE){
// Si ya existe, distinguimos dos casos:
// 1. nota nueva >= 0; cambiamos la nota
// 2. nota nueva < 0; borramos el nodo
CDatos datos = (CDatos)arbolbb.buscar(new
CDatos(nombre,nota));
if (nota>=0)
datos.asignarNota(nota);
else{
if (arbolbb.borrar(new CDatos(nombre,nota))==null)
System.out.println("no borrado porque no existe");
else
System.out.println("nodo borrado");
}
}
System.out.print("nombre: ");
ESTRUCTURA DE DATOS EN JAVA 121
}
System.out.println("\n");

// Mostrar los nodos del árbol


System.out.println("\nArbol Inorden:");
arbolbb.visitarInorden();
System.out.println("\nArbol posorden:");
arbolbb.visitarPosorden();
System.out.println("\nArbol preorden:");
arbolbb.visitarPreorden();
}
}

122 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


CAPITULO SIETE

ORDENAMIENTO Y BÚSQUEDA

7.1. ORDENAMIENTO
Consiste en organizar los datos en algún orden da-
to, tal como ascendente o descendente los datos a
ordenar tienen que ser del mismo tipo como: numéri-
cos, alfabéticos, alfanuméricos, fechas.

Si la siguiente lista de "N" elementos esta ordena-


da ascendentemente:

A1, A2, A3, A4, ... , AN

entonces:

A1<=A2<=A3<=A4<= ... <=AN

7.2. CLASES DE ORDENAMIENTO


Se consideran dos:

1. Ordenamiento interno: Tiene lugar con todos los


datos en la memoria RAM del computador. Clara-
mente, es aplicado sólo para un número razonable
de datos. Los métodos de este tipo se agrupan en
dos subclases.
1.1. Métodos directos
ESTRUCTURA DE DATOS EN JAVA 123
1.2. Métodos avanzados

2. Ordenamiento externo: Tiene lugar con una parte


de los datos en la memoria RAM del computador y
la otra en un almacenamiento secundario. Clara-
mente, es aplicado a enormes volúmenes de datos
(Todos los métodos son avanzados).
7.3. MÉTODOS DIRECTOS DE ORDENAMIENTO
Las características principales de estos métodos
son las siguientes:

1. Se realizan IN SITU; es decir, con los datos al-


macenados en un arreglo durante todo el proceso
de ordenamiento.

2. Los algoritmos que los describen son muy sim-


ples.

3. Se aplican a pequeños números de datos o a un


moderado número de datos si el ordenamiento se
realiza pocas veces.

7.3.1. ORDENAMIENTO POR INTERCAMBIO DIREC-


TO. MÉTODO DE LA BURBUJA.

Consiste en comparar dos elementos conse-


cutivos e intercambiarlos cuando estén
desubicados. La comparaciones pueden
hacerse de del primer elemento al último
elemento o viceversa.

Después de realizar el primer recorrido,


comparar los elementos consecutivos del
primer elemento al último se tiene que el
último elemento esta en posición correcta.
En el segundo recorrido se compara los
elementos consecutivos del primer elemento
al penúltimo elemento, no se considera el
último por que ya esta ordenado, al termi-
nar el recorrido los dos últimos elementos
están ordenados. En el tercer recorrido se
compara los elementos consecutivos del
primer elemento al antepenúltimo elemento,
124 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
no se considera el último ni el antepenúl-
timo por que ya están ordenados, al termi-
nar este recorrido los tres últimos ele-
mentos están ordenados. Las comparaciones
continúan hasta ordenar los el primero con
el segundo elemento.

Burbuja de izquierda a derecha

Esta versión va colocando en cada pasada


el mayor elemento de los tratados en la
última posición, quedando en su posición
correcta y por lo tanto excluido de los
elementos a tratar en el siguiente reco-
rrido.
A0 A1 A2 A3 A4
Secuencia inicial 3 2 4 1 2
1er recorrido 2 3 1 2 4
2do Recorrido 2 1 2 3 4
3er Recorrido 1 2 2 3 4
4to Recorrido 1 2 2 3 4

SEUDOCODIGO
Para i= n-2 hasta 0 incremento -1 hacer
Para j= 0 hasta i hacer
Si datos[j]>datos[j+1] entonces
cambio(datos[j],datos[j+1])
Finsi
Finpara
Finpara

Donde: Si se llama al función cambio de


la siguiente manera: cambio(A,B);
y los valores de sus parámetros
son: A=1 y B=5. Al terminar la
función los valores de las varia-
bles serán intercambiadas a: A=5 y
B=1.

Burbuja de derecha a izquierda


Es una versión simetrica de la anterior
desplazando los elementos menores hacia la
izquierda.
A0 A1 A2 A3 A4
Secuencia inicial 3 2 4 1 2
1er recorrido 1 3 2 4 2
2do Recorrido 1 2 3 2 4
3er Recorrido 1 2 2 3 4
ESTRUCTURA DE DATOS EN JAVA 125
4to Recorrido 1 2 2 3 4

SEUDOCODIGO
Para i= 1 hasta n-1 hacer
Para j=n-1 hasta i incremento -1 hacer
Si datos[j-1]>datos[j] entonces
cambio(datos[j-1],datos[j])
Finsi
Finpara
Finpara

Ordenamiento por inserción directa

Este método también es conocido como el


método de la baraja. Consiste en repetir
el siguiente proceso desde el segundo ele-
mento hasta el último elemento: se toma
dicho elemento y se inserta en el lugar
que le corresponda entre los elementos si-
tuados a la izquierda (que ya están orde-
nados). Los elementos superiores a la tra-
tada se desplazaran un lugar a la derecha.
A0 A1 A2 A3 A4
Secuencia inicial 3 2 4 1 2
Se ubica A1 2 3 4 1 2
Se ubica A2 2 3 4 1 2
Se ubica A3 1 2 3 4 2
Se ubica A4 1 2 2 3 4

SEUDOCODIGO
Para i=1 hasta n-1 hacer
aux=datos[i]
j=i-1
Mientras datos[j]>aux y j>0 hacer
datos[j+1]=datos[j]
j=j-1
FinMientras
Si datos[j]>aux entonces
datos[j+1]=datos[j]
datos[j]=aux
sino
datos[j+1]=aux
FinSi
FinPara

Ordenamiento por selección directa

Consiste en repetir el siguiente proceso


desde el primer elemento hasta el penúlti-
mo. Se selecciona la componente de menor
valor de todas las situadas a la derecha

126 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


de la tratada (si que existe) y se inter-
cambian con esta.
A0 A1 A2 A3 A4
Secuencia inicial 3 2 4 1 2
Se intercambia A0 y A3 1 2 4 3 2
No se intercambia A1 1 2 4 3 2
Se intercambia A2 y A4 1 2 2 3 4
No se intercambia A3 1 2 3 3 4

SEUDOCODIGO
Para i=0 hasta n-2 hacer
k=i
aux=datos[i]
Para j=i+1 hasta n-1 hacer
Si datos[j]<aux entonces
k=j
aux=datos[j]
FinSi
FinPara
datos[k]=datos[i]
datos[i]=aux
FinPara

7.4. MÉTODOS AVANZADOS DE ORDENAMIENTO:


Las características principales de estos métodos
son las siguientes:

1. Se aplican para un número grande de datos ya que


para pocos elementos son ineficientes.

2. Los intercambios de datos se realizan a grandes


distancias.

3. Los algoritmos que los describen son complica-


dos.

7.4.1. ORDEMAMIENTO CON EL MÉTODO DE SHELL

Consiste en comprar los elementos separa-


dos una misma distancia, si los elementos
no se encuentran ordenados se intercambian
sus valores. La distancia inicial es la
mitad de las longitud del vector. La dis-
tancia de comparación se reduce a la mitad
cuando ya no existen intercambios a esa
distancia. El proceso se repite hasta que
la distancia sea 1.

ESTRUCTURA DE DATOS EN JAVA 127


DISTANCIA DE COMPARACIÓN:

D=parte_entera(9/2)=4
A0 A1 A2 A3 A4 A5 A6 A7 A8
Secuencia inicial 3 2 4 6 7 3 5 1 1
1era Comparación 3 2 4 1 1 3 5 6 7
2da Comparación 1 2 4 1 3 3 5 6 7

DISTANCIA DE COMPARACIÓN:

D=parte_entera(4/2)=2
A0 A1 A2 A3 A4 A5 A6 A7 A8
Secuencia inicial 1 2 4 1 3 3 5 6 7
1era Comparación 1 2 4 1 3 3 5 6 7
2da Comparación 1 1 3 2 4 3 5 6 7

DISTANCIA DE COMPARACIÓN:

D=parte_entera(2/2)=1
A0 A1 A2 A3 A4 A5 A6 A7 A8
Secuencia inicial 1 1 3 2 4 3 5 6 7
1era Comparación 1 1 2 3 3 4 5 6 7

SEUDOCODIGO
d=n
Repetir
d=Parte_entera(d/2)
Repetir
sw=0
i=0
Repetiir
i=i+1
Si a[i]>a[i+d] entonces
cambio(a[i],a[i+d])
sw=1
Finsi
Hasta i+d=n
Hasta sw=0
Hasta d=1

Donde: Si se llama al función cambio de


la siguiente manera: cambio(A,B);
y los valores de sus parámetros
son: A=1 y B=5. Al terminar la
función los valores de las varia-
bles serán intercambiadas a: A=5 y
B=1.

128 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


7.4.2. ORDENAMIENTO RÁPIDO (QUICK SORT)

Es un algoritmo que elige un valor llamado


comparando y entonces divide a los elemen-
tos en dos partes: una parte todos los
elementos mayores o iguales que el compa-
rando y en la otra parte todos los meno-
res. Este proceso se repite para cada tro-
zo restante hasta que los elementos queden
ordenados. Su implementación requiere del
uso de la recursividad.
Medio A0 A1 A2 A3 A4 A5 A6 A7 A8 A9

1er Paso 55 86 3 10 23 12 67 59 47 31 24

2do Paso 35 24 3 10 23 12 31 47 59 67 86
<>
3er Paso 27 24 3 10 23 12 31 47 59 67 86
<> <>
4to Paso 18 24 3 10 23 12 31 47 59 67 86
<> <>
5to Paso 11 12 3 10 23 24 31 47 59 67 86
<> <>
6to Paso 6 10 3 12 23 24 31 47 59 67 86
<> <> <> <> <>
7to Paso 23 3 10 12 23 24 31 47 59 67 86
<> <> <> <> <> <> <>
8vo Paso 72 3 10 12 23 24 31 47 59 67 86
<> <> <> <> <> <> <> <>
9no Paso 63 3 10 12 23 24 31 47 59 67 86
<> <> <> <> <> <> <> <> <> <>
Orden final 3 10 12 23 24 31 47 59 67 86

Ilustración 11. Algoritmo de ordenamiento rápido.

Este algoritmo comienza estimando un valor


medio, podría ser el promedio de los ele-
mentos extremos. El valor del punto medio
no es crucial; el algoritmo trabajara con
cualquier punto medio. No obstante, cuando
más cerca esté el punto medio estimado del
valor medio del arreglo, más rápida será
la ordenación.

El procedimiento calcula un punto medio a


partir de la media aritmética de los ele-
mentos primero y último de la porción del
arreglo que se va a ordenar. Uma vez que
el procedimiento selecciona un punto me-
dio, coloca en la parte inferior del arre-
ESTRUCTURA DE DATOS EN JAVA 129
glo los elementos que están por debajo de
dicho punto medio y los que están por en-
cima en la parte superior, como se muestra
en la Ilustración 11.

En el paso 1, el punto medio es 55, la me-


dia entre 86 y 24. En el paso 2, el seg-
mento a ordenar va desde 24 hasta 47, con
el punto medio igual a 35. Observe que
llos elementos del segmento raramente se
distribuyen uniformemente con relación al
punto medio. Esto no perjudica al procedi-
miento, pero disminuye su eficiencia.

En cada paso del proceso, la ordenación


rápida ordena los elementos de un segmento
del array alrededor del valor del punto
medio. A medida que los segmentos se hacen
más y más pequeños, el arreglo se aproxima
a su forma totalmente ordenada.

SEUDOCODIGO
quicksort(data[],inf,sup)
/* data es el arreglo a ordenar
inf y sup son los indices izquierdo
y derecho respectivamente que definen
la porción del arreglo a ordenar */
INICIO

left=inf;
right=sup;
half=data[parte_entera((left+right)/2)];
Mientras left<right hacer
Mientras data[left]<half y
left<sup hacer
left++;
FinMientras
Mientras half<data[right] y
right>inf)
right--;
FinMientras
Si left<right entonces
cambio(data[left],data[right])
FinSi
left=left+1
right=right-1
FinMientras
Si inf<right entonces
quicksort(data, inf, right)
FinSi
Si left<sup entonces
quicksort(data, left, sup)
FinSi
FIN

130 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


Donde: Si se llama al función cambio de
la siguiente manera: cambio(A,B);
y los valores de sus parámetros
son: A=1 y B=5. Al terminar la
función los valores de las varia-
bles serán intercambiadas a: A=5 y
B=1.

Para llamar a la función se utiliza:


quicksort(datos,0,n-1)

Se ordena los elementos desde el indice 0


al indice n-1, es decir, los n elementos
del arreglo.
7.5. PROGRAMA CON LOS ALGORITMOS DE
ORDENAMIENTO

Clase Ordenamiento
public class Ordenamiento extends ArregloUni{
public void burbuja_der_izq(){
int i,j;

for (i=1;i<=n-1 ;i++)


for (j=n-1;j>=i;j--)
if (a[j-1]>a[j])
cambio(a,j-1,j);
}

public void burbuja_izq_der(){


int i,j;

for (i=n-2;i<=0 ;i--)


for (j=0;j<=i;j++)
if (a[j]>a[j+1])
cambio(a,j,j+1);
}

public void baraja(){


int i,j,aux;

for(i=1;i<=n-1;i++){
aux=a[i];
j=i-1;
while (a[j]>aux && j>0){
a[j+1]=a[j];
j=j-1;
}
if(a[j]>aux){
a[j+1]=a[j];
a[j]=aux;
}
else a[j+1]=aux;
};
}

public void seleccion_directa(){


int i,j,k,aux;

for(i=0;i<=n-2;i++){
k=i;
ESTRUCTURA DE DATOS EN JAVA 131
aux=a[i];
for(j=i+1;j<=n-1;j++)
if(a[j]<aux){
k=j;
aux=a[j];
}
a[k]=a[i];
a[i]=aux;
}
}

public void shell(){


int d,i,sw;

d=n;
do{
d=d/2;
do{
sw=0;
i=-1;
do{
i++;
if(a[i]>a[i+d]){
cambio(a,i,i+d);
sw=1;
}
} while(i+d!=n);
} while(sw!=0);
} while(d!=1);
}

public void quicksort(int data[],int inf,int sup){


int left,right;
double half;

left=inf;
right=sup;
half=data[(left+right)/2];

while (left<right){
while(data[left]<half && left<sup) left++;
while(half<data[right] && right>inf) right--;
if (left<right) cambio(data,left,right);
left++;
right--;
}
if (inf<right) quicksort(data, inf, right);
if (left<sup) quicksort(data, left, sup);
}

public void cambio(int []a, int pos1, int pos2){


int t;

t=a[pos1];
a[pos1]=a[pos2];
a[pos2]=t;
}
}

Clase DemoOrdenamiento
public class DemoOrdenamiento{
public static void main(String []args){
Ordenamiento vector=new Ordenamiento();

int sw,opcion;

vector.ingreso();
sw=1;
132 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
do{
System.out.println(
"\n\n\n\nSeleccione el algoritmo de ordenamiento\n");
System.out.println("0. Salir");
System.out.println("1. Burbuja de derecha a izquierda");
System.out.println("2. Burbuja de izquierda a derecha");
System.out.println("3. Inserción directa (Baraja)");
System.out.println("4. Seleccion directa");
System.out.println("5. Método de shell");
System.out.println("6. Ordenamiento rápido");
System.out.print("Opcion ==> ");
opcion=Leer.datoInt();
if(opcion>0){
System.out.println("Arreglo antes de ordenar");
vector.reporte();
}

switch(opcion){
case 0: sw=0;break;
case 1: vector.burbuja_der_izq();break;
case 2: vector.burbuja_izq_der();break;
case 3: vector.baraja();break;
case 4: vector.seleccion_directa();break;
case 5: vector.shell();break;
case 6: vector.quicksort(vector.a,0,vector.n-1);break;
}
if(opcion>0){
System.out.println("Arreglo despues de ordenar");
vector.reporte();
}
}while(sw==1);
}
}

7.6. MEZCLA CONTROLADA POR FIN DE ARCHIVO


Sean dos archivos Fl y F2, con registros de igual
estructura y ordenados por el campo .clave C (C1
para el registro RI de F1 y C2 para el registro R2
de F2). Se desea obtener F ordenado por el mismo
campo, que contenga los registros de ambos.

El algoritmo consiste en el recorrido simultáneo de


FI y F2, copiando el registro menor de ambos en F y
avanzando en el archivo correspondiente. Se contro-
la la terminación de los archivos por medio de dos
switches SW1 y SW2.

A la salida del bucle de fusión, uno de los dos ar-


chivos no habrá sido copiado en su totalidad, por
lo que es necesario añadir dos bucles de copia para
completar la fusión con el resto del archivo no co-
piado. El procesador detecta cuál es el archivo no
completado por el valor de su switch.

Este algoritmo se puede generalizar para N archivos


ordenados, aunque es recomendable, en este caso,
realizar sucesivas fusiones de dos en dos, por la
complejidad del mismo.
ESTRUCTURA DE DATOS EN JAVA 133
SEUDOCODIGO
Abrir F1 para lectura
Abrir F2 para lectura
Abrir F para escritura
sw1=0
sw=0
Si FF(F1)entonces
sw=1
Sino
Leer F1, R1
FinSi
Si FF(F2) entonces
sw=1
Sino
Leer F2, R2
FinSi
Mientras sw1=0 y sw2=0 hacer
Si C1<C2 entonces
Escribir F, R1
Si FF(F1) entonces
sw1=1
Sino
Leer F1,R1
FinSi
Sino
Escribir F, R2
Si FF(F2) entonces
sw2=1
Sino
Leer F2, R2
FinSi
FinSi
FinMientras
Si swl=0 entonces
Iterar
Escribir F, R1
Salir si FF(F1)
Leer F1, R1.
FinIterar
FinSi
Si sw2=0 entonces
Iterar
Escribir F, R2
Salir si FF(F2)
Leer F2, R2
FinIterar
FinSi
Cerrar F1, F2, F

7.7. CLASIFICACIÓN DE ARCHIVOS


(ORDENAMIENTO EXTERNO)
Se dice que un archivo está clasificado ascendente
o descendentemente si tiene todos sus registros en
secuencia ascendente o descendente respecto al va-
lor de un campo que denominamos clave de ordena-
ción.

Un algoritmo de clasificación tiene por objeto re-


distribuir los registros para que se cumpla la con-
dición de ordenación.
134 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
Si el archivo a ordenar, por su tamaño, cabe ínte-
gramente en la memoria central, se carga en una ta-
bla y se realiza una clasificación interna, recopi-
lando el resultado en el archivo original.

Las clasificaciones externas se realizan si el ar-


chivo no cabe en la memoria central, teniendo la
desventaja de que su tiempo de ejecución es mucho
mayor por la gran cantidad te operaciones de entra-
da y salida que conlleva.

Algunos algoritmos de clasificación son una combi-


nación de ordenación externa a interna, aprovechan-
do al máximo la capacidad de la memoria central.

7.7.1. CLASIFICACIÓN POR MEZCLA DIRECTA

Se trata de la realización sucesiva de una


partición y una mezcla que produce secuen-
cias ordenadas de longitud cada vez mayor.

La primera partición se hace en secuencias


de longitud 1, y la fusión correspondiente
produce sobre el archivo inicial secuen-
cias ordenadas de longitud 2.

A cada nueva partición y fusión, se dupli-


ca la longitud de las secuencias ordenada.

El proceso termina cuando la longitud de


la secuencia ordenada excede la longitud
del archivo a ordenar.

Ejemplo

Sea un archivo F cuyos valores del campo


clave son los que figuran a continuación.
Se utilizan dos archivos auxiliares F1 y
F2 con la misma estructura que F, para
realizar las sucesivas particiones y fu-
siones.
F:
15, 18, 7, 75, 14, 13, 43, 40, 51, 93, 75, 26, 64, 27, 13

Partición en secuencias de longitud 1


F1: 15, 7, 14, 43, 51, 75, 64, 13
F2: 18, 75, 13, 40, 93, 26, 27

ESTRUCTURA DE DATOS EN JAVA 135


Fusión de secuencias de longitud 1:
F:
15,18, 7,75, 13,14, 40,43, 51,93, 26,75,.27,64, 13

Partición en secuencias de longitud 2


F1: 15,18, 13,14, 51,93, 27,64
F2: 7,75, 40,43, 26,75, 13

Fusión de secuencias de longitud 2:


F:
7,15,18,75, 13,14,40,43, 26,51,75,93, 13,27,64

Partición en secuencias de longitud 4


F1: 7,15,18,75, 26,51,75,93
F2: 13,14,40,43, 13,27,64

Fusión de secuencias de longitud 4:


F:
7,13,14,15,18,40,43,75, 13,26,27,51,64,75,93

Partición en secuencias de longitud 8


F1: 7,13,14,15,18,40,43,75
F2: 13,26,27,51,64,75,93

Fusión de secuencias de longitud 8:


F:
7,13,13,14,15,18,26,27,40,43,51,64,75,75,93

El proceso termina al detectarse que la


nueva longitud de la secuencia para parti-
ción es mayor o igual que el número de re-
gistros de F.

7.7.2. CLASIFICACIÓN POR MEZCLA EQUILIBRADA

Es una optimización del método anterior


consistente en realizar la partición to-
mando las secuencias ordenadas de máxima
longitud posible y realizando la fusión de
secuencias ordenadas alternativamente so-
bre dos archivos, lo que hace que la si-
guiente partición quede realizada.

Utiliza tres archivos auxiliares, junto


con el original, siendo alternativamente
dos de ellos de entrada y los otros dos de
136 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
salida para la realización simultánea de
fusión y partición.

Durante el proceso de fusión-partición,


dos o más secuencias ascendentes, que es-
tén consecutivas, pueden constituir una
única secuencia para el paso siguiente.

El proceso termina cuando, en la realiza-


ción de una fusión-partición, el segundo
archivo queda vacío. El archivo totalmente
ordenado estará en el primero.

Ejemplo

Sea F el archivó a ordenar, y F1, F2 y F3


los auxiliares. Con las mismas claves del
ejemplo anterior, el proceso es el si-
guiente.
F:
15, 18, 7, 75, 14, 13, 43, 40, 51, 93, 75, 26, 64, 27, 13

F1:

Partición inicial
F2: 15,18, 14, 40,51,93, 26,64, 13
F3: 7,75, 13,43, 75, 27

Primera fusión-partición
F : 7,15,18,75, 26,27,64
F1: 13,14,40,43,51,75,93, 13

Segunda fusión-partición
F2: 7,13,14,15,18,40,43,51,75,75,93
F3: 13,26,27,64

Tercera fusión-partición
F :
7,13,13,14,15,18,26,27,40,43,51,64,75,75,93
F1:

7.7.3. CLASIFICACIÓN DE RAÍZ

Se utiliza para claves de ordenación numé-


ricas. Consiste en distribuir los regis-
tros en diez archivos auxiliares, numera-
dos del 0 al 9, según el dígito de la cla-
ve que corresponde al número de pasada que
se esta realizando. A continuación se con-
ESTRUCTURA DE DATOS EN JAVA 137
catenan los diez archivos en el archivo
original.

Los dígitos de la clave se toman de dere-


cha a izquierda, completándose la ordena-
ción en tantos pasos como dígitos tenga el
campo clave.

Ejemplo

Sea F el archivo de los ejemplos anterio-


res, y F0, F1,.., F8, F9 los diez archivos
auxiliares. El procesó necesitará dos pa-
sadas compuestas por una partición y una
concatenación:
F:
15, 18, 07, 75, 14, 13, 43, 40, 51, 93, 75, 26, 64, 27, 13

Primera partición
F0: 40
F1: 51
F2:
F3: 13,43,93,13
F4: 14,64
F5: 15,75,75,
F6: 26
F7: 07,27
F8: 18
F9:

Primera concatenación:
F:
40,51,13,43,93,13,14,64,15,75,75,26,07, 27,18

Segunda partición
F0: 07
F1: 13,13,14,15,18
F2: 26,27
F3:
F4: 40,43
F5: 51
F6: 64
F7: 75,75
F8:
F9: 93

Segunda concatenación:
F:
07,13,13,14,15,18,26,27,40,43,51,64,75,
75,93

138 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


7.8. BÚSQUEDA
Se denomina búsqueda cuando queremos obtener la po-
sición donde se encuentra el elemento o si es desea
saber si esta almacenado en la estructura.

La búsqueda de uno o más elementos es una de las


tareas más frecuentes en computación. Por tanto se
requieren el conocimiento de métodos que hagan más
eficiente el proceso.

7.8.1. DEFINICIONES

1. Un algoritmo de búsqueda es un algo-


ritmo que acepta un argumento a y tra-
ta de encontrar un registro con llave
a. Si lo encuentra, retorna dicho re-
gistro o un puntero al registro; en
caso contrario retorna "un registro
nulo".

2. Un algoritmo de búsqueda e inserción


es un algoritmo de búsqueda tal que si
no encuentra al registro con llave da-
da a, lo inserta en el conjunto de da-
tos.

7.8.2. CLASES DE BÚSQUEDA

Como en el ordenamiento hay dos clases de


búsqueda:

1. Búsqueda interna: Tiene lugar con to-


dos los datos en la memoria RAM del
computador. Mencionaremos dos técni-
cas:

a. Búsqueda secuencial

b. Búsqueda binaria

2. Búsqueda externa: Tiene lugar con una


parte de los datos en la memoria RAM
del computador y la otra en un almace-
namiento secundario (disco).

ESTRUCTURA DE DATOS EN JAVA 139


7.9. BÚSQUEDA SECUENCIAL
Es la más simple y es aplicable preferentemente,
cuando los datos están desordenados pero almacena-
dos en un arreglo o en una lista enlazada.

Consiste en recorrer el arreglo de izquierda a de-


recha hasta encontrar una componente cuyo valor co-
incida el buscado o hasta a llegar al último ele-
mento. Este algoritmo generalmente es usado cuando
los datos no están ordenados y para buscar la pri-
mera ocurrencia. En los casos que existan elementos
con valores repetidos iguales iguales al valor bus-
cado el algoritmo retorna el indice del primero que
encuentra.

SEUDOCODIGO
El siguinete algoritmo retorna el indice en el
arreglo donde es encontrado el “dato”, caso contra-
rio retorna -1.
i=0;
Mientras (dato<>vec[i]) y (i<n) hacer
i=i+1
FinMientras
Si dato=vec[i] entonces
posicion=i
Sino
posicion=-1
FinMientras

Donde: Dato es el valor a buscar en el arreglo


unidimensional.

7.10. BÚSQUEDA BINARIA


Es la búsqueda que usamos en los diccionarios o las
guías telefónicas, en los cuales las llaves (pala-
bras o nombres, en estos casos) están ordenadas,
permitiendo seleccionar una página, por ejemplo la
de cerca de la mitad, comparar la llave dada con
alguna palabra de dicha página y según el resultado
de la comparación avanzar en el sentido apropiado.

Es un algoritmo que trabaja con arrays ordenados.


Consiste en comparar el elemento que ocupa la posi-
ción central, si no es igual al valor buscado se
reduce el intervalo de búsqueda a la mitad derecha
140 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
o izquierda, según donde se pueda encontrase el va-
lor a buscar. El algoritmo termina si se encuentra
el valor buscado o si el termino del intervalo de
búsqueda queda anulado. En los casos que existan
elementos con valores repetidos iguales al valor
buscado este algoritmo obtendrá uno de ellos alea-
toriamente según los lugares que ocupen las cuales
necesariamente son consecutivos.

SEUDOCODIGO
El siguiente algoritmo retorna la posición del ele-
mento que coincide con el buscado o -1 si no esta
en el vector.
inf=0
sup=n-1
sw=0
Mientras (sup>inf) y (sw=0) hacer
cen=Parte_entera((sup+inf)/2)
Si dato>datos[cen] entonces
inf=cen+1
Sino
si dato<datos[cen] entonces
sup=cen-1
Sino
sw=1
Finsi
FinSi
FinMientras
Si sw=1 entonces
posicion=cen
Sino
posicion=-1
Finsi

Donde: dato es el valor a buscar en el vector.

7.11. PROGRAMA CON LOS ALGORITMOS DE


BÚSQUEDA

Clase Búsqueda
public class Busqueda extends ArregloUni{
public int busqueda_secuencial(int dato){
int i,posicion;

i=0;
while(dato!=a[i] && i<n) i++;
if (dato==a[i]) posicion=i;
else posicion=-1;
return posicion;
}

public int busqueda_binaria(int dato){


int inf,sup,sw,cen=0,posicion;

inf=0;
sup=n-1;
sw=0;
ESTRUCTURA DE DATOS EN JAVA 141
while(sup>=inf && sw==0){
cen=(sup+inf)/2;
if(dato>a[cen]) inf=cen+1;
else if(dato<a[cen]) sup=cen-1;
else sw=1;
}
if(sw==1) posicion=cen;
else posicion=-1;
return posicion;
}

public void quicksort(int data[],int inf,int sup){


int left,right;
double half;

left=inf;
right=sup;
half=data[(left+right)/2];

while (left<right){
while(data[left]<half && left<sup) left++;
while(half<data[right] && right>inf) right--;
if (left<right) cambio(data,left,right);
left++;
right--;
}
if (inf<right) quicksort(data, inf, right);
if (left<sup) quicksort(data, left, sup);
}

public void cambio(int []a, int pos1, int pos2){


int t;

t=a[pos1];
a[pos1]=a[pos2];
a[pos2]=t;
}
}

Clase DemoBusqueda
public class DemoBusqueda{
public static void main(String []args){
Busqueda vector=new Busqueda();

int sw,opcion,x=0,pos=0;

vector.ingreso();
sw=1;
do{
System.out.println("\n\n\n\nSeleccione el algoritmo de
Busqueda\n");
System.out.println("0. Salir");
System.out.println("1. Busqueda secuencial");
System.out.println("2. Búsqueda binaria");
System.out.print("Opcion ==> ");
opcion=Leer.datoInt();
if(opcion>0){
System.out.print("Elemento a buscar: ");
x=Leer.datoInt();
}
switch(opcion){
case 0: sw=0;break;
case 1:
System.out.println("Contenido del arreglo");
vector.reporte();
pos=vector.busqueda_secuencial(x);
break;
case 2:
142 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno
vector.quicksort(vector.a,0,vector.n-1);
System.out.println("Contenido del arreglo (ordenado)");
vector.reporte();
pos=vector.busqueda_binaria(x);
break;
}
if(opcion>0)
if(pos!=-1)
System.out.println("Esta en la posición: "+pos);
else
System.out.println("No se encuentra en el arreglo");
}while(sw==1);
}
}

7.12. EFICIENCIA DE LOS ALGORITMOS DE


ORDENAMIENTO Y BÚSQUEDA
Seymour Lipschutz, en su libro Estructura de Datos,
nos dice: "Analizar algoritmos es una de las tareas
mas costosas en el diseño de estos. Para comparar
dos algoritmos que solucionan el mismo problema es
necesario aportar criterios que midan la eficiencia
de ambos. ... Supongamos que "M" es el algoritmo y
que "n" es el tamaño de los datos de entrada. El
tiempo de ejecución y el espacio utilizado por "M",
son los parámetros principales que miden la efi-
ciencia de "M". El tiempo suele medirse contando el
número de operaciones clave realizadas. Por ejem-
plo: En una ordenación o búsqueda, el numero de
comparaciones realizadas. Esto es debido a que su-
ponemos que el tiempo empleado en aquellas otras
operaciones que no consideramos clave es menor o a
lo sumo proporcional al empleo por estas. El espa-
cio es evaluado contando el máximo de memoria nece-
saria por el algoritmo".

De los algoritmos de ordenación o búsqueda expues-


tos líneas arriba, se puede deducir que todos uti-
lizan aproximadamente la misma cantidad de memoria.
Por esa razón concluimos:

ALGORITMO CASO PEOR CASO MEDIO


n(n - 1) n(n - 1)
De la burbuja
2 2
n(n - 1) n(n - 1)
Por inserción
2 4
n(n - 1) n(n - 1)
Por selección
2 2
n(n - 1)
Ordenamiento rápido 1,4(n * log2 n)
2
ESTRUCTURA DE DATOS EN JAVA 143
(n + 1)
Búsqueda secuencial n
2
Búsqueda binaria log2 n ≈ log 2 n

La eficiencia se mide en base a las comparaciones


necesarias realizadas para ordenar la lista, el nu-
mero de comparaciones tiene relación directa con la
cantidad de elementos y el numero de comparaciones
tiene relación directa con el tiempo, a más elemen-
tos se requiere más comparaciones y tiempo.

144 Mg. Daniel Gamarra Moreno - Mg. Abraham Gamarra Moreno


BIBLIOGRAFÍA

1. AHO, ALFRED; HOPCROFT, JHON y ULLMAN JEFFREY (1988). “ES-

TRUCTURA DE DATOS Y ALGORITMOS”. Ed. Addison-Wesley Iberoa-

mericana S.A. E.U.A.

2. ALLEN WEISS, MARK (2000). “ESTRUCTURA DE DATOS EN JAVA”. Ed.

Addison Wesley. España.

3. CAIRO, O y GUARDATI S. (1988). “ESTRUCTURA DE DATOS”. Ed.

McGraw Hill. España.

4. LANGSAM; AUGENSTEIN y TENENBAUM (1997). “ESTRUCTURA DE

DATOS CON C Y C++”. Ed. Prentice Hall.

5. WIRTH, NIKLAUS (1987). “ALGORITMOS Y ESTRUCTURA DE DATOS”.

Ed. Prentice Hall. México.

ESTRUCTURA DE DATOS EN JAVA 145

Vous aimerez peut-être aussi