0% encontró este documento útil (0 votos)
41 vistas

Manual de Prácticas-ProgramaciónII

Este manual presenta 8 prácticas de programación para el curso de Programación II. La primera sección presenta los lineamientos del laboratorio y el sistema de evaluación. Las prácticas cubren temas como herencia, interfaces, colecciones de objetos, tiempos de ejecución de algoritmos, uso de pilas, colas, árboles y manejo de archivos. El objetivo es que los estudiantes aprendan conceptos avanzados de programación orientada a objetos y estructuras de datos para gestionar información de forma dinámica en la industria del software

Cargado por

ireneico
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
41 vistas

Manual de Prácticas-ProgramaciónII

Este manual presenta 8 prácticas de programación para el curso de Programación II. La primera sección presenta los lineamientos del laboratorio y el sistema de evaluación. Las prácticas cubren temas como herencia, interfaces, colecciones de objetos, tiempos de ejecución de algoritmos, uso de pilas, colas, árboles y manejo de archivos. El objetivo es que los estudiantes aprendan conceptos avanzados de programación orientada a objetos y estructuras de datos para gestionar información de forma dinámica en la industria del software

Cargado por

ireneico
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 61

UNIVERSIDAD AUTÓNOMA DEL ESTADO DE MÉXICO

Manual de Prácticas de
Programación II

Irene Aguilar Juárez marzo del 2023


Elaboró: Gerardo Alexis Villavicencio Pérez Fecha:

H. Consejo Académico H. Consejo de Gobierno


Fecha de
aprobación
ÍNDICE

Aparatados Pág.

PRIMERA SECCIÓN
Lineamientos del Laboratorio
Presentación (Introducción)
Sistema de Evaluación
SEGUNDA SECCIÓN
Compendio y Presentación: 6
Práctica 1: Herencia simple 7
Objetivo 7
Introducción Teórica 7
Ejercicio para realizar 11
Evaluación: 11
Evidencia: 11
Referencias 11
Práctica 2: Interfaces y Clases abstractas 12
Objetivo: 12
Introducción Teórica: 12
Ejemplo 13
Ejercicios 17
Evidencia de trabajo: 18
Referencias: 18
Práctica 3: Colecciones de Objetos e Iteradores 19
Objetivo: El alumno conocerá y usará las Colecciones de Objetos de uso más
común en java. 19
Introducción Teórica 19
Ejemplo 22
Procedimiento 26
Evaluación y evidencia: 26
Referencias 26
Práctica 4: Tiempos de ejecución de algoritmos de ordenamiento y búsqueda.
27
Introducción Teórica: 27
Procedimiento 31
Evaluación: 32
Evidencia para obtener: 32
Referencias 32
Práctica 5: Uso de Pilas 34
Objetivo: 34
Introducción Teórica: 34
Ejercicio 39
Evaluación 39
Evidencia 39
Referencias 39
Practica 6: Uso de Colas 40
Objetivo: 40
Introducción Teórica: 40
Ejemplo 42
Ejercicio a realizar 45
Evaluación 45
Evidencia: 45
Referencias 45
Práctica 7: Árboles 46
Objetivo: 46
Introducción Teórica: 46
Ejemplo 50
Ejercicio a realizar 53
Evaluación: 53
Evidencia: 53
Práctica 8: Manejo de archivos y procesamiento de datos. 54
Introducción Teórica: 54
Procedimiento 58
Evaluación: 59
Evidencia a obtener: 59
Referencias 59
ANEXO 60
Universidad Autónoma del Estado de México Centro
Universitario UAEM Texcoco
REGLAMENTO PARA ACCESO Y USO DE LOS LABORATORIOS Y SALAS DE CÓMPUTO

1.-Los servicios de sala de uso general, laboratorios de microcomputadoras y especializados son para
uso exclusivo de horas clase y procedimientos institucionales que los requieran.

2.- El registro de usuarios de sala de uso general, laboratorios de microcomputadoras y especializados


para horas clase y procedimientos institucionales es de carácter obligatorio para el personal docente,
así como para sus alumnos.

3.-Queda estrictamente prohibido introducir bebidas y/o alimentos en los laboratorios de cómputo.

4.-Queda estrictamente prohibido fumar dentro de las instalaciones de los Laboratorios de Cómputo.

5.-Los objetos personales (mochilas, bolsas, etc.) de los usuarios no deben colocarse sobre la mesa del
equipo de cómputo.

6.-Si hay necesidad de instalar software específico, deberá solicitarse a los RTIC (Responsable de
Tecnologías de la Información y Comunicaciones) con 5 días hábiles de anticipación, proporcionando lo
requerido (software, licencia en caso de no ser software libre y método de instalación en caso de
requerir alguna configuración especial).

7.-Toda información deberá ser almacenada en alguna unidad de almacenamiento externo propio del
usuario, ya que los equipos cuentan con un freeze que al reiniciar el equipo restaura su
configuración anterior borrando cambios o información guardada en dicho equipo.

8.-Por ningún motivo se deshabilitará el freeze de los laboratorios.

9.-Cada equipo solo podrá ser utilizado por dos personas como máximo.

10.- Por ningún motivo se permitirá el acceso a los alumnos al Laboratorio sin la presencia de su
profesor.

11.-El profesor deberá permanecer dentro del espacio durante su estancia hasta que el último alumno
se retire o finalice la sesión de laboratorio.

12.-Queda prohibido cambiar la configuración de las computadoras (tapices, colores de pantalla,


punteros, password, sistema operativo, etc.) y/o desconectar el equipo y sus componentes.

13.-Toda persona que sea sorprendida sustrayendo accesorios, equipamiento, mobiliario, cambiando
configuraciones y/o desconectando equipo de cómputo, será presentada ante la autoridad
competente.

14.-El uso de internet en el laboratorio deberá ser requerido y justificado al iniciar la sesión por el
profesor y este será de uso estrictamente académico por lo tanto no se podrá acceder a
ningún tipo de chat, páginas de contenido pornográfico, snuff, o páginas de descarga, música, videos,
redes sociales,
deportes y/o juegos a menos que el programa de estudios lo especifique.

15.-La tolerancia de acceso a los laboratorios es de 15 minutos después de la hora marcada, en caso de
que haya alguna solicitud de uso de laboratorio, este será asignado por ausencia de grupo o profesor.

16.-En caso de existir algún desperfecto, daño o faltante con respecto a equipo de cómputo, mobiliario
o infraestructura de sala de uso general y Laboratorios, deberá de ser notificado al RTIC y/o personal a
cargo por parte del profesor para levantar el reporte y dar el seguimiento necesario a este.

17.-Es responsabilidad propia del usuario todo objeto olvidado dentro del laboratorio.

18.-Es responsabilidad del profesor mantener el orden dentro del laboratorio.

19.-El acceso a los laboratorios será proporcionado única y exclusivamente por el RTIC y/o el personal a
cargo.

20.-Es responsabilidad del profesor solicitar y entregar la(s) listas de registro debidamente llenadas
(una lista por laboratorio), así como notificar de inmediato cualquier faltante, anomalía o
desperfecto encontrado o suscitado durante su sesión, de lo contrario se hará responsable al
grupo anterior al momento del reporte.

21.- El usuario deberá apagar el equipo de cómputo al terminar la sesión de clases.

22.- El profesor deberá cerrar la(s) puertas del Laboratorio colocando seguro y notificar a la persona a
cargo de su salida la cual deberá ser con al menos cinco minutos de anticipación de la hora límite de su
clase para que el Laboratorio sea revisado por el RTIC y/o el personal a cargo.
NOTA: En caso de incumplir el presente reglamento, se girará el reporte a las autoridades universitarias
correspondientes.
Compendio y Presentación:

Las necesidades contemporáneas de la industria del software son cada vez más
demandantes y complejas. La industria y la empresa requieren sistemas
computacionales que de forma dinámica gestione información importante.

Para hacer frente a las demandas de la industria es importante que los profesionistas
conozcan los conceptos básicos de complejidad computacional, los algoritmos de
ordenamiento, de búsqueda, del almacenamiento permanente de la información y los
principios de operación de las estructuras dinámicas lineales y no lineales.

En la unidad de aprendizaje Programación II, se tratan los conceptos complementarios


de la programación orientada a objetos, además del estudio de las estructuras de datos
para capacitar a los alumnos en los tópicos avanzados de la gestión de la memoria
dinámica y del almacenamiento permanente.

Este manual se compone de prácticas que abordan 4 unidades temáticas:


1. Conceptos suplementarios de la programación orientada a objetos
2. Ordenamiento y búsqueda
3. Estructura de datos lineales y no lineales
4. Manejo de archivos

Las prácticas aquí planteadas llevarán al alumno poco a poco a dominar los
conocimientos necesarios para aplicar en los programas computacionales más
significativos. El estudio de los temas de la unidad puede ampliarse de acuerdo con las
decisiones del profesor con apoyo en las referencias que se anexan en el documento.
Práctica 1: Herencia simple

U. Competencia 1: Conceptos suplementarios de programación orientada a objetos


Duración Estimada: 2 sesión de 50 minutos

Objetivo
Identificar y usar las propiedades de la herencia simple como estrategia de
reutilización de código

Introducción Teórica
La herencia provee el mecanismo más simple para especificar una forma alternativa de
acceso a una clase existente, o para definir una nueva clase que añada nuevas
características a una clase existente. Esta nueva clase se denomina subclase o clase
derivada de la clase existente, superclase o clase base. Las clases que están en la
parte inferior en la jerarquía heredan de las clases que están en la parte superior de la
jerarquía.
En una jerarquía de clases, una clase es tanto más especializada cuanto más alejada
esté de la raíz. Y es tanto más genérica cuando más cerca esté de la raíz. Por ejemplo,
la clase Object es la raíz de la jerarquía de las clases de Java y sólo define los atributos
y comportamientos comunes a todas las clases.
Generalmente, la razón de la existencia de una clase genérica es proporcionar los
atributos y comportamientos que serán compartidos por todas las subclases. En la
siguiente imagen se observa la clase Mueble que representa todas las propiedades y
métodos comunes de los muebles que se venden en una mueblería y la silla representa
las propiedades específicas de todas las sillas de la mueblería. Obsérvese que se usa
la línea que significa es un. para indicar que la Silla es un Mueble. Para codificar es
importante reconocer la jerarquía de las clases ya que se deben codificar primero las
clases de mayor jerarquía y al final las clases más especializadas.
A través de la herencia, la POO permite definir la clase Silla como una extensión de
Mueble. Los siguientes puntos resumen las reglas a tener en cuenta cuando se define
una subclase:
1. Una subclase hereda todos los miembros de su superclase, excepto los
constructores. Una consecuencia inmediata de esto es que la estructura interna de
datos de un objeto de una subclase estará formada por los atributos que ella define y
por los heredados de su superclase. Una subclase no tiene acceso directo a los
miembros privados de su superclase. Una subclase si puede acceder directamente a
los miembros públicos y protegidos de su superclase, también puede acceder a los
miembros predeterminados
2. Una subclase puede añadir sus propios atributos y métodos. Si el nombre de alguno
de estos miembros coincide con el de un miembro heredado, este último queda oculto
para la subclase, que se traduce en que la subclase ya no puede acceder directamente
a ese miembro.
3. Los miembros heredados por una subclase pueden, a su vez, ser heredados por más
subclases de ella. A esto se le llama programación de herencia. Los métodos de una
subclase no tienen acceso a los miembros privados de su superclase, pero sí lo tiene a
sus miembros protegidos y públicos, y si la subclase pertenece al mismo paquete que la
superclase, también tiene acceso a sus miembros predeterminados. Si una subclase
tuviera acceso a los miembros privados de su superclase, entonces cualquiera podría
acceder a los miembros privados de una clase, simplemente derivando una clase de
ella. Consecuentemente, si una subclase quiere acceder a los miembros privados de
su subclase, debe hacerlo a través de la interfaz pública, protegida, o predeterminada
en su caso, de dicha superclase.
Constructores de las subclases.
Cuando se tiene una relación subclase-superclase, al momento de construir un objeto
de una subclase, se invoca a su constructor, que a su vez invoca al constructor sin
parámetros de la superclase, que a su vez invoca al constructor de su superclase, y así
sucesivamente.
Ahora bien, si se han definido constructores con parámetros tanto en subclases como
en superclases, tal vez se desee construir un objeto de la subclase iniciándolo con unos
valores predeterminados. Esto permite que el constructor de subclase invoque
explícitamente al constructor de la superclase. Esto se hace utilizando la palabra
reservada “super”.
public nombre_subclase (lista de parámetros incluyendo los que se requieren para la super clase){
super(lista de parámetros);
//cuerpo del constructor de la subclase.
}

Cuando desde un constructor de una subclase se invoca al constructor de su


superclase, esta línea tiene que ser la primera. La sintaxis y los requerimientos son
análogos a los utilizados con “this” cuando se llama a otro constructor de la misma
clase.
Si la superclase no tiene un constructor en forma explícita o tiene uno que no requiere
parámetros, no se necesita invocarlo explícitamente, ya que Java lo invocará
automáticamente mediante “super()” sin argumentos.
Por ejemplo, en la clase Silla se tiene el constructor:
super(numserie, modelo, preciocosto, precioventa,existencia);

Esta línea llama al constructor de Mueble, superclase de Silla. Por lo que Silla debe
tener un constructor con cinco parámetros del tipo de los argumentos especificados
Cuando se crea un objeto de una subclase, por ejemplo “sillaSecretarial1” o
“sillaEjecutiva2”, primero se construye la porción del objeto correspondiente a su
superclase y a continuación la porción del objeto correspondiente a la subclase.
Ejemplo de Codificación
Con base en el diagrama anterior el código queda de la siguiente forma:
Código de la clase Mueble
public class Mueble {
//Atributos
private String numSerie; private String modelo;
private float precioCosto; private float precioVenta;
private int existencias;

//Constructor
public Mueble(String numSerie, String modelo, float precioCosto, float precioVenta, int existencias) {
this.numSerie = numSerie; 10
this.modelo = modelo;
this.precioCosto = precioCosto;
this.precioVenta = precioVenta;
this.existencias = existencias;
}
//Setters y Getters
public String getNumSerie() { return numSerie; }
public void setNumSerie(String numSerie) { this.numSerie = numSerie; }
public String getModelo() { return modelo; }
public void setModelo(String modelo) { this.modelo = modelo; }
public float getPrecioCosto() { return precioCosto; }
public void setPrecioCosto(float precioCosto) { this.precioCosto = precioCosto; }
public float getPrecioVenta() { return precioVenta; }
public void setPrecioVenta(float precioVenta) { this.precioVenta = precioVenta; }
public int getExistencias() { return existencias; }
public void setExistencias(int existencias) { this.existencias = existencias; }

@Override
public String toString() {
return "Mueble{" + "numSerie=" + numSerie + ", modelo=" + modelo + ", precioCosto=" + precioCosto
+ ", precioVenta=" + precioVenta + ", existencias=" + existencias + '}';
} }

Código de la clase Silla


Obsérvese que para usar la herencia se debe usar la palabra reservada extends y se
debe invocar al constructor de la clase padre con la palabra super en la primera
instrucción de su constructor
public class Silla extends Mueble {
//Atributos
private String material;
private int numPatas;
//Constructor
public Silla(String material, String numSerie, String modelo, float precioCosto, float precioVenta, int
existencias) {
super(numSerie, modelo, precioCosto, precioVenta, existencias);
this.material = material; }
//Setters y Getters
public String getMaterial() { return material; }
public void setMaterial(String material) { this.material = material; }
public int getNumPatas() { return numPatas; }
public void setNumPatas(int numPatas) { this.numPatas = numPatas; }

@Override
public String toString() {
String datosDelPadre=super.toString();
String datosDeHijo="Silla{" + "material=" + material + ", numPatas=" + numPatas + '}';
return datosDeHijo.concat(datosDelPadre); } }
Ejercicio para realizar 11
Con base en el ejemplo anterior codifica la siguiente jerarquía de clases, por el poco
espacio no se incluyeron los métodos getters y setters de las clases, pero en el código
no debes omitirlos
Incluye la codificación de la clase main

Evaluación:
Aciertos: 10 puntos por clase codificada

Evidencia:
Jerarquía terminada y ejecución del proyecto evaluado por el profesor

Referencias
Sznajdleder, Pablo Augusto, Java a fondo: estudio del lenguaje y desarrollo de aplicaciones. - 2a ed. Buenos
Aires: Alfaomega Grupo Editor Argentino, 2013, 456 p; ISBN 978-987-1609-36-9
Guardati Buemo Silvia, (2007). “Estructura De Datos Orientada A Objetos, Algoritmos Con C++]”, Pearson
Educación.
Guardati Buemo Silvia. (2016). Estructuras de datos básicas programación orientada a objetos con
Java. Alfaomega Grupo Editor
Práctica 2: Interfaces y Clases abstractas 12
U. Competencia 1: Conceptos suplementarios de programación orientada a objetos
Duración Estimada: 2 sesión de 50 minutos

Objetivo:
Conocer y usar las clases abstractas y las Interfaces.

Introducción Teórica:
Una de las características más útiles de cualquier lenguaje orientado a objetos es la
posibilidad de declarar clases que definen como se utilizan solamente, sin tener que
implementar métodos. Esto es muy útil cuando la implementación es específica para
cada usuario, pero todos los usuarios tienen que utilizar los mismos métodos. Un
ejemplo de clase abstracta en Java es la clase Graphics:
public abstract class Graphics {
public abstract void drawLine( int x1,int y1,int x2, int y2 );
public abstract void drawOval( int x,int y,int width, int height );
public abstract void drawArc( int x,int y,int width, int height,int startAngle,int arcAngle );
...
}

Los métodos se declaran en la clase Graphics, pero el código que ejecutará el método
está en algún otro sitio:
public class MiClase extends Graphics {
public void drawLine( int x1,int y1,int x2,int y2 ) {
<código para pintar líneas -específico de
la arquitectura->
}
}

Cuando una clase contiene un método abstracto tiene que declararse abstracta. No
obstante, no todos los métodos de una clase abstracta tienen que ser abstractos. Las
clases abstractas no pueden tener métodos privados (no se podrían implementar) ni
tampoco estáticos. Una clase abstracta tiene que derivarse obligatoriamente, no se
puede hacer un new de una clase abstracta.
Una clase abstracta en Java es lo mismo que en C++ virtual func() = 0; lo que obliga a
que al derivar de la clase haya que implementar forzosamente los métodos de esa clase
abstracta.
Interfaces: Los métodos abstractos son útiles cuando se quiere que cada
implementación de la clase parezca y funcione igual, pero necesita que se cree una
nueva clase para utilizar los métodos abstractos.
Los interfaces proporcionan un mecanismo para abstraer los métodos a un nivel
13
superior. Una Interface contiene un conjunto de métodos que se implementan en otras
clases de acuerdo a las necesidades específicas de cada clase implementadoras. Los
métodos de una clase son public, static y final.
La principal diferencia entre Interface y abstract es que un Interface proporciona un
mecanismo de encapsulación de los protocolos de los métodos sin forzar al usuario a
utilizar la herencia.

Ejemplo

En el diagrama siguiente se tiene la Interface RegistroContable que es implementada


por dos clases diferentes Vendedor y Mesero. Para codificar se debe iniciar con el nivel
mayor, es decir con la Interface y después las clases implementadoras

package restaurante;

public interface RegistroContable {


public void registroUsuario();
public void registroVentasS(float venta);
public float calculaPago();
}

Las clases que quieran utilizar la Interface RegistroContable utilizarán la palabra


implements y proporcionarán el código necesario para implementar los métodos que
se han definido para la Interface:
package restaurante;
14
import java.util.Date;
public class Mesero implements RegistroContable {
private String nombre;
private String rfc;
private Date fecIngreso;
private float propinas;
private float montoServicio;

public Mesero(String nombre, String rfc, Date fecIngreso) {


this.nombre = nombre;
this.rfc = rfc;
this.fecIngreso = fecIngreso;
this.propinas = 0.0f;
this.montoServicio = 0.0f;
}
public void registroUsuario(){
System.out.println("Ingresando el rfc a la base contable del Restaurant");
}

public void registroVentasS(float ventaNueva){ montoServicio+=ventaNueva; }

public float calculaPago(){


propinas+=montoServicio*0.1;
return propinas;
}

public String getNombre() { return nombre; }


public void setNombre(String nombre) { this.nombre = nombre; }
public String getRfc() { return rfc; }
public void setRfc(String rfc) { this.rfc = rfc; }
public Date getFecIngreso() { return fecIngreso; }
public void setFecIngreso(Date fecIngreso) { this.fecIngreso = fecIngreso; }
public float getPropinas() { return propinas; }
public void setPropinas(float propinas) { this.propinas = propinas; }
public float getMontoServio() { return montoServicio; }
public void setMontoServio(float montoServio) { this.montoServicio = montoServio; }
}

package restaurante;

import java.util.Date;

public class Vendedor implements RegistroContable {

private String nombre;


private String rfc;
private Date fecIngreso;
private float comisionS;
private float pagoGanado;

public Vendedor(String nombre, String rfc, Date fecIngreso, float comisionS) {


this.nombre = nombre;
this.rfc = rfc;
this.fecIngreso = fecIngreso;
this.comisionS = comisionS; 15
}
//Métodos implementados
public void registroUsuario(){
System.out.println("RFC ingresandose a la lista de vendedores de la empresa");
}
public void registroVentasS(float venta){ comisionS+=venta*.15; }

public float calculaPago(){ return comisionS +3500.0f; }

//Setters y Getters
public String getNombre() { return nombre; }
public void setNombre(String nombre) { this.nombre = nombre; }
public String getRfc() { return rfc; }
public void setRfc(String rfc) { this.rfc = rfc; }
public Date getFecIngreso() { return fecIngreso; }
public void setFecIngreso(Date fecIngreso) { this.fecIngreso = fecIngreso; }
public float getComisionS() { return comisionS; }
public void setComisionS(float comisionS) { this.comisionS = comisionS; }
public float getPagoGanado() { return pagoGanado; }
public void setPagoGanado(float pagoGanado) { this.pagoGanado = pagoGanado; }

@Override
public String toString() {
return "Vendedor{" + "nombre=" + nombre + ", rfc=" + rfc + ", fecIngreso=" + fecIngreso + ",
comisionS=" + comisionS + ", pagoGanado=" + pagoGanado + '}';
}

Código reducido de la clase main Restaurante

import java.util.ArrayList;
import java.util.Date;
public class Restaurante {

public static void main(String[] args) {

ArrayList personalRest = new ArrayList();


Vendedor ven1= new Vendedor("Teresa Pérez ","TRPG127845RP0", new Date(), 0.12f);
Vendedor ven2 = new Vendedor ("Imelda García", "IGER234578GE2", new Date(), 0.15f);
Mesero mes1= new Mesero("Gustavo Díaz ", "GDRT237845HG6", new Date());
Mesero mes3= new Mesero("Ana López","FERD024578HY56", new Date());

// agregar personal al registro de empleados


personalRest.add(mes3);
mes3.registroUsuario();
personalRest.add(ven1);
ven1.registroUsuario();
personalRest.add(ven2);
ven2.registroUsuario();
mes1.registroUsuario(); 16
// asignar ventas a los vendedores
ven1.registroVentasS(7500);
ven2.registroVentasS(3600);
ven2.registroVentasS(6800);
ven1.registroVentasS(800);
// mostar pago de vendedores

for(Object elemento: personalRest){


if(elemento instanceof Vendedor){
System.out.println("pago al vendedor "
+((Vendedor) elemento).getNombre() + "\n "+((Vendedor) elemento).calculaPago());
} } } }

Ejecución de código:

Al utilizar implements para la Interface es como si se hiciese una acción de copiar-y-


pegar del código de la Interface, con lo cual no se hereda nada, solamente se pueden
usar los métodos.
La ventaja principal del uso de interfaces es que una clase Interface puede ser
implementada por cualquier número de clases, permitiendo a cada clase compartir la
Interface de programación sin tener que ser consciente de la implementación que hagan
las otras clases que implementen la interface.
Ejercicios 17
Con base en el ejercicio anterior codifica la siguiente jerarquía de clases:
Evidencia de trabajo: 18
Ejercicios resueltos con las clases codificadas
• Animal
• Mascota
• Mamífero
• Ave
• Perro
• Gato
• Perico
• Vacuna
• Clase main Veterinaria (incluye un menú para que el usuario decida las acciones que desea
registrar

Referencias:
Sznajdleder, Pablo Augusto, Java a fondo: estudio del lenguaje y desarrollo de aplicaciones. - 2a ed. Buenos
Aires: Alfaomega Grupo Editor Argentino, 2013, 456 p; ISBN 978-987-1609-36-9
Guardati Buemo Silvia, (2007). “Estructura De Datos Orientada A Objetos, Algoritmos Con C++]”, Pearson
Educación.
Guardati Buemo Silvia. (2016). Estructuras de datos básicas programación orientada a objetos con
Java. Alfaomega Grupo Editor
19
Práctica 3: Colecciones de Objetos e Iteradores
U. Competencia 1: Conceptos suplementarios de programación orientada a objetos

Duración Estimada: 2 sesión de 50 minutos


Objetivo: El alumno conocerá y usará las Colecciones de Objetos de uso más común
en java.

Introducción Teórica
En prácticamente todos los lenguajes de computación existen estructuras para
almacenar colecciones de datos. Esto es, una serie de datos agrupados a los que se
puede hacer referencia con un único nombre. Ejemplo de ello son los arreglos, el
problema de los arreglos es que son estructuras estáticas, esto significa que se debe
saber el número de elementos que formarán parte de esa colección a priori, es decir,
en tiempo de compilación hay que decidir el tamaño del arreglo.
Las estructuras dinámicas tienen la ventaja de que sus integrantes se deciden en
tiempo de ejecución y que el número de elementos es ilimitado. Estas estructuras
dinámicas son clásicas en la programación y son las colas, pilas, listas enlazadas,
árboles, grafos, etc. En muchos lenguajes se implementan mediante punteros; como
Java no posee punteros explícitos que controlen los programadores se crearon clases
especiales para implementar estas funciones.
En Java desde la primera versión se incluyeron las clases: Vector, Stack, Hashtable,
BitSet y la interfaz Enumeration. En Java 2 se modificó este funcionamiento y se
potenció la creación de estas clases.
Interface Collection
La interfaz fundamental de trabajo con estructuras dinámicas es java.util.Collection.
Esta interfaz define métodos muy interesantes para trabajar con listas y conjuntos.
Todas las clases que implementan la Interface Collection se usan de forma similar. Lo
que cambia es la forma en que se almacenan los elementos: ordenados, con duplicidad,
con acceso basado en una clave.
Algunas características comunes de las clases heredadas de Collection:
• Los elementos de una Collection se pueden recorrer secuencialmente y son
accesibles mediante un índice.
• Map contiene pares clave-objeto, de forma que los elementos son ordenados y
son accesibles a través de sus claves.
• Para recorrer un Map debe antes extraerse de él una Collection.
• ArrayList y LinkedList pueden usarse a modo de pila, añadiendo y eliminando
elementos.
• TreeMap y TreeSet están ordenados.
20
• Set y Map no pueden tener duplicados.

Respecto al almacenamiento de objetos


• HashSet, TreeSet set.add(object) - Añade en algún sitio, en el orden que tengan
los elementos
• LinkedList list.add(object) - Añade al final list.add(index, object) - Añade en la
posición dada por el índice, desplazando previamente los elementos necesarios.

En la imagen siguiente se observa la jerarquía completa de la Interface Collection.

Como se observa en la imagen las clases que implementan las Interfaces:


• HashSet: implementa Set
• HashMap: implementa Map
• ArrayList: implementa List
• TreeSet: implementa SortedSet
• TreeMap: implementa SortedMap
• LinkedList: implementa List

Principales características de las colecciones.


• ArrayList list.add(object) - Añade al final el objeto
o list.add(index, object) - Añade en la posición dada por el índice,
desplazando previamente los elementos necesarios
o list.set(index,object) - Sobreescribe el elemento con dicho índice
21
• HashMap, TreeMap
o map.put(key,value) - El objeto con su clave se sitúan en el lugar que le
corresponda según el orden de las claves.
Manejo de objetos
• clear( ): elimina todos los objetos de la colección.
• size( ): devuelve el tamaño de la colección.
• remove(object): elimina de la colección al objeto indicado

Para HashMap y TreeMap:


• obj = m.get(key); // entrega el objeto de la clave indicada
• obj = m.remove(key); // elimina el objeto referenciado por la clave recibida
• bool = m.containsKey(key); // informa mediante un boleano si la colección
contiene la clave consultada
• bool = m.containsValue(key); // informa mediante un loleano si la colección
contiene el valor consultado
• collection = m.values( ); // devuelve los valores de la colección para ser
almacenados en otra colección
• set = m.keySet( ); // entrega un conjunto de claves de la colección

Transformaciones
Se puede pasar de un tipo de estructura a otra, de forma que así se eliminen los
duplicados, se ordenen los elementos, se cree un array, etc., según sea el caso.
Cualquier tipo de Collection puede transformarse a otra Collection, simplemente al crear
una nueva instancia:
• Set set = new HashSet();
• SortedSet ss = new TreeSet(set);
• Los Map se transforman en Collection eliminando las claves:
• Collection col = tm.values();
• Cualquier Collection puede transformarse en un Array:
o Object [] obj = collection.toArray();

Recorrer una Collection


La forma de recorrer una Collection es mediante un Iterator:

for (Iterator it=coll.iterator(); it.hasNext( ); ) {


Object anObject = it.next( );
System.out.println( anObject );
}
Iteradores
22
La interfaz Iterator (también en java.util) define objetos que permiten recorrer los
elementos de una colección. Los métodos definidos por esta interfaz son:
Iterator it=colecciónString.iterator();

while(it.hasNext()){
String s=(String)it.next(); System.out.println(s);
}

Clase Stack
Es una clase derivada de la anterior usada para crear estructuras de pilas. Las pilas
son estructuras dinámicas en las que los elementos se añaden por arriba y se obtienen
primero los últimos elementos añadidos.
Clase abstracta Dictionary
La desventaja de las estructuras anteriores reside en que su manipulación es larga
debido a que el orden de la lista permanece en todo momento, lo que obliga a recorrer
la lista elemento a elemento.
La clase abstracta Dictionary proporciona la interfaz para trabajar con mapas de valores
clave. Actualmente está absolutamente reemplazado con la interfaz Map. La idea es
proporcionar estructuras con un par de valores, código - contenido. En estas estructuras
se busca el código para obtener el contenido.
Mapas
Permiten definir colecciones de elementos que poseen pares de datos clave-valor. Esto
se utiliza para localizar valores en función de la clave que poseen. Son muy interesantes
y rápidos. Es la nueva implementación de tablas hash. El objeto Map es interno a los
objetos Map y representa un objeto de par clave/valor. Esta interfaz está implementada
en la clase HashMap. Además, existe la interfaz SortedMap implementada en TreeMap.
La diferencia es que TreeMap crea un árbol ordenado con las claves (el manejo es el
mismo).

Ejemplo

Para ejemplificar el uso de la clase ArrayList se codificará el siguiente diagrama de


clases; se forma de tres clases Producto que representa las características de los
elementos vendibles en el mercado, estos productos tienen nombre, cantidad vendida
y costo unitario, la clase CControl contiene un objeto llamado “bolsa” de tipo ArrayList
que será la colección de objetos a comprar por un usuario.
23

El código de las clases será el siguiente (la explicación se encuentra en los


comentarios):
Clase producto
package mercado;
public class Producto {
//atributos
private String nombre;
private int cantidad;
private float costoUnitario;
//constructor
public Producto(String nombre, int cantidad, float costoUnitario) {
this.nombre = nombre;
this.cantidad = cantidad;
this.costoUnitario = costoUnitario;
}
//Setters y getters
public String getNombre() { return nombre; }
public void setNombre(String nombre) { this.nombre = nombre; }
public int getCantidad() { return cantidad; }
public void setCantidad(int cantidad) { this.cantidad = cantidad; }
public float getCostoUnitario() { return costoUnitario; }
public void setCostoUnitario(float costoUnitario) { this.costoUnitario = costoUnitario; }
public float calculaMonto(){ return cantidad*costoUnitario;}
@Override
public String toString() {
return "Producto{" + "nombre=" + nombre + ", cantidad=" + cantidad + ", costoUnitario=" + costoUnitario + '}'; } }

package mercado;
//importer las clases necesarias para usar colecciones
import java.util.ArrayList;
import java.util.Iterator;
24
public class CControl {
//atributos
ArrayList <Producto> bolsa;
//Constructor
public CControl (ArrayList mbolsa){ this.bolsa=mbolsa; }

public int buscarProducto(String p){ //busca al objeto p y devuelve la posición en la bolsa


Iterator rec=bolsa.iterator();
while (rec.hasNext()){ //mientras haya objetos en la colección hacer…
Producto tem= (Producto)rec.next();// se obtiene el objeto siguiente
int resultadoC=tem.getNombre().compareTo(p); //se compara el nombre del objeto obtenido con el objeto a buscar
if(resultadoC==0){ //si el resultado es cero significa que si existe
return bolsa.indexOf(tem); // se devuelve la posición del objeto encontrado
}
}
return -1; // si no existe el objeto buscado se devuelve -1
}

//Busca el elemento p y lo elimina


public void eliminarP (String p){ // se recibe un nombre a buscar
// busco a p, si esta lo elimino
int posbuscado=0;
posbuscado=buscarProducto(p); //invoco a buscarProducto para saber si existe el objeto en la colección
if (posbuscado !=-1){ //si el resultado es diferente a -1 (si existe)
bolsa.remove(posbuscado); //entonces se puede eliminar
}
else //si no esta el objeto a buscar entonces informamos al usuario
System.out.println("El producto "
+ "no está en la bolsa");

public String modificaCosto(float nc, String p){


int posbuscado=0;
posbuscado=buscarProducto(p);
if (posbuscado!= -1){
Producto tem=(Producto)bolsa.get(posbuscado);
tem.setCostoUnitario(nc);
return "Costo Modificado";
}
return "No existe el producto; no se pudo modificar el costo";
}

public float calculaMontoTotal(){


float sumatoria=0; //inicializa la variable en cero
for(Producto prod : bolsa){ //otra forma de recorrer la colección con el ciclo for each
sumatoria+=prod.calculaMonto(); // se invoca al método calculaMonto para cada producto y se acumula en sumatoria
}
return sumatoria; // se retorna la sumatoria obtenida
}
public void mostrarContBolsa(){ //Recorre la colección y muestra su contenido
int i=1; //variable para contar los productos 25
for(Producto prod : bolsa){ // for each para recorrer la colección llamada bolsa
//Se muestra en consola el nombre del producto y el monto parcial por ese producto
System.out.println("Pago por producto "+i+ "\n "+ prod.getNombre() + " : "+prod.calculaMonto());
i++; //se incrementa el contador
}
}}

package mercado;
//importar las clases necesarias para usar las colecciones
import java.util.ArrayList;
import java.util.Scanner;

public class Mercado {

public static void main(String[] args) {//método principal


CControl contr= new CControl(new ArrayList()); //instanciamos a un objeto que tendrá el control de la colección
//generar productos para comprar
Producto m= new Producto("Pan",5,1.5f); //representa 5 piezas de pan a 1.5 cada pieza
Producto n= new Producto("Leche",2,21.00f); // representa 2 piezas de leche a 21.00 cada pieza
Producto p= new Producto("Manzana", 1, 40.0f); representa 1 kilo de manzana a 40.0 cada kilo
Producto l= new Producto ("jitomate",2,50.0f); representa 2 kilos de jitomate a 50.00 cada kilo
Producto g= new Producto("Salmón",1,350.f); representa 1 pieza de salmón a 350.00 cada pieza

//Informa que la bolsa esta sin elementos


System.out.println("Productos " + "en la bolsa: "+contr.bolsa.size());
//almacenar los productos en la bolsa
contr.bolsa.add(g); contr.bolsa.add(m);
contr.bolsa.add(n); contr.bolsa.add(p); contr.bolsa.add(l);

//muestra que la bolsa ya tiene elementos


System.out.println("Productos "+ "en la bolsa: "+contr.bolsa.size());
//Calcular el monto total a pagar por los productos en la bolsa
System.out.println("Monto total por los productos en la bolsa "+contr.calculaMontoTotal());

//modificar datos de los productos de la bolsa (en este caso el costo unitario)
Scanner leer = new Scanner(System.in);
System.out.println("Inserte el producto a modificar");
String prdBuscado=leer.nextLine();
System.out.println("Inserte el nuevo costo unitario");
float ncosto=Float.parseFloat(leer.next());
String reslMod=contr.modificaCosto(ncosto, prdBuscado);
System.out.println(reslMod);

//Mostrar el contenido de la bolsa y el costo parcial por cada producto


contr.mostrarContBolsa(); } }
Procedimiento 26
Con base en el ejemplo anterior generar un programa que permita a llevar el control de
inscripciones de personas a varios cursos. El programa permitirá al usuario mediante
un menú
1. agregar cursos
2. modificar datos del curso
3. eliminar cursos
4. mostrar al usuario los cursos registrados
5. mostrar el total de créditos (la sumatoria de los créditos de cada curso inscrito)
6. buscar cursos
7. eliminar todos los registros de cursos para iniciar una nueva inscripción

Se sugiere usar el diagrama siguiente (puede modificarlo si lo considera necesario):

Recuerda que puedes consultar el Anexo de información para tener más datos sobre
las colecciones

Evaluación y evidencia:
Clases codificadas y ejecución del programa calificado por el profesor

Referencias
Sznajdleder, Pablo Augusto, Java a fondo: estudio del lenguaje y desarrollo de aplicaciones. - 2a ed. Buenos
Aires: Alfaomega Grupo Editor Argentino, 2013, 456 p; ISBN 978-987-1609-36-9
Guardati Buemo Silvia, (2007). “Estructura De Datos Orientada A Objetos, Algoritmos Con C++]”, Pearson
Educación.
Guardati Buemo Silvia. (2016). Estructuras de datos básicas programación orientada a objetos con
Java. Alfaomega Grupo Editor
27
Práctica 4: Tiempos de ejecución de algoritmos de
ordenamiento y búsqueda.
U. Competencia 2: Ordenamiento y búsqueda.
Duración Estimada: 3 sesiones de 50 minutos

Objetivo: Implementar programas por computadora para la solución de problemas


que involucren el procesamiento de datos mediante recursividad, búsqueda y
ordenamiento de datos.

Introducción Teórica:
La ordenación de datos consiste en disponer o clasificar un conjunto de datos en algún
determinado orden con respecto a alguno de sus campos. Para esto existen diferentes
algoritmos que permiten el ordenamiento y estos se pueden clasificar en dos tipos:
• Ordenamiento interno.
Se lleva a cabo completamente en memoria principal. Todos los objetos que se ordenan
caben en la memoria principal de la computadora.
• Ordenamiento externo.
No cabe toda la información en memoria principal y es necesario ocupar memoria
secundaria. El ordenamiento ocurre transfiriendo bloques de información a memoria
principal en donde se ordena el bloque y este es regresado, ya ordenado, a memoria
secundaria.
Existen diferentes criterios de eficiencia para los distintos tipos de algoritmos, los cuales
son:
• Por el número de pasos
• Por el número de comparaciones entre llaves para ordenar n registros.
• De utilidad cuando la comparación entre llaves es costosa.
• Por el número de movimientos de registros que se requieren para ordenar n registros.
De utilidad cuando el movimiento de registros es costoso
Tres de los algoritmos clásicos que se pueden encontrar y desarrollar con facilidad son
28
los siguientes:
Método de la burbuja: Este método de ordenación consiste en recorrer los elementos
siempre en la misma dirección, intercambiando elementos adyacentes si fuera
necesario.

método por inserción: El método de Inserción realiza n–1 iteraciones sobre el arreglo,
dejando en la i- ésima etapa (2 ≤ i ≤ n) ordenado el subarreglo a[1..i]. La manera de
hacerlo es colocando en cada iteración el elemento a[i] en su sitio correcto,
aprovechando el hecho de que el subarreglo a[1..i–1] ya ha sido previamente ordenado.

Método quicksort: Este método es probablemente el algoritmo de ordenación más


utilizado, pues es muy fácil de implementar, trabaja bien en casi todas las situaciones
y consume en general menos recursos (memoria y tiempo) que otros métodos. Su
diseño está basado en la técnica de Divide y Vencerás, que básicamente consiste en
subdividir un arreglo en otros, de tal manera que cada subarreglo se pueda ordenar de
manera más fácil.
29

Por otro lado se encuentran los procesos o algoritmos de búsqueda que involucran
recorrer un arreglo completo con el fin de encontrar algo. Lo más común es buscar el
menor o mayor elemento (cuando es puede establecer un orden), o buscar el índice de
un elemento determinado.

Para ello existen diversos algoritmos que varían en complejidad, eficiencia, tamaño del
dominio de búsqueda.
Los mas comunes se pueden observar a continuación.

Búsqueda secuencial: Consiste en ir comparando el elemento que se busca con cada


elemento del arreglo hasta cuándo se encuentra. El algoritmo se puede aplicar tanto de
derecha a izquierda como a la inversa, es decir, de izquierda a derecha. La eficiencia
del algoritmo se describe a continuación:
• Mejor Caso: El elemento buscado está en la primera posición. Es decir, se hace una
sola comparación.

• Peor Caso: El elemento buscado está en la última posición. Necesitando igual cantidad
de comparaciones que de elementos el arreglo.

• En Promedio: El elemento buscado estará cerca de la mitad. Necesitando en promedio,


la mitad de las comparaciones que de elementos
Básicamente la velocidad de ejecución depende linealmente del tamaño del arreglo.
30

Búsqueda binaria: Una búsqueda más eficiente puede hacerse sobre un arreglo ya
ordenado, precisamente así lo hace “Búsqueda Binaria”. La Búsqueda Binaria, compara
si el valor buscado está en la mitad superior o inferior, lo hace subdividiendo el arreglo
(divide y vencerás) y así sucesivamente hasta encontrar el valor. La eficiencia se
describe a continuación:
• Mejor Caso: El elemento buscado está en el centro. Por lo tanto, se hace una sola
comparación.

• Peor Caso: El elemento buscado está en una esquina. Necesitando log2(n) cantidad de
comparaciones.

Por lo tanto, la velocidad de ejecución depende logarítmicamente del tamaño del


arreglo.
31

Procedimiento

La práctica para elaborar consistirá en lograr unificar todos los métodos anteriormente
mencionados en un solo código, midiendo y comparando los tiempos de ejecución entre
estos, con la finalidad de detectar la eficiencia de uno en contra de otros, todo esto en
iguales circunstancias. El programa deberá funcionar de la siguiente manera:

1. Solicitar al usuario un numero entero n para construir un arreglo A de tal


dimencion.

0 . . . n-1
A

2. Crear un metodo para llenar de numeros aleatorios al arreglo A sin que


contenga numeros repetidos. Mostrar los datos desordenados.

3. Crear dos arreglos mas, B y C. El contenido de estos debera ser exactamente


el mismo que contiene A.

4. Posteriormente ordenar A por Burbuja, B por Inserccion y C por Quicksort.


5. Realizar la búsqueda de un elemento X en el arreglo A que anteriormente fue
32
ordenado por el método Burbuja. La búsqueda se realizará por los métodos
secuencial y posteriormente binaria.

6. Finalmente se mostrará en pantalla la siguiente información: Datos del arreglo


A ordenados, posición donde se encontró el elemento X y tiempos de
ejecución de cada uno de los algoritmos implementados.

Ejecutar el código tantas veces sea necesario para evidenciar las diferencias de tiempo
entre cada uno de ellos en diferentes circunstancias. Es decir, probar el mejor de los
casos, el peor de los casos y el caso promedio.

Las siguientes líneas de código funcionan como guía para medir relativamente el tiempo
de ejecución que tarda un código en java en ejecutar alguna sentencia.

long inicio = System.currentTimeMillis(); //Obtiene el tiempo en milisegundos antes de iniciar la siguiente línea de código

ordenarPorBurbuja(A); //Se invoca en este caso el método burbuja para medir su tiempo de ejecución

long fin = System.currentTimeMillis();(); //Obtiene el tiempo en milisegundos después de terminar la anterior línea de código

double tiempo = (double) ((fin - inicio) / 1000); // Al dividir entre 1000 se calcula los segundos que tardo la ejecución

System.out.print("Tiempo de ejecución: " + tiempo); //Muestra los segundos que tardo en ejecutar la sentencia

Evaluación:
Aciertos: 20 puntos por algoritmo codificado y demostración de tiempo de ejecución.

Evidencia para obtener:


Ejecución del proyecto evaluado por el profesor, mostrando principalmente las
diferencias en tiempo de ejecución de cada algoritmo de búsqueda y ordenamiento.

Referencias
Torres, A. C. (2017). Aprenda a Diseñar Algoritmos. Universidad Nacional Abierta y a Distancia.
33
Práctica 5: Uso de Pilas 34
U. Competencia 3: Estructuras de datos lineales y no lineales

Duración Estimada: 2 sesión de 50 minutos

Objetivo:
El alumno aplicará el principio de almacenamiento LIFO (Last In, First out) para el uso
de pilas.

Introducción Teórica:

Las estructuras dinámicas son muy útiles en la computación ya que permiten almacenar
información de tamaño variable, recordemos que los arreglos también sirven para
gestionar información, pero tienen la desventaja de ser estáticos, es decir, no crecen
en tiempo de ejecución.
Una pila es una lista de elementos a la cual se puede insertar o eliminar elementos solo
por uno de los extremos. En consecuencia, los elementos de una pila serán eliminados
en orden inverso al que se insertaron; es decir, el último elemento que se mete en la
pila es el primer elemento en salir; a esta estrategia se le denomina LIFO (Last in, First
out).
En la pila se identifican los siguientes elementos:
• la unidad de información recibe el nombre de nodo que consiste en una estructura con
la información de interés y un apuntador que permite acceder al siguiente elemento
• la base de la pila que es el primer nodo y es el que permite el acceso a la estructura
completa
• el tope de la pila que es el último nodo insertado y que será el nodo para eliminar
Las operaciones que se pueden realizar en las pilas son:
35
• Crear la pila
• Insertar la pila también referida como Push
• Eliminar un elemento de la pila también llamada Pop
• Mostrar la información de la pila
• Verificar si la pila está vacía (isEmpty)

Aplicaciones de las Pilas


En lenguajes de programación procedurales como Pascal o C, la pila es una estructura
indispensable, debido a las llamadas a función. Ya que cuando ocurre una llamada a
alguna función, el estado global del sistema se almacena en un registro y éste en una
pila. Cuando se termina de ejecutar algún procedimiento, se recupera el registro que
está en la cima de la pila para continuar con el trabajo que se estaba realizando.
Otra aplicación muy evidente del uso de las pilas sucede en el funcionamiento de
programas como los navegadores web. En ellos se almacenan los sitios previamente
visitados en una pila y cuando el usuario quiere regresar (presiona el botón de
retroceso), simplemente se extrae la última dirección (pop) de la pila de sitios visitados,
así sucesivamente hasta que se llega a la primera dirección visitada.
En los editores de texto y en otros programas también se usan las pilas en el control de
instrucciones ya que los cambios efectuados se almacenan en una pila, que usualmente
se implementan como un arreglo. De esta forma el usuario puede deshacer los cambios
mediante la operación “deshacer”, la cual extraer el estado del texto antes del último
cambio realizado.
Las pilas pueden implementarse en varias estructuras, pueden ser administradas
mediante arreglos, aunque esto tiene la desventaja de que el número de elementos
queda limitada al tamaño de dicho arreglo y puede volverse ineficiente con grandes
cantidades de información
36

public class Nodo {

//Atributos
private int elemento;
private Nodo siguiente; //Apunta al siguiente nodo

//Constructor
public Nodo(int elemento, Nodo siguiente) {
this.elemento = elemento;
this.siguiente = siguiente;
}
//Métodos
public int getElemento() { return elemento; }
public void setElemento(int elemento) { this.elemento = elemento; }
public Nodo getSiguiente() { return siguiente; }
public void setSiguiente(Nodo siguiente) { this.siguiente = siguiente; }

@Override
public String toString() { return elemento + "\n"; }
}

package ejemplopila;

public class Pila {


private Nodo top; //último nodo que se ha incluido
private int tamanio; //el número de elementos en la pila

public Pila() { //Constructor


top = null; //No hay elementos
this.tamanio = 0;// el tamaño es cero
}
37
public boolean isEmpty() {//informa si la pila esta vacía
return top == null; }

//Informa el número de elementos en la pila


public int size() { return this.tamanio; }

public Nodo top() { //entrega el Nodo en el tope de pila


if (isEmpty()) {
return null;
} else { return top; }
}

public Nodo pop(Nodo i) { //entrega el último nodo de la pila


System.out.println("Inicia método POP ");
System.out.println("Valor de i "+ i.getElemento());
Nodo s= new Nodo(0,null);
//recorre la pila hasta el tope de pila
while(i.getSiguiente()!=null){
s=i.getSiguiente();
if(s.getSiguiente()==null){
Nodo aux=s.getSiguiente();
System.out.println("Valor sacado"+ s.getElemento());
i.setSiguiente(null);
top=i;
return top; }
else{ i=s; }
}
this.tamanio--; //disminuye el tamaño de la pila
top=i; //Actualiza el tope de pila
return top;
}

public Nodo push(Nodo i,Nodo nv) { //Inserta nodos en la pila


if (i.getSiguiente()==null){
i.setSiguiente(nv);
System.out.println("Valor insertado "+nv.getElemento());
top=i;
return top;
}
else{
Nodo s=visitarPila(i);
if (s.getSiguiente()==null){
System.out.println("Valor insertado "+ nv.getElemento());
s.setSiguiente(nv);
top=s.getSiguiente();
this.tamanio++;
return top;
}
}
return top; }
38
public Nodo visitarPila(Nodo i){ //recorre la pila y muestra el contenido
System.out.println("Inicia metodo recorrer Pila ");
System.out.println("Valor de i "+ i.getElemento());
Nodo s= new Nodo(0,null);
while(i.getSiguiente()!=null){
s=i.getSiguiente();
System.out.println("Valor visitado "+ s.getElemento());
i=s;
}
return i;
}

public String toString() { //muestra los valores de la pila


if (isEmpty()) { return "La pila esta vacía"; }
else
{ String resultado = "";
Nodo aux = top;
//Recorro la pila
while (aux != null) {
resultado += aux.toString();
aux = aux.getSiguiente();
}
return resultado;
} } }

package ejemplopila;

public class EjemploPila {


public static void main(String[] args) { // construcción del nodo inicial

Nodo inicial= new Nodo(1,null); //se construye el nodo base de la pila, tiene valor 1 y no apunta a otro nodo

System.out.println("inicial: "+inicial.getElemento()); // se muestra la base de la pila

Pila mipila= new Pila(); // Iniciamos la construcción de pila


System.out.println(mipila.toString()); // Se muestra el contenido de la pila

Nodo pvalor= new Nodo(3,null); // construcción de nodo nuevo

Nodo top= mipila.push(inicial,pvalor); // se inserta el nodo en la pila


System.out.println("valor Top "+top.getElemento());
top= mipila.push(inicial,new Nodo(78,null));
System.out.println(" Valor Top "+top.getElemento());

//Se insertan varios nodos


top= mipila.push(inicial, new Nodo(23,null));
System.out.println("******");

//Se elimina en la pila


top= mipila.pop(inicial);
System.out.println("***Después de borrado***");
top=mipila.push(inicial,new Nodo(45,null)); 39
top=mipila.push(inicial,new Nodo(89,null));
top=mipila.push(inicial,new Nodo(41,null));
System.out.println(top.toString());

//Se muestran los nodos incluidos en la pila


System.out.println(" Valor Top "+mipila.top().toString());

Ejecución del programa

Ejercicio
Con base en el código anterior modifica el método main de la clase ejemplo pila para
que sea el usuario el que pueda insertar, visitar los valores de la pila o sacar elementos
de la pila cuando lo decida. Apóyate en la realización de un menú que controle la
interacción del usuario

Evaluación
10 puntos por el proyecto completo

Evidencia
Programa que interactúe con el usuario y sea validado por el profesor

Referencias
Sznajdleder, Pablo Augusto, Java a fondo: estudio del lenguaje y desarrollo de aplicaciones. - 2a ed. Buenos
Aires: Alfaomega Grupo Editor Argentino, 2013, 456 p; ISBN 978-987-1609-36-9
Guardati Buemo Silvia, (2007). “Estructura De Datos Orientada A Objetos, Algoritmos Con C++]”, Pearson
Educación.
Guardati Buemo Silvia. (2016). Estructuras de datos básicas programación orientada a objetos con Java.
Alfaomega Grupo Editor
40
Practica 6: Uso de Colas
U. Competencia 3 Estructuras de datos lineales y no lineales

Duración Estimada: 1 sesión de 50 minutos

Objetivo:
El alumno aplicará el principio de almacenamiento FIFO (First In, First out) para el uso
de colas.

Introducción Teórica:
Una cola es una estructura de datos lineal y dinámica que permite gestionar la
información con base en la estrategia FIFO (First In, First out); es decir primer elemento
en entrar será el primer elemento en salir. En la vida cotidiana es fácil identificar las
colas, pues los humanos usamos esta estrategia para considerar a la primera persona
en llegar. Es común ver esta estrategia en los bancos, autobuses y otras oficinas de
atención a clientes.

En la imagen siguiente se pueden observar los componentes involucrados en el manejo


de las colas:
• La unidad de información, nombrada nodo, que consiste en el dato y un apuntador al
siguiente elemento.
• El frente de la cola, es el primer elemento en haberse registrado en la cola
• El final de la cola, representa el último elemento agregado, su apuntador no tiene
asignación de nodo siguiente, es decir, apunta a null.
Las operaciones que se pueden realizar en la cola son:
41
• Crear la cola
• Insertar elementos a la cola
• Verificar si la cola está vacía (isEmpty)
• Encolar (insertar elementos en la cola)
• Desencolar (eliminar o sacar un elemento de la cola
• Visualizar los elementos de la cola

Las estructuras tienen variantes en la computación. Una de esas variantes es la cola


doblemente ligada; estas colas tienen nodos con dos apuntadores, uno que apunta al
nodo precedente y otro que apunta hacia el nodo antecesor. De esta forma la cola
puede ser recorrida en dos direcciones en caso necesario, las operaciones de encolar
y desencolar se mantienen con la misma regla.

Cola doblemente ligada

La cola circular se caracteriza por que el apuntador del final en lugar de apuntar a
null, apunta al frente de la cola, las operaciones encolar y desencolar funcionan de
igual forma que en las demás colas.

También se usa en algunos problemas la bicola o doble cola; esta estructura


consiste en usar los dos extremos tanto para encolar como para desencolar, de esta
forma la lista puede crecer por ambos extremos y si es necesario también se puede
42
usar con nodos doblemente ligados.

Ejemplo
Con base en el paradigma orientado a objetos para implementar una cola se identifican
las siguientes clases:
• Nodo: describe la unidad mínima de información, permite crear nuevos elementos
• Cola: es la clase en la que se definen las operaciones para gestionar la cola
• EjemploCola: es una clase con un método main mediante la cual el usuario podrá
interactuar con el programa

El diagrama a codificar será el siguiente:


La codificación queda de la siguiente forma, la explicación se hace en los comentarios
43
public class Nodo {
//Atributos
private int elemento;
private Nodo siguiente; //Apunta al siguiente nodo

//Contructor
public Nodo(int elemento, Nodo siguiente) {
this.elemento = elemento;
this.siguiente = siguiente;
}
//Métodos
public int getElemento() { return elemento; }
public void setElemento(int elemento) { this.elemento = elemento; }
public Nodo getSiguiente() { return siguiente; }
public void setSiguiente(Nodo siguiente) { this.siguiente = siguiente; }

@Override
public String toString() { return elemento + "\n"; }
}

package ejemplopila;

public class Cola {


private Nodo frente; //primer en entrar
private int tamanio; // tamaño de la cola

public Cola() { //Constructor


frente = null; //No hay elementos
this.tamanio = 0; // tamaño cero
}

public boolean isEmpty() { return frente == null; }

public int size() { return this.tamanio; }

public Nodo raiz() {


if (isEmpty()) {
return null;
} else {
return frente;
} }

public void sacar() { // método desencolar


System.out.println("Inicia método sacar ");
if(frente!=null){
System.out.println("Valor sacado "+ frente.getElemento());
Nodo s= frente.getSiguiente();
frente=s;
}
this.tamanio--; }
public void encolar(Nodo nv) { 44
if (frente==null){
frente=nv;
System.out.println("Valor insertado "+nv.getElemento()); }
else{
Nodo s=recorreCola();
if (s.getSiguiente()==null){
System.out.println("Valor insertado "+ nv.getElemento());
s.setSiguiente(nv);
this.tamanio++;
} }
}

public Nodo recorreCola(){


System.out.println("Inicia método recorrer cola");
System.out.println("Valor visitado "+frente.getElemento());
Nodo i= frente;
Nodo s=new Nodo(0,null);
while(i.getSiguiente()!=null){
s=i.getSiguiente();
System.out.println("Valor visitado "+ s.getElemento());
i=s;
}
return i;
}

public String toString() {


if (isEmpty()) { return "La cola esta vacía"; }
else
{ String resultado = "";
Nodo aux = frente;
//Recorro la pila
while (aux != null) {
resultado += aux.toString();
aux = aux.getSiguiente();
}
return resultado;
} } }
Ejercicio a realizar 45
Con base al siguiente diagrama de clases, codificar el programa que mediante un menú
el usuario pueda encolar, desencolar, saber si la cola está vacía y recorrer la cola hacía
adelante y hacia atrás. Si observa la clase NodoD representa un nodo doblemente
ligado.

Evaluación
10 puntos por el programa ejecutado.

Evidencia:
Código de cada clase y la ejecución validada por el profesor

Referencias

Sznajdleder, Pablo Augusto, Java a fondo: estudio del lenguaje y desarrollo de aplicaciones. - 2a ed. Buenos
Aires: Alfaomega Grupo Editor Argentino, 2013, 456 p; ISBN 978-987-1609-36-9
Guardati Buemo Silvia, (2007). “Estructura De Datos Orientada A Objetos, Algoritmos Con C++]”, Pearson
Educación.
Guardati Buemo Silvia. (2016). Estructuras de datos básicas programación orientada a objetos con Java.
Alfaomega Grupo Editor.
Práctica 7: Árboles 46
U. Competencia 1

Duración Estimada: 1 sesión de 50 minutos

Objetivo:
El alumno aplicará la metodología para resolver problemas.

Introducción Teórica:
Los árboles representan las estructuras no lineales y dinámicas más importantes en
cómputo.
Un árbol es una estructura jerárquica que se define por:
• Un conjunto de nodos (uno de los cuales se distingue por ser la raíz del árbol)
• Un conjunto de aristas de manera que:
o Cualquier nodo H, a excepción de la raíz, está conectado por medio de
una arista a un único nodo P.
o Un nodo puede tener múltiples hijos.
• Si un nodo tiene algún hijo es un nodo interno, sino es una hoja.

• Los nodos con el mismo padre son hermanos.


Ejemplo: Los nodos M y N son hermanos (el padre es K)
• Si hay un camino desde un nodo u hasta un nodo v, se dice:
o u es un ascendiente de v
o v es un descendiente de u
o Todo nodo es ascendiente de sí mismo.
o Si u≠v entonces se denomina ascendiente/descendiente propio
• El tamaño de un nodo es el número de descendientes
• Desde la raíz a cada nodo hay un camino de longitud igual a su número de
aristas.
• El tamaño de un árbol es el tamaño de su nodo raíz.
Ejemplo: El tamaño del árbol es 14.
Ejemplo. El camino desde la raíz al nodo etiquetado como E es A-B-E (Longitud
2)
• La profundidad de un nodo es la longitud del camino que va desde la raíz a él.
47
Ejemplo. La profundidad del nodo raíz es cero. La profundidad del nodo
etiquetado como L es 4.
• La altura de un nodo es la longitud del camino que va desde dicho nodo hasta
la hoja más profunda bajo él.
Ejemplo. La altura del árbol es 4.
• Un árbol es:
o Un árbol vacío o
o Un nodo raíz y cero o más subárboles no vacíos donde cada una de sus
raíces está conectada por medio de una arista con la raíz del árbol.
• Cada nodo de un árbol defina un subárbol que es aquel que tiene por raíz.

Árbol binario

Un árbol binario tiene las siguientes propiedades:


• Un árbol binario es un árbol en el cual ninguno de sus nodos tiene más de dos
hijos.
• Sea T un árbol binario y sean Ti y Td sus subárboles, su altura H(T), es:
o 0 si el árbol T tiene solo la raíz.
o 1 + max(H(Ti), H(Td)) si contiene más nodos
• En un árbol binario de altura H:
o El número máximo de nodos en el nivel i es 2i (0≤i≤H)
o El máximo número de nodos es:
∑𝐻𝑖=0 2 = 2
𝑖 H+1-1

o El máximo número de hojas es:


(2H+1-1)- ∑𝑖=0
𝐻−1 2𝑖 =2H

o El máximo número de nodos internos es:


2H+1-1-2H=2H-1
• Un árbol binario de altura H es lleno si tiene todos sus niveles completos.
• Para un árbol binario lleno de tamaño N y altura H se cumplen las siguientes
propiedades:
H=log2N
N=2H+1-1
• Un árbol binario es completo si tiene todos sus niveles completos a excepción,
48
quizás del último que, entonces, debe tener situados todos sus nodos, las
hojas del árbol, tan a la izquierda como sea posible.

• Todo árbol binario lleno es completo, aunque no es cierta la afirmación inversa.


• Por lo que se cumplen las siguientes propiedades.
o Altura de un árbol binario completo
H≤Log2N
o Número de nodos de un árbol binario completo de altura H.
2H≤N≤2H+1-1
o La relación entre altura (H) y número de nodos (N) de un árbol binario
completo (o Lleno) determina si está equilibrado:
▪ Sus N datos se distribuyen en el árbol tal que la longitud de su
camino más largo (esto es, la atura) está acotada por Log2N.
• Un árbol binario es equilibrado o perfectamente balanceado si la diferencia
de la altura de los hijos derecho e izquierdo es, como máximo de uno.

• Un árbol binario es:


o Un árbol binario vacío o
o Un nodo raíz y dos subárboles binarios, uno izquierdo y otro derecho,
que pueden ser vacíos.
o
▪ Un árbol binario degenerado es aquel que todos los nodos tienen sólo un
subárbol excepto el último. Un árbol degenerado puede ser degenerado por la 49
derecha o por la izquierda.

▪ Dado que un nodo se identifica con el árbol del que es raíz, el recorrido en
profundidad puede seguir el siguiente orden de visita:

o Recorrido en preorden: Nodo→Sub árbol izquierdo→subárbol derecho


6-3-1-5-8-7-9

o Recorrido en postorden: Sub árbol izquierdo → subárbol derecho


→Nodo
1-5-3-7-9-8-6

o Recorrido en inorden: Sub árbol izquierdo→Nodo→ subárbol derecho


1-3-5-6-7-8-9

▪ El recorrido en anchura (por niveles) desde la raíz se realiza de la siguiente


manera:
6-3-8-1-5-7-9

Un árbol binario tiene múltiples aplicaciones. Se los puede utilizar para representar una
estructura en la cual es posible tomar decisiones con dos opciones en distintos puntos
de un proceso, para representar la historia de un campeonato de tenis, para representar
un árbol genealógico y para representar expresiones algebraicas construidas con
operadores binarios. Esto sólo para citar algunos de sus múltiples usos.
Ejemplo 50
Para implementar un árbol binario de búsqueda serán necesario al menos tres clases
• El nodo; representa la unidad básica de información; incluye un apuntador para la rama
izquierda y otro apuntador para la rama derecha
• La clase ArbolB, en la que se definen los métodos para recorrer el árbol, insertar y
buscar nodos en la estructura arbórea
• La clase EjArbol en la que se define el método principal para permitir al usuario la
interacción con el programa que gestiona al árbol binario.

El diagrama de clases propuesto es el siguiente:

Las clases codificadas quedan de la siguiente forma


package ejarbol;
public class Nodo {
//Atributos
private int elemento;
private Nodo ramaIz; //Apunta a la rama izquierda
private Nodo ramaDer; //Apunta a la rama derecha

public Nodo(int elemento ) {//Constructor


this.elemento = elemento;
ramaIz=null;
ramaDer=null; }

public void InsertaBinario (int elem){//define las acciones a verificar al momento de insertar nodo
if(elem < this.elemento){
if (ramaIz == null)
ramaIz = new Nodo(elem);
else
ramaIz.InsertaBinario(elem);
} 51
else{
if (elem > this.elemento){
if (ramaDer == null)
ramaDer = new Nodo(elem);
else
ramaDer.InsertaBinario(elem);
}
} }
//Setters y Getters
public int getElemento() { return elemento; }
public void setElemento(int elemento) { this.elemento = elemento; }
public Nodo getRamaIz() { return ramaIz; }
public void setRamaIz(Nodo ramaIz) { this.ramaIz = ramaIz; }
public Nodo getRamaDer() { return ramaDer; }
public void setRamaDer(Nodo ramaDer) { this.ramaDer = ramaDer; }

@Override
public String toString() {
return "Nodo{" + "elemento=" + elemento + ", ramaIz=" + ramaIz + ", ramaDer=" + ramaDer + '}';
}
}

Clase ArbolB
package ejarbol;
public class ArbolB {
Nodo padre;
Nodo raiz;

public ArbolB(){ //Constructor


raiz = null; }

public void InsertaNodo (int elem){ //Inserción de un elemento en el árbol


if(raiz == null)
raiz = new Nodo (elem);
else
raiz.InsertaBinario (elem);
}

//recorrido preorden Recursivo del árbol


public void Preorden (Nodo Nodo){
if(Nodo == null) return;
else{
System.out.print (Nodo.getElemento() + " ");
Preorden (Nodo.getRamaIz());
Preorden (Nodo.getRamaDer());
}
}

//PostOrden recursivo del árbol


public void PostOrden (Nodo Nodo){
if(Nodo == null) return; 52
else{
PostOrden (Nodo.getRamaIz());
PostOrden (Nodo.getRamaDer());
System.out.print (Nodo.getElemento() + " ");
}
}

//Inorden Recursivo del árbol


public void Inorden (Nodo Nodo){
if(Nodo == null) return;
else{
Inorden (Nodo.getRamaIz());
System.out.print(Nodo.getElemento() + " ");
Inorden (Nodo.getRamaDer());
}
}
//Busca un elemento en el árbol
void Busqueda (int Elem, Nodo A){
if((A == null) | (A.getElemento() == Elem)){
System.out.print(A.getElemento() + " ");
return;
}
else{
if(Elem>A.getElemento()) Busqueda (Elem, A.getRamaDer());
else Busqueda ( Elem, A.getRamaIz());
}
}
//Altura del árbol
public int Altura (Nodo Nodo){ // cuenta el número de niveles del árbol
int Altder = (Nodo.getRamaDer() == null? 0:1 + Altura (Nodo.getRamaDer()));
int Altizq = (Nodo.getRamaIz()== null? 0:1 + Altura (Nodo.getRamaDer()));
return Math.max(Altder,Altizq);
}

Clase EjArbol
package ejarbol;
import java.util.Scanner;

public class EjArbol {


public static void main(String[] args) {
ArbolB A = new ArbolB();
int indice;
int opc=0;
Scanner leer = new Scanner (System.in);
System.out.println("****BIENVENIDO A ÁRBOL BINARIO ORDENADO****");
do{
System.out.println("MENÚ\n");
System.out.println("1.Insertar");
System.out.println("2.Eliminar");
System.out.println("3.Recorrido en Pre orden"); 53
System.out.println("4.Recorrido en In orden");
System.out.println("5.Recorrido en Pos orden");
System.out.println("6.Salir");
System.out.println("seleccione opción --->\n");
opc=leer.nextInt();

switch(opc) {
case 1:
System.out.println("Dame el número a insertar\n");
int p=leer.nextInt();
A.InsertaNodo(p); break;

case 2: break;

case 3:
System.out.print("El recorrido en Preorden es: ");
A.Preorden (A.raiz);
System.out.println(); break;

case 4:
System.out.print("El recorrido en Inorden es: ");
A.Inorden (A.raiz);
System.out.println(); break;
case 5:
System.out.print("El recorrido en Postorden es: ");
A.PostOrden (A.raiz);
System.out.println(); break;
}//fin switch
}while(opc!=6);//fin do

} }

Ejercicio a realizar
Con base en el código del ejemplo, completa el código para que el usuario pueda buscar
a un elemento y agrega lo necesario para que el usuario pueda recorrer al árbol por
amplitud
Evaluación:

Evidencia:
Programa ejecutándose, código de las clases modificadas y evaluadas por el profesor
Práctica 8: Manejo de archivos y procesamiento de datos. 54
U. Competencia 4: Manejo de archivos.
Duración Estimada: 3 sesiones de 50 minutos
Objetivo: Implementar programas de computadora utilizando persistencia de
objetos, archivos secuenciales de texto y directos, para la solución de problemas
que impliquen el procesamiento de datos.

Introducción Teórica:

REGISTROS
Para la informática, existen distintos tipos de registros, pero en todos los casos hay una
referencia al concepto de almacenar datos o información sobre el proceso o uso de las
computadoras. En específico en lo que se refiere al ámbito de la programación este tipo
de dato está formado por varios elementos en asociación que responden a una misma
estructura. Los registros de programación pueden ser elementales o complejos y
guardan información sobre cómo el software en particular trabajará en cada momento.
En cualquier caso, el empleo de registros tiene el fin de almacenar información es decir
cualquier tipo de datos, ponerla en relación y colocarla al alcance bajo un índice o
sistema de orden que permita su acceso y uso en cualquier momento.
Por lo tanto los registros son el mecanismo que tanto el usuario como el sistema
computacional utilizan para acceder y utilizar toda la información. De lo que resulta ser
un registro se puede derivar distintos conceptos, entre estos están persistencia de
objetos y generación de archivos.

Nombre del registro

Representación Contenido delregistro


gráfica de un registro

PERSISTENCIA
“Es la propiedad de un objeto por la que su existencia trasciende el tiempo, es decir, el
objeto continúa existiendo después de que su creador deja de existir y/o espacio.” (Lara,
2015).
Visto de otra forma, la persistencia es la acción de mantener la información del objeto
55
de una manera permanente, es decir, guardarla. Pero también debe de poder
recuperarse dicha información para que pueda ser utilizada nuevamente. Por ejemplo,
en lo que se refiere a archivos son las acciones de crear, escribir y leer datos.
La persistencia de objetos en programación orientada a objetos se clasifica en:

• Objetos transitorios: Son aquellos que su tiempo de vida depende del espacio
del proceso que lo creo.
• Objetos persistentes: Son aquellos que su estado es almacenado en un medio
temporal para su posterior reconstrucción y utilización, por lo cual el objeto no
depende del proceso que lo creo.

Ejemplo de instancia y persistencia transitoria de un objeto de la clase persona.

Archivos
Es un conjunto de bits almacenados en un dispositivo y accesible a través de un camino
de acceso que lo identifica, a este camino se le conoce como pathname. En lo que se
refiere a java, los tipos de archivos o también llamados ficheros se diferencian por las
clases que se usan para representarlos y manipularlos.
Las clases estándar en java que se usan para el tratamiento de archivos están en el
paquete java.io por lo que deben ser importadas para poder manipular ficheros.

Criterios para distinguir distintos de archivos.

El modo de acceso en archivos java es de dos modos básicos de acceso a la


información:
• Secuencial: La información en estos archivos es una secuencia de bytes o caracteres,
por lo que para acceder a la información debe pasar desde el primer byte hasta el byte
que se necesita leer.
56
• Acceso directo: Este modo permite acceder directamente a la información del byte que
se necesita de manera inmediata (ejemplo básico de un acceso directo es el que se da
al acceder a un espacio de memoria en los arreglos).

Cuando se manejan archivos en java es necesario el tratamiento de errores o lo que se


conoce como excepciones. Estas son un mecanismo que permite a los métodos indicar
que algo “anómalo” ha sucedido que impide su correcto funcionamiento, de manera que
quien los invoca puede detectar el error que esté sucediendo.
Las excepciones no son tema propio de la unidad IV, así que a continuación se muestra
un ejemplo de un tratamiento muy simplificado de errores para que java de por correcto
o incorrecto los códigos generados.

Tratamiento de excepciones simplificado.

Manipulación de archivos.

A continuación, se muestra cómo crear un archivo de texto plano en Java con dos
técnicas diferentes.
Primer método, la clase PrintWriter recibe una cadena con la ruta del archivo o una
instancia de File (en el ejemplo solo se usa directamente la ruta del archivo txt
pathname), el segundo parámetro es el tipo de encoding es usado (UTF-8), que resulta
útil si se necesita guardar texto con caracteres especiales como los utilizados en el
lenguaje español.
El trabajo de escritura se hace con el método println, que permite escribir otros tipos de
datos como enteros, de punto flotante, booleanos y caracteres. ¿Cómo hacerlo?
57

Creación de un archivo y escritura, usando la clase PrintWriter

Debe notarse que primeramente si el archivo no fue previamente creado antes de


ejecutar el código, la clase PrintWriter creara el archivo, sin embargo, si ya existe el
fichero se usara para seguir escribiendo dentro del ya existente. Por consecuencia si
se crea un archivo o se abre un ya existente resulta necesario invocar al método close()
que cierra el flujo de lectura o escritura al fichero.
Segundo método, usando las clases FileWriter y BufferWriter, donde se usa el método
write que permite escribir cadenas o arreglos de caracteres.
La escritura se hace en estas sentencias, donde la clase FileWriter debe crearse con
una referencia a una clase File que contiene los detalles del archivo que será creado y
el contenido del texto se crea con la función bw.write() de la clase BufferedWriter. Este
segundo método resulta más complejo, pero permite mayor versatilidad con el manejo
de archivos.
58

Creación de un archivo y escritura, usando las clases FileWriter y BufferWriter

En el anterior ejemplo únicamente las acciones son creación y escritura dentro de


ficheros, sin embargo, la forma de leer datos no se aprecia. Para poder leer se necesitan
implementar las clases FileReader y BufferReader invocando al método readLine() de
la clase BufferReader.

Procedimiento
La práctica a elaborar consistirá en lograr unificar todos los métodos anteriormente
mencionados en un solo código, es decir utilizar las clases PrintWriter, FileWriter,
FileReader, BufferWriter y BufferReader junto con sus respectivos métodos para
escribir y leer datos. El programa debera funcionar de la siguiente manera:
1. Solicitar al usuario que ingrese un texto de al menos 150 palabras que incluya
tanto caracteres como numeros, por ejemplo:
“Reconocido por su legibilidad y simplicidad, Java es uno de los lenguajes de programación
más adoptados: más de 9 millones de desarrolladores lo usan y está presente en 7 mil millones 59
de dispositivos en todo el mundo. Desde 2001 se mantiene en las primeras posiciones…”

El texto que ingrese el usuario deberá ser almacenado en una variable o más de tipo
String.
2. Crear un archivo .txt llamado “mi texto” en el directorio raíz del proyecto java. El archivo
se creara con la clase PrintWriter y el contenido deberá ser lo que el usuario ingreso
como texto.

3. Utilizando las clases FileReader y BufferReader abrir nuevamente el archivo “mi texto”
deberá extraer el texto y almacenarlo en un arreglo de tipo carácter.

4. Crear un método que permita contabilizar la frecuencia de aparición de cada letra y cada
número que aparece en el texto extraído (indistintamente de mayúsculas y minúsculas).
Por ejemplo del texto, “Desde 2001 se mantiene en las primeras posiciones…”

‘A’=3, ‘B’=0, ‘C’=1, hasta, ‘Z’=0, ‘0’=2, ‘1’=1, ‘2’=1, hasta, ‘9’=0

5. Finalmente, utilizando las clases FileWriter y BufferWriter, crear un archivo llamado


“frecuencias” y escribir la información que encontró el método descrito en el punto
anterior.

Recuerda que puedes consultar el Anexo de información para tener más datos sobre
las clases del paquete java.io

Evaluación:
Aciertos: 20 puntos por cada punto codificado y funcionamiento correcto.

Evidencia a obtener:

Ejecución del proyecto evaluado por el profesor, mostrando el contendido generado por
los métodos solicitados. Los archivos solicitados deberán contener la información
correcta.

Referencias
Lara, D. (8 de 10 de 2015). styde. Obtenido de https://styde.net/concurrencia-y-
persistencia-en-programacion-orientada-a-objetos/
Torres, A. C. (2017). Aprenda a Diseñar Algoritmos. Universidad Nacional Abierta y a
Distancia.
60
ANEXO

Métodos más usados de la clase String

Métodos de la clase StringBuffer


Métodos de la clase Math
61

Métodos de la clase vector


Clases útiles de Entrada y Salida java
62

También podría gustarte