Guia Edoo2012

122
Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 1 1 INTRODUCCION A LAS ESTRUCTURAS DE DATOS 1.1 Abstracción Términos simples: Es un proceso mental, mediante el cual se extraen los rasgos esenciales de algo para representarlos por medio de un lenguaje gráfico o escrito. Debido a que es un proceso mental es una acción subjetiva y creativa es decir: depende del contexto psicológico de la persona que la realiza. Términos de la POO: Constituye un principio de la POO que: “Enfatiza en detalles que son significativos y que suprime otros detalles que son por el momento irrelevantes”. “Denota las características esenciales de un objeto que lo distinguen de todas las otras clases de objetos”. 1.2 Importancia de la abstracción Dato: unidad básica de la información, que por lo general por si solo no dice nada. Información: es el conocimiento que puede comunicarse, generalmente es el conjunto de datos pero que tienen relación y que tienen sentido; La abstracción: es una técnica o metodología que permite diseñar o modelar Estructuras de Datos, Consiste en representar bajos ciertos lineamientos de formato las características esenciales de una Estructura de Datos. Su importancia radica en que la abstracción es una capacidad para modelar una realidad por medio de herramientas computacionales. 1.3 Estructuras de Datos Cualquier colección o grupo de datos organizados, de tal forma que tengan asociados un conjunto de operaciones para poder manipularlos. La mayoría de lenguajes de programación de alto nivel disponen de tipos de datos estructurados o estructuras de datos predefinidas. Ejemplo: Arreglos, que no son más que un conjunto de datos, todos del mismo tipo, con una organización lineal y con métodos claros de acceso a través de sus subíndices. Las operaciones tradicionales son: comparación, asignación, escritura, lectura.

Transcript of Guia Edoo2012

Page 1: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 1

1 INTRODUCCION A LAS ESTRUCTURAS DE DATOS 1.1 AbstracciónTérminos simples: Es un proceso mental, mediante el cual se extraen los rasgos esenciales de algo para representarlos por medio de un lenguaje gráfico o escrito. Debido a que es un proceso mental es una acción subjetiva y creativa es decir: depende del contexto psicológico de la persona que la realiza.

Términos de la POO: Constituye un principio de la POO que:

“Enfatiza en detalles que son significativos y que suprime otros detalles que son por el momento irrelevantes”.

“Denota las características esenciales de un objeto que lo distinguen de todas las otras clases de objetos”.

1.2 Importancia de la abstracciónDato: unidad básica de la información, que por lo general por si solo no dice nada.Información: es el conocimiento que puede comunicarse, generalmente es el conjunto de datos pero que tienen relación y que tienen sentido;

La abstracción: es una técnica o metodología que permite diseñar o modelar Estructuras de Datos, Consiste en representar bajos ciertos lineamientos de formato las características esenciales de una Estructura de Datos.

Su importancia radica en que la abstracción es una capacidad para modelar una realidad por medio de herramientas computacionales.

1.3 Estructuras de DatosCualquier colección o grupo de datos organizados, de tal forma que tengan asociados un conjunto de operaciones para poder manipularlos.

La mayoría de lenguajes de programación de alto nivel disponen de tipos de datos estructurados o estructuras de datos predefinidas.

Ejemplo: Arreglos, que no son más que un conjunto de datos, todos del mismo tipo, con una organización lineal y con métodos claros de acceso a través de sus subíndices. Las operaciones tradicionales son: comparación, asignación, escritura, lectura.

Page 2: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 2

Tipos de Estructuras

Hacen referencia a un solo valor a la vez. Ocupan una sola casilla de memoria Pueden ser: Entero, real, lógico carácter (donde: su

tamaño depende del Lenguaje de Programación).

Se caracteriza por el hecho de que con un nombre se hace referencia a un grupo de casillas de memoria es decir ésta estructura está formada: Por uno o varios datos simples. Por uno o varios datos compuestos. Porque pueden tener algún tipo de comportamiento

(métodos).

ED:Estructura de almacenamiento + Operaciones de manipulación (métodos).

Clasificación de las Estructuras de Datos

ESTATICAS DINAMICAS Tienen una cantidad fija de

memoria principal Delimitan el espacio que ocupan

en memoria en tiempo de compilación

Ejemplo: Arreglos o Arrays, Cadenas // declaraciónint [ ] A;

// crea un arreglo con 10 números// enterosA = new int [ 10 ] ;

No tienen limitación en el tamaño de memoria principal ocupada

El espacio de memoria a ocupar se determina en tiempo de ejecución

Ejemplo: listas, árboles, grafos, etc.

public class Nodo{ // Atributos private int dato; private Nodo sig; // Constructor public Nodo (Nodo ns){ sig = sig; } // Métodos a implementar para la // clase Nodo}

TDA: Tipo de Dato Abstracto: Es el modelo, junto con varias operaciones definidas sobre el modelo, con lo que se representa a la estructura y el comportamiento del mundo real. El TDA, especifica el ¿Qué? más no el ¿Cómo?

1.4 Tipo de Dato Abstracto ( T.D.A)TDA es un modelo matemático de estructuras de datos que especifica los tipos de datos almacenados, las operaciones definidas sobre esos datos y los tipos de los parámetros de esas operaciones.

COMPUESTAS

SIMPLES

Page 3: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 3

Un TDA define lo que cada operación debe hacer, más no como lo debe hacer. En un lenguaje de programación como Java un TDA puede ser expresado por una interface, que es una simple lista de declaraciones de métodos.

Un TDA es materializado por una estructura de datos concreta, en Java, es modelada por una clase. Una clase define los datos que serán almacenados y las operaciones soportadas por los objetos que son instancia de la clase. Al contrario de la las interfaces, las clases especifican como las operaciones son ejecutadas (Implementación).

La técnica de la abstracción de datos establece que al diseñar una nueva Estructura de Datos – pasa a ser un TDA que luego podrá ser implementado en cualquier lenguaje de programación.

Especificación lógica de un TDA

Es un documento en el que se plasma la abstracción realizada al diseñar una Estructura de Datos y a partir del cual se implementa la Estructura de Datos. En dicho documento se definirán claramente todas las reglas en las que podrá usarse el TDA

Partes:

1. Elementos que conforman la Estructura de DatosDescribe el tipo de los datos individuales que guardara la estructura. Ejemplo: números enteros, números reales, caracteres, fechas, registro con los datos de un empleado.

2. Tipo de organización en que se guardara los elementos

Lineal: Si hay una relación de uno a uno entre los elementos. (Arreglos)

Jerárquica: Si hay una relación de uno a muchos entre los elementos. (Arboles)

Red: Relación de muchos a muchos entre los elementos (grafos)

Sin relación: Si no hay relación entre los elementos

Page 4: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 4

3. Dominio de la estructura (opcional)Se describirá la capacidad de la estructura de datos en cuanto al rango posible de datos por guardar.

4. Descripción de las operaciones de la estructura Para cada operación se debe considerar los siguientes puntos:

• Nombre de la operaciónDescripción breve de su utilidad

• Datos de entrada a la operación• Datos que generan como salida la operación• Precondición: condición que debe cumplirse ANTES de utilizar la

operación para que se ejecute sin problemas.• Postcondicion : condición en que queda el TDA DESPUES de ejecutar la

operación.

“Definir claramente la especificación lógica del TDA, facilita la implementación y aplicación de la Estructura de Datos.”

Importante: Averigua varios ejemplos de aplicaciones dentro del campo informático, donde se identifique a una estructura de datos y el tipo de organización en su implementación INVESTIGA..!!!

1.5 Niveles de abstracción de datos

1.- Nivel (Lógico o abstracto)Corresponde a la especificación lógica del TDA. En este nivel se define abstractamente a la Estructura de Datos y las operaciones relacionadas con ella, independientemente del lenguaje de programación en el que se implemente o utilice la Estructura.

2.- Nivel (Físico o de Implementación)Se decide el lenguaje de Programación en el que se va a implementar la estructura de datos. Así como los tipos de datos ya definidos en el lenguaje de programación servirán para representar a la estructura. y luego se implementa cada una de las operaciones diseñadas en el TDA

3. – Nivel de Aplicación o de Uso: El programador usará el TDA para resolver determinadas aplicaciones, el uso del TDA se limita a llamar a las operaciones sobre la estructura que se requiera cuidando siempre de cumplir las reglas de cada operación especificadas en el nivel lógico.

Analiza:Identifica los niveles de abstracción en el siguiente ejemplo de la vida real como lo es: “Construir un edificio”. Piensa en otros casos más, comenta con tus compañeros y con tu profesora !!!

Analiza:Identifica los niveles de abstracción en el siguiente ejemplo de la vida real como lo es: “Construir un edificio”. Piensa en otros casos más, comenta con tus compañeros y con tu profesora !!!

Page 5: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 5

Ventajas de utilizar la Técnica de Abstracción de Datos

Se tiene una implementación más clara, documentable y fácil de darle mantenimiento.

Debido a la independencia de datos, se puede crear paquetes como unidades de software reutilizable, con los que se obtienen Estructuras de Datos genéricas.

Facilita y hace más rápido el desarrollo de aplicaciones.

Ejemplo de TDA:

En un sistema bancario las cuentas de cheques de los clientes pueden considerarse objetos. Todos ellos pertenecen a una cuenta llamada CUENTA _CHEQUES que definen para cada instancia los siguientes datos:

Numero de la cuenta. Nombre del cliente. Sucursal donde se abrió la cuenta. Saldo de la cuenta.

Y las siguientes Operaciones Abrir cuenta Deposito Retiro Consultar saldo

A continuación elaboramos la especificación lógica que contienen los siguientes puntos:

TDA: CUENTA _CHEQUES.1.- Elementos que conforman la estructura de datosNúmero de cuenta cadenaNombre del cliente cadenaSucursal donde se abrió cadenaSaldo de la cuenta real2.- Tipo de organización.El tipo de organización es lineal entre los números de cuentas3.- DominioExiste entre 0 y 10000 cuentas, el dominio será todos aquello números que se ubiquen dentro del rango establecido.

4.- Descripción de las operaciones- ABRIR_CUENTA:Utilidad: Esta operación se ejecutará al crear un objeto de la clase CUENTA_CHEQUES, e implica solicitar

por teclado los datos correspondientes para guardarlos en los atributos del objeto y colocar el valor de cero al saldo inicial.

Datos de entrada:Nombre del cliente, Nombre de la sucursal, (Saldo inicial de la cuenta será cero)Datos de salida: Número de cuentaPrecondiciones: NingunaPostcondiciones: Los datos ingresados serán guardados en los atributos correspondientes del objeto.

- DEPOSITARUtilidad: Agrega la cantidad especificada al saldo de la cuenta.Datos de Entrada: Monto a depositarDatos de Salida: Saldo disponible aumentadoPrecondiciones: Número de la cuenta exista Que la cantidad a depositar sea mayor a ceroPostcondiciones: Saldo de la cuenta agregado la cantidad especificada

- RETIRAR

Page 6: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 6

Utilidad: Quita al saldo de la cuenta la cantidad espeficada, validando que sea posible retirar esa cantidad.Datos de Entrada: Monto a retirarDatos de Salida: saldo disponible disminuidoPrecondiciones: Que el número de cuenta exista Que el saldo disponible sea mayor que la cantidad especificado para el retiro.Postcondiciones: saldo disponible disminuido en la cantidad especificada

- CONSULTAR_SALDOUtilidad: Mostrar en pantalla el saldo de la cuenta correspondienteDatos de Entrada: Número de cuentaDatos de Salida: Saldo disponiblePrecondiciones: Exista el número de cuentaPostcondiciones: Ninguna

1.6 Representación de una estructura de datosPuede entenderse como el punto de conexión entre la especificación lógica de una TDA y su implementación en un lenguaje de programación particular.Dentro del proceso de abstracción de datos la representación de una estructura corresponde al inicio del segundo nivel de abstracción es decir el nivel físico. Constituye un esquema de cómo se almacenarán los elementos de la Estructura de Datos, en la memoria de tal forma que se logre su óptimo aprovechamiento.

Tipos de representaciones para una Estructura de Datos

Independientemente de las facilidades de implementación que ofrezcan los lenguajes de programación, una Estructura de Datos puede representarse de dos formas:

1. Representación de una estructura de datos por posiciones El lugar físico donde se almacena un elemento determina automáticamente su posición relativa en la estructura de datos. Se podría considerar como un espacio de almacenamiento contíguo donde:

cada lugar sirve para almacenar un elemento.Un elemento esta en un lugar K, por lo tanto

Tipos

1. Por posiciones

2. Por ligas Almacenamiento disperso

Almacenamiento contiguo

Tendrá la k- ésima posición dentro de la estructura

El elemento K+1 estará después de K por lo tanto se almacenará en el lugar k+1 del espacio de almacenamiento.

Page 7: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 7

1 Elemento 12 Elemento 2 Existe una relación lineal

… Elemento 1 pos 1K Elemento k Elemento 2 pos 2K+1 Elemento k+1 …. Elemento N pos N

…N Elemento N

Herramientas en los lenguajes de programación para desarrollar una representación por posiciones

Todos los lenguajes de programación proveen al programador de herramientas útiles para representar Estructuras de Datos en forma contigua, más conocidas como estructuras de datos implícitas del lenguaje.

1. Arreglos de elementos uniformes.- Solo almacenan un conjunto de elementos de un mismo tipo simple enteros, reales, cadenas o tipos compuestos registros con elementos de diferentes tipos2. Registros de elementos de diversos tipos.- Permiten definir estructuras que contienen valores de diferentes tipos, almacenados como si fuera unidad.3.- Archivos Secuenciales.- el almacenamiento es contiguo, son similares a los arreglos, permiten almacenar un conjunto de elementos aunque lo hace en la memoria secundaria.Ventajas

- Fácil implementación.- Rapidez de recorrido, debido a que la dirección de cada elemento está

implícita en su posición física.Desventajas

- Al realizar manipulaciones de los elementoso Al agregar un nuevo elemento en algún lugar que no sea el

último, se tiene que desplazar los elementos hacia abajo que están después de la posición de inserción deseada logrando que se genere un espacio para poder agregar un nuevo elemento.

o Al borrar un elemento que no sea el último deja un espacio no permitido entre los elementos, para lo cual se tiene que desplazar una posición hacia arriba los elementos, que están después del elemento borrado.

2. Representación de una estructura de datos por ligas En este tipo de representación la ubicación física de un elemento no determina la posición relativa que tiene dentro de la Estructura de Datos.El almacenamiento se realiza en forma dispersa: dos elementos contiguos en la Estructura de Datos no necesariamente deben estar almacenados físicamente en posiciones contiguas dentro del espacio de almacenamiento.

1 Elemento k Dir k+12 Almacenamiento disperso

Page 8: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 8

… Lista Uno:Elemento k, el que sigue está en la dirección Dir k+1, que es el Elemento 1, el que sigue está en la Dir 2 que es nula.

K Lista Dos.K+1 Elemento 1 Dir 2 Elemento k+1, el que sigue tiene

dirección … Nula Dir k+2

N Elemento k+1 Dir k+2

En necesario que cada elemento almacene la dirección física donde se ubica el elemento que le sigue en el Estructura de tal forma que puedan mantener una relación en donde está cada uno de los elementos.

Características1.- La posición física del elemento no determina la posición relativa dentro de la

Estructura de datos.2.- El almacenamiento se realiza en forma dispersa.3.- Es necesario que cada elemento almacena la dirección física del siguiente

elemento.4.- Cada elemento debe contener 2 o más campos (dato y dirección).

Ventajas 1.- La representación no es exclusiva debido a que mantiene una organización

lineal2.- Posibilidad de agregar y eliminar elementos de la estructura, sin tener que desplazar los elementos que ya estaban en ella.3.- Permite un uso más eficiente del espacio de almacenamiento ya que puede crecer o decrecer en tiempo de ejecución, según requiera el usuario.

Desventajas 1.- Cada elemento deber “recordar” donde está alguno de los elementos, cada

espacio es un elemento compuesto por (dato y la dirección del siguiente elemento).

2.- Las operaciones requieren mayor tiempo de procesamiento, debido a que el acceso no es directo, se requiere realizar un recorrido hasta encontrar el elemento deseado.

Herramientas en los Lenguajes de Programación para desarrollar una Representación por Ligas

En la mayoría no existen herramientas predefinidas, por lo tanto es el programador implementa las estructuras. Se recomienda el uso de apuntadores, un apuntador se define como un tipo capaz de almacenar una dirección de memoria, se considera como una referencia indirecta a un elemento.

Page 9: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 9

2 ESTRUCTURAS DE DATOS BÁSICAS 2.1 Cadenas o StringsCadena: Es una secuencia finita de símbolos tomados como un conjunto de caracteres (letras, números, caracteres especiales).

Strings: Internamente es un arreglo de caracteres, dependiendo del lenguaje de Programación generalmente se considera el inicio de la cadena en la posición 0.

La importancia del String radica en que la mayor parte de la información que se maneja actualmente en casi cualquier área del conocimiento puede verse como una secuencia de caracteres. Ejemplo: el nombre de una persona, el nombre del un libro, la información de un texto son vistas como cadenas de caracteres.

Conceptualización de un String como un TDASe puede diseñar muchos TDA, que definen una String considerando que operaciones se tomarán como básicas para el funcionamiento de dicha estructura y cuál será el conjunto de caracteres que aceptarán como parte de él.

TDA: StringElementos: Conjunto de letras mayúsculas y minúsculas, caracteres especiales y dígitos.Estructura: Existe una relación lineal, debido a que se considera como una cadena de caracteres.Dominio: Suponiendo que los Strings pueden almacenar entre 0 y 80 caracteres, su dominio será el conjunto de

todas las cadenas que puedan formar con la combinación de elementos de esa longitud.Operaciones: - INICIALIZAR

Utilidad: Nos sirve para definir el espacio a ocupar en la memoria por el string.Datos de entrada: Tamaño de memoria para el StringDatos de salida: El string S es nulo (esta vacio)Precondición: NingunaPostcondición: el String S es nulo.

- INSERTAR_CARÁCTER_AL_FINALUtilidad: añadir un carácter al finalDatos de entrada: String S y la letra L que se insertará al final de S.Datos de salida: String S modificadoPrecondición: El numero de letras en S es menor que 80.Postcondición: el string S tiene una letra más en el extremo derecho

- BORRAR_ CARÁCTER_AL_INICIO- Utilidad: Permite borrar un carácter al inicio del String- Datos de entrada: String S al que se le borrara la primera letra- Datos de salida: String S modificado- Precondición: el String S exista y no sea nulo- Postcondicion: el String S tiene una letra menos en el extremo izquierdo

- CONCATENARUtilidad: Unir dos Strings S1 y S2Datos de entrada: Strings S1 y S2.Datos de salida: String S1 modificado.Precondición: La suma de la longitud de S1 y S2 debe ser menor que 80.Postcondición: A string S1 se le agrega todos los caracteres de s2(en el extremo derecho); s2 no se modifica.

- BUSCAR_SUBSTRINGUtilidad: Buscar un Substring S2 en S1Datos de entrada: Strings S1 y S2.Datos de salida: verdadero si S2 está contenida en S1, falso en caso contrarioPrecondición: S1 y S2 existanPostcondición: ninguna

Page 10: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 10

- OBTENER_ CARACTERUtilidad: Sirve para encontrar un carácter dentro del StringDatos de entrada: String S donde se desea conocer cierto carácter y la posición i del carácter que se desea conocer.Datos de salida: Carácter que se encuentra en la posición i del String SPrecondición: El String S no sea nulo e i debe ser un valor entre 1 y la longitud de SPostcondición: Ninguna

- VERIFICA_VACIOUtilidad: Sirve para verificar si una cadena o String está vacía o noDatos de entrada: String S que será verificadoDatos de salida: Verdadero si el String S no tiene caracteres y Falso en caso contrario.Precondición: Ninguna.Postcondición: Ninguna.

- VERIFICAR_LLENAUtilidad: Sirve para verificar si una cadena está llena o noDatos de entrada: String S que será verificadoDatos de salida: Verdadero si la cadena o String S contiene 80 caracteres y Falso en caso contrarioPrecondición: NingunaPostcondición: Ninguna

- INVIERTEUtilidad: Sirve para invertir el orden de los caracteres de un String.Datos de entrada: String S1 a invertirDatos de salida: String S2Precondición: la secuencia de la cadena S se invierte, de forma que el primer carácter toma el lugar del último, el segundo del penúltimo y así sucesivamente.Postcondición: El String S1 cambia sus caracteres y se convierte en String S2

Page 11: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 11

Representación del TDA String.

Se puede almacenar en la memoria mediante almacenamiento contiguo y también podrá utilizarse el almacenamiento no contiguo.

1. Uso de un Carácter Centinela

Los caracteres se almacenan en un arreglo con longitud predefinida.

Se delimitan por un carácter especial, denominado “Centinela”-equivale a un carácter nulo en la mayoría de los lenguajes de programación ‘\0’.

MARTES\00 1 2 3 4 5………………...n

Desventaja.

El carácter centinela ocupará un espacio dentro del String.

No se conoce la longitud del String por lo que se debería programar un método que permita realizar dicha operación.

Los lenguajes de programación que utilizan este tipo de almacenamiento son: C Y C++.

2. Almacenamiento de la longitud del String

Los elementos del String se almacenan en un arreglo de longitud predefinida.

La Longitud actual del String se almacenan en la posición 0 y no forma parte del String. max

ASCII6MARTES.... 0 1 2 3 4 5 6 N

Desventaja.

Debido a que la longitud ocupa una posición de un carácter la longitud se restringe a 265.

El lenguaje de programación que utiliza este tipo de almacenamiento es el Pascal.

ALMA CC OE NN TA IM GI UE ONTO

Page 12: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 12

EJERCICIOS PROPUESTOS

1. Cree un método que permita generar y presentar la letras del alfabeto mayúsculas separadas por un guión

2. Cree un método que permita contar el número de letras A que existen dentro de una cadena.

3. Cree un método que permita contar el número de letras mayúsculas que existen dentro de una cadena.

4. Cree un método que permita contar el número de palabras que existe dentro de una frase.

5. Cree un método que permita cambiar de mayúsculas a minúsculas y viceversa

1. Lista encadenada de nodos con un caracter

Genera una lista encadenada donde cada nodo almacena un solo carácter y la dirección del siguiente nodo de la lista.

Ventaja.

Puede generar Strings de longitud infinita.

Desventaja.

Desperdicio del 80% en la memoria debido al almacenamiento en tantas direcciones de nodos.

2. Lista encadenada de nodos con N caracteres

Genera una lista encadenada donde cada uno de los nodos almacena N caracteres, del String (N>1) y la dirección donde se encuentra el siguiente nodo.

Ventajas.

Genera Strings de longitud infinita y se disminuye el desperdicio de memoria.

Desventajas.

La implementación de sus operaciones es más compleja, ya que la información contenida en el String está almacenada en forma de substrings.

A NL OMA CC OE NN TA IM GI UE ONTO

M TRA E S

UNIVERS IDAD NA CIONAL DE LOJA

Page 13: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 13

2.2 Arreglos Unidimensionales (Arrays)

¿Qué es un arreglo Unidimensional?

Es un tipo de dato estructurado, está formado por una colección finita y ordenada de datos del mismo tipo.Además de conoce como una estructura natural, que es utilizada para modelar lista de elementos iguales, donde el tipo de acceso es “DIRECTO” debido al uso de un índice que indica la posición relativa del elemento dentro de la Estructura de Datos y además porque para acceder a cada elemento se lo hace directamente sin tener que consultar elementos anteriores o posteriores.

Representación en memoria.

TDA: ARREGLO.Elementos: Números enteros.Estructura: Lineal entre los elementos del arreglo.Dominio: Los datos o elementos posibles a guardar estarán en el rango de 0-20 números.Operaciones:

- OBTENERUtilidad: Regresa el elemento del arreglo A, que tiene un rango r.Datos Entrada: índice iDatos Salida: elemento ePrecondiciones: elemento e, este guardado dentro del arreglo A.

índice i sea < rango.Postcondiciones: se produce una condición de error si el índice i<0 o si i > N-1, donde n es la cantidad actual de elementos.

- AGREGARUtilidad: Colocar un elemento e, en el arreglo A del rango r.Datos Entrada: el elemento nuevo e Datos Salida: El arreglo A con un elemento masPrecondiciones: haya espacio en el arreglo

Analiza:Se tienen las notas de un grupo de 90 estudiantes y necesitamos saber cuántos de estos estudiantes tienen tienen una nota superior al promedio del grupo. ¿Cómo podríamos resolver este problema?.... Piensa en varias soluciones, comenta con tus compañeros y con tu profesora…..!!!

Analiza:Se tienen las notas de un grupo de 90 estudiantes y necesitamos saber cuántos de estos estudiantes tienen tienen una nota superior al promedio del grupo. ¿Cómo podríamos resolver este problema?.... Piensa en varias soluciones, comenta con tus compañeros y con tu profesora…..!!!

100 A[0]101 A[1]102 A[2]103 A[3]104 A[4]

.

.

.

.

Page 14: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 14

Postcondiciones: El arreglo con un elemento agregado.

- MODIFICARUtilidad: Sustituir el elemento e del arreglo A de rango r en el índice i.Datos Entrada: elemento ea, y el nuevo elemento ne Datos Salida: mensajePrecondiciones: El arreglo este creado y no este vacioPost condiciones: Se produce un mensaje de error, si el elemento no se encuentra en el arreglo.- ELIMINAR

Utilidad: quitar el elemento e del arreglo A de rango r en el índice i.Datos Entrada: elemento eDatos Salida: mensaje indicando que la operación ha tenido éxito.Precondiciones: el arreglo no este vacio y que el elemento se encuentre en el arregloPostcondiciones: Se produce un mensaje de error, si el elemento no se encuentra en el arreglo.

Representación de Arreglos

Manejo de arreglos en Java.Los arreglos son considerados como objetos cuyo tamaño se determina en tiempo de compilación y no puede ser modificado en tiempo de ejecución.Pueden contener. Tipos de datos (int, char, boolean, float)

Objetos de clases (los del API, o los definidos por el usuario).

Se hace uso del operador [ ].

Dispone de una función miembro para consultar la longitud de arreglo length.

Declaración de un arreglo.

<tipo dato/clase> [ ] identificador;

<tipo_dato/clase> identificador [ ];

Ejemplos:String [ ] días_Semana;int [ ] edades_Estudiantes;double [ ] notas;char [ ] vocales;boolean [ ] productos disponibles.

Creación de los arreglos.

Reservar el espacio en memoria y se requiere de un constructor que es el operador (new).

dias_Semana = new String[7];

Page 15: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 15

edades_Estudiantes = new int[20];notas = new double[10];vocales = new char[5];

Se puede declarar y crear el arreglo:• Declarar y crear un arreglo vacio.

String [ ] días_Semana=new String [7];

• O también: declarar y crear un arreglo con valores iníciales.int [ ] edades_Estudiantes={15,20,23,18};

Errores.1. Crear arreglos estáticos en tiempo de compilación.

int [4]edades;

2. Asignar valor a un arreglo sin haber determinado su tamaño.int [ ] edades;edades [0]=15;

Principales Operaciones1. Lectura

Saber el contenido o el valor del arreglo de una determinada posición.Ejemplo.

int [ ] edades={15,18,20,25};Sintaxis: Nombre_Arreglo[subindice];

edades[3]; retorna el 25 ya que está en la posición 3.

2. Escritura y actualizaciónSintaxis: Nombre_Arreglo[subíndice]=”valor”;

Edades [1]=28; Ejemplo de actualización de la posición 1.

3. Presentación de los elementos arreglos.Se lo hace a través de un recorrido.for(int i<0;i<edades.length;i++){

System.out.println(edades [i]);}

Recuerda: Java utiliza los siguientes api: Vector, Collection, Array que son clases y/o interfaces que permiten almacenar cualquier clase de objetos como elementos y que pueden ser usados independientemente como unidimensionales o multidimensionales.

Page 16: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 16

EJERCICIOS PROPUESTOS

1. Crear un método que rellene un arreglo con los números enteros comprendidos entre 2 y 20.

2. Escriba un método que rellene un arreglo con los números pares comprendidos entre 1 y 40.

3. Escribir un método, que rellene un arreglo con diez números enteros consecutivos a partir de un número pasado como parámetro y haga una copia de ese arreglo en otro.

4. Escribir un método, que permita ingresar por teclado diez elementos en un arreglo, determine la posición del arreglo en la que se encuentra el máximo valor de los elementos ingresados.

2.3 Arreglos Bidimensionales (Matrices)

¿Qué es un arreglo bidimensional?

Un arreglo bidimensional es un conjunto de datos homogéneos finito y ordenado donde se hace referencia a cada elemento por medio de dos índices: renglón (fila) y columna.

Arreglos bidimensionales más conocidos como matrices (mxn), donde m representa a las filas y n a las columnas. También conocidos como arreglos de arreglos, su manipulación es similar a los arreglos unidimensionales sin acceso directo la única variación es que se requiere tantos índices como dimensiones se tengan.

Para calcular el número de elementos que están en la Matriz se realiza la siguiente operación:ne=n elementos1* n elementos2*… n elementos n.ne=m*nne=3*2ne=6.

Representación de una matriz

MATRIZ COLUMNAS

FILAS

0 1 2 .. N0 P(0,0) P(0,1) P(0,2) …p(0,N-1)

1 P(1,0) P(1,1) P(1,2) …p(1,N-1)

2 P(2,0) P(2,1) P(2,2) …p(2,N-1)

Analiza:Se requiere representar el número de accidentes mensual por región del Ecuador ¿Cómo podríamos resolver este problema?.... Piensa en varias soluciones, comenta con tus compañeros y con tu profesora…..!!!

Analiza:Se requiere representar el número de accidentes mensual por región del Ecuador ¿Cómo podríamos resolver este problema?.... Piensa en varias soluciones, comenta con tus compañeros y con tu profesora…..!!!

Page 17: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 17

…M P(M,0) P(M,1) P(M,2) …p(M-A,N-1)

Manejos de Arreglos Bidimensionales (Matrices)

Declaración:

<Tipo/Clase> [ ][ ]identificador;double [ ][ ]x;

Creación:

1. Un arreglo bidimensional vacio:double [ ][ ]x=new double[3][2];

2. Con valores inicialesdouble [ ][ ]x={{1.0,2.0},{6.0,5.0},{10.0,8.0}};

Operaciones Básicas

1. Lectura: Obtener un elemento contenido en la matriz: double r = x [1][1]=5;

2. Modificación: Actualizar al elemento:x [2][0]=4.0;

3. Presentación: Utilizar un ciclo repetitivo que recorre las filas(i); y otro ciclo anidado que recorre a las columnas(j).

for(int i=0; i<n;i++){for(int j=0;j<n;j++){

System.out.println(x[i][j]); }}

Page 18: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 18

EJERCICIOS PROPUESTOS

Implementar la clase MatrizMatriz

+ n: entero //dimensión de la matriz- x[ ][ ]:doublé // array bidimensional

//constructores+ Matriz(n: entero) + Matriz(x [ ][ ]double)//métodos de la clase Matriz+ suma(a: Matriz,b Matriz): Matriz+ resta(a: Matriz,b Matriz): Matriz+ multiplicacion(a: Matriz,b Matriz): Matriz+ productoEscalar(double,a: Matriz): Matriz+ transpuesta(a: Matriz): Matriz+ sumaDiagonal(): double+sumElemSobDiagonal():double+sumElemBajoDiagonal():double+triBaseSup(Matriz a):double+triBaseInf(Matriz a):double+triBaseIzq(Matriz a):double+triBaseDer(Matriz a):double+triVerticeSup(Matriz a):double+triVerticeInf(Matriz a):double+triVerticeIzq(Matriz a):double+triVerticeDer(Matriz a):double+Rombo(Matriz a):double+Arbol(Matriz a):double+Reloj(Matriz a):double

IMPLEMENTACION DE LA CLASE MATRIZpublic class Matriz {        /** Miembros dato */    public int n;      //dimension    private double[][] x; //Array bidimensional    //Constructores    public Matriz(int n) {        this.n=n;        x=new double[n][n];        for(int i=0; i<n; i++){            for(int j=0; j<n; j++){                x[i][j]=0.0;            }        }    }    public Matriz(double[][] x) {        this.x=x;        n=x.length;   }    //Para mostrar los datos redefinimos la funcion toString    //de la Clase base Object de la cual deriva implicitamente Matriz    public String toString(){        String texto="\n";        for(int i=0; i<n; i++){

Page 19: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 19

            for(int j=0; j<n; j++){                texto+="\t "+(double)Math.round(1000*x[i][j])/100;            }            texto+="\n";        }        return texto;  } 2.4 Conjuntos

Es una colección de elementos del mismo tipo cuyo orden y cantidad de repeticiones es observada.Entre sus principales características tenemos: Es un contenedor de objetos distintos No hay elementos duplicados En la implementación de la estructura conjunto el ordenamiento juega un papel

muy importante

TDA CONJUNTOSElementos: Puede ser cualquier tipo de objetos (elementos diferentes).Estructura: Tiene una estructura lineal entre los objetos del conjunto.Dominio: Son todos los datos posibles a guardar dentro del rango definido por el usuario en relación con el tipo de aplicación de la estructura.OPERACIONES:- UNION : A∪B= { x∈A o x∈B }Utilidad: Que se reemplaza en A con la unión A y B, esto es ejecutar A← A∪B . O se puede crear un

nuevo conjunto C.Datos de Entrada: Dos conjuntos { }A, { }B.Datos de Salida: El conjunto {}A modificado o también puede ser un nuevo conjunto {}C.Precondiciones: Que el conjunto {}A, y {}B existan.Postcondiciones: El conjunto {}A o el {}C contiene los elementos de la unión

- INTERSECCION : A∩B= {x∈A y x∈B }Utilidad: Se reemplazará en {}A con la intersección del conjunto A y B, esto es ejecutar A← A∩B . O se

puede crear un nuevo conjunto C.Datos de Entrada: Dos conjuntos { }A, { }B.Datos de Salida: El conjunto {}A modificado o también puede ser un nuevo conjunto {}C.Precondiciones: Que el conjunto {}A, y {}B existan.Postcondiciones: El conjunto {}A o el {}C contiene los elementos de la intersecsión.

- DIFERENCIA: A−B= {x∈A y x∉B }Utilidad: Reemplaza en A con la diferencia A y B, esto es ejecutar A← A−B . O se puede crear un nuevo

conjunto C.Datos de Entrada: Dos conjuntos { }A, { }B.Datos de Salida: El conjunto {}A modificado o también puede ser un nuevo conjunto {}C.Precondiciones: Que el conjunto {}A, y {}B existan.Postcondiciones: El conjunto {}A o el {}C contiene los elementos de la diferencia del conjunto {}A, y {}B.

En algunos lenguajes de programación éstas operaciones se realizan sobre el primer conjunto o sea el conjunto A ó se

Analiza:¿Cómo sería el proceso que se aplican los motores de búsqueda de Información en Internet?Piensa en varias soluciones, comenta con tus compañeros y con tu profesora…..!!!

Analiza:¿Cómo sería el proceso que se aplican los motores de búsqueda de Información en Internet?Piensa en varias soluciones, comenta con tus compañeros y con tu profesora…..!!!

Page 20: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 20

definir a éstas operaciones sin alterar al conjunto A, devolviendo en un nuevo conjunto que podría ser el conjunto C.

Manipulación de conjuntos en Java

En el api de Java encontramos, el paquete Java.util que incluye la interfaz SET, que nos permite manipular conjuntos de elementos y tiene como características las siguientes:

• Un conjunto no puede contener elementos duplicados• Incluye métodos parecidos a los definidos en el TDA mencionado anteriormente.

A continuación se muestra:

Correspondencia entre TDA CONJUNTO y la Interfaz Java.util.Set

TDA CONJUNTO Interfaz Java.util.SetUnión addAll (collection c):booleanIntersección retainAll(collection c):booleanDiferencia removeAll(collection c):boolean

Ejemplo de representación de la operaciones básicas(inserción y eliminación); operaciones con subconjuntos y las operaciones entre conjuntos(Unión, Intersección

y Diferencia) de la Estructura Conjunto en Java

MODELADOConjunto

+a: SortedSet

//Constructor+Conjunto()+getA():SortedSet+setA(a:SortedSet):void//metodos de Conjunto+inserta(e:Object):void+elimina(e:Object):void+subconjuntosup(e:Object):SortedSet+subconjuntoinf(e:Object):SortedSet+subconjuntoentre(Object ei, Object ef):SortedSet+union(SortedSet a, SortedSet b):SortedSet+interseccion(SortedSet a, SortedSet b):SortedSet+diferencia(SortedSet a, SortedSet b):SortedSet

IMPLEMENTACION DE CONJUNTO import java.util.*;public class Conjunto {    public SortedSet a;    public Conjunto() {        a= new TreeSet();    }    public SortedSet getA() {        return a;    }    public void setA(SortedSet a) {        this.a = a;    }

Page 21: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 21

    public void inserta(Object e){        if(a.add(e)==false){            System.out.println("Elemento :"+ e +" repetido!!..No se pudo insertar");        }    }    public void elimina(Object e){        if(a.remove(e)){            System.out.println("Elemento  : "+e+" : ha sido eliminado");        }else{            System.out.println("No existe el elemento a eliminar");        }    }    public SortedSet subconjuntosup(Object e){        SortedSet b=new TreeSet();        b=a.tailSet(e);        return b;

    }    public SortedSet subconjuntoinf(Object e){        SortedSet b=new TreeSet();        b=a.headSet(e);        return b;    }    public SortedSet subconjuntoentre(Object ei, Object ef){        SortedSet b=new TreeSet();        b=a.subSet(ei, ef);        return b;    }    public SortedSet union(SortedSet a, SortedSet b){        a.addAll(b);        return a;    }    public SortedSet interseccion(SortedSet a, SortedSet b){        a.retainAll(b);        return a;    }    public SortedSet diferencia(SortedSet a, SortedSet b){        a.removeAll(b);        return a;    }} 2.5 Archivos o ficherosLa estructura de datos tipo archivo (ficheros) es la única estructura de datos que se almacena en memoria secundaria o externa (disco o cinta). Un archivo de datos es una estructura constituida simplemente por colecciones de datos que se pueden guardar, para uso posterior mediante la ejecución de programas adecuados. Otra característica importante de los archivos es que permite almacenar gran cantidad de información.

Esta colección de datos sirve para la entrada y salida a la computadora y se maneja con un programa en contraste con archivos y registros, el tamaño de esta colección no es fija y está limitada solo por la cantidad de memoria secundaria (disco o cinta) disponible. Es decir, los archivos son dinámicos, esto es que se pueden hacer archivos de datos más grandes o más pequeños según sean las necesidades.

Page 22: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 22

Los archivos no están limitados por la memoria donde están contenidas las estructuras. Cada archivo se puede manipular por un identificador.

Un archivo está compuesto por un conjunto de registros que es una colección de los elementos de información sobre una entidad particular, los diferentes elementos se conocen como campo que pueden guardar información diferente, y estos pueden a su vez contener subcampos los que están compuestos de caracteres.

Métodos de acceso a un archivoUn método de acceso, no es más que la forma como recuperar la información del archivo, a veces se pude procesar dato por dato, en otras veces se podría acceder rápidamente a un dato sin recuperar los datos anteriores.

Existen dos métodos para acceder a un archivo de datos: acceso secuencial y acceso aleatorio.

• Acceso SecuencialExige el tratamiento elemento a elemento es necesario una exploración secuencial comenzando desde el primer elemento hasta llegar al elemento buscado.

• Acceso Aleatorio o DirectoPermite procesar o acceder a determinado elemento mediante una dirección en el soporte de almacenamiento.Representación Grafica

Representación de la Estructura Archivo

1. SECUENCIAL: Entre sus principales características tenemos más sencillos de implementar, no es eficiente cuando la cantidad de datos a almacenar es grande, deben actualizarse en forma periódica para reflejar los cambios dados en la información almacenada. Ejemplo: archivo que almacena los datos de los clientes de un banco, al obtener dinero de un cajero automático.

a cb

puntero

elementosAcceso a un archivo

secuencial

Acceso directo

Índice (posición)

Acceso a un archivo directo

Δ

R1 R2 R3 R….

RnEOF

Page 23: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 23

2. INDEXADOS: Entre sus principales características tenemos: que este tipo de archivos requiere que se conozca la dirección donde se encuentra el dato a buscar, se compone de un archivo de datos(secuencial) y un archivo de índices(guarda las llaves o clave del archivo secuencial, o sea la dirección del dato correspondiente en disco).

Tipos de archivos

Texto: Solo permiten acceso secuencial y su unidad constitutiva es el carácter.

Acceso directo: Se puede acceder secuencial o aleatoriamente y está compuesto por bytes.

Con tipo o Serializables: Se puede acceder secuencialmente, y solo trabaja con objetos.

Implementación de un archivo tipo texto.MODELADO:

ArchivoTexto

+ f : File+bw : BufferedWriter+br: BufferedReader

//ConstructorArchivoTexto(dir:String)ArchivoTexto(dir:String, nom:String)//Métodos del Archivo+escribir(dato:String):void+leer():void+info():void+lista():void+listaFiltro():void

Filtro implements FilenameFilter

+extension:String

//Constructor+Filtro(extension:String)//Redefinición método accept

Archivo de Índices

Llave Dirección10008 00110209 00310321 006

Número de cuenta(llave)

Archivo de datos (Secuencial)001 10008 María del Cisne

Calderón ….

002003 10209 María Gabriela

Gonzaga…

004005006 10321 María José Salinas …007008…300301…N

Page 24: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 24

+accept(dir:File, name String ):boolean

CLASE ARCHIVOTEXTOimport java.io.*;public class ArchivoTexto {    public File f=null;    public BufferedWriter bw=null;    public BufferedReader br=null;

    public ArchivoTexto(){    }

    public File getF() {        return f;    }

    public void setF(File f) {        this.f = f;    }    public boolean verifica(String dir, String nom){        //Comprobar si hay un archivo con ese nombre en el directorio        File fa=new File(dir);        File[] lf=fa.listFiles();        boolean existe=false;        for(int i=0; i<lf.length; i++){            if(lf[i].getName().equalsIgnoreCase(nom)){                fa=lf[i];                existe=true;                setF(fa);                break;            }        }        return existe;    }    public void abrir(String da,String na){        this.f = new File(da,na);    }    public void escribir(String dato)throws IOException{       //*************ESCRIBIR EN EL ARCHIVO*************************        //Recuerda que la filosofia de acceso a la lectura y escritura a los archivos,        //siempre es la misma. Buffer, que envuelve a Reader, que a su vez envuelve        //al archivo (o stream).        //Para escribir utilizamos en el metodo .write() del buffer        //int pos=(int)f.length();        if(f.exists()){            bw = new BufferedWriter(new FileWriter(getF(),true));        }else{            bw = new BufferedWriter(new FileWriter(getF()));        }        bw.write(dato+"\n");        bw.close();    }    public void leer()throws IOException{        //*************LEER EL ARCHIVO**********************************        //Manejar el buffer Reader es muy sencillo ya que simplemente deberemos de

Page 25: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 25

        //ejecutar lecturas por linea.         System.out.println("El contenido del Archivo es:");         br = new BufferedReader(new FileReader(getF()));         String texline=br.readLine();         while(texline!=null){                System.out.println(texline);                texline = br.readLine();         }         br.close();   }   public void info(){        if( f.exists() ){            System.out.print( "El Archivo existente " );            System.out.println( "Nombre: "+f.getName() );            System.out.println( "Camino: "+f.getPath() );            System.out.println("Directorio padre:"+f.getParent());            System.out.print( (f.canRead() ? "  se puede Leer" : "") );            System.out.println( (f.canWrite() ? " y se puede Escribir" : "") );            System.out.println( "La longitud del Archivo es: "+ f.length() +"Bytes" );        }else{            System.out.println( "El Archivo no existe." );        }

   }   public void lista(){       System.out.println(" ******* lista de los archivos de este directorio *******");        File fa=new File("/home/usuario/Documentos");        String[] lf=fa.list();        for(int i=0; i<lf.length; i++){            System.out.println(lf[i]);        }   }   public void listaFiltro(){       System.out.println("***** lista de los archivos de este directorio con filtro ***\n");        File fa=new File("/media/RESPALDO/");        String[] lf=fa.list(new Filtro(".odt"));        for(int i=0; i<lf.length; i++){            System.out.println(lf[i]);        }   }}CLASE FILTROimport java.io.*;/** * * @author Ing. Mire */public class Filtro implements FilenameFilter{    String extension;    Filtro(String extension){        this.extension=extension;    }    public boolean accept(File dir, String name){        return name.endsWith(extension);    }}

Page 26: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 26

Ejemplo de manejo de un archivo tipo de acceso Aleatorio

MODELADO:Log

+Rf : RandomAccessFile

//Constructor+Log(nom: String, t: String)//Métodos Archivo Aleatorio +escribirfinal(dato:String):void+escribirposicion(dato:String, pos: int).void+leer():void+cerrar():void+info():void

import java.io.*;public class ArchivoAleatorio {

    public RandomAccessFile Rf;    /** Creates a new instance of ArchivoAleatorio */    public ArchivoAleatorio(String nom, String t) throws IOException{        Rf = new RandomAccessFile(nom, t);    }    public void escribirfinal(String dato){        try{             // Nos vamos al final del fichero, Incorporamos la cadena al fichero              Rf.seek( Rf.length());            Rf.writeBytes(dato);         }catch (Exception  e){            System.out.print("Ha ocurrido un error....El directorio no existe");         }    }    public void escribirposicion(String dato, int pos){        try{                Rf.seek(pos);            Rf.writeBytes(dato);        }catch (Exception e){            System.out.println("Fichero no existe.");        }    }    public void leer(){            //  Presentamos los datos del archivo, mediante el acceso secuencial        try{            Rf.seek(0);            String linea=Rf.readLine();            while(linea!=null){                System.out.println(linea);                linea = Rf.readLine();            }        }catch (Exception e){            System.out.println("Fichero no existe");        }

    }    public void cerrar() throws IOException{

Page 27: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 27

        Rf.close();    }    public void info()throws IOException{        System.out.println("El puntero esta en la posicion :"+Rf.getFilePointer());        System.out.println("El tamaño del archivo es: " + Rf.length());        System.out.println("El puntero esta en la posicion :"+Rf.getFilePointer());    }}

Ejemplo de manejo de un archivos Serializables

MODELADO

Clase DatosDatos

#nombre:String#telefono: String#direccion:String+Datos(String n, String t, String d);+getNombre():String+getTelefono():String+getDireccion():String+to String(): String

Clase de LecturaContadoInput

-f:FileInputStream-fi:ObjectInputStream+abrir():void+cerrar():void+leer():Datos

Clase de EscrituraContactoOutput

-f:FileOutputStream-sf:ObjectOutputStream+abrir():void+cerrar():void+escribir(Datos d):void

IMPLEMENTACIÓN DE ARCHIVOS SERIALIZABLES

CLASE DATOSpublic class Datos implements java.io.Serializable {    protected String nombre;    protected String telefono;    protected String direccion;

    /** Creates a new instance of Datos */    public Datos(String n, String t, String d){        nombre = n;        telefono = t;        direccion = d;    }    public String getNombre() {

Page 28: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 28

        return( nombre );        }

    public String getTelefono() {        return( telefono );        }

    public String getDireccion() {        return( direccion );        }

    @Override   public String toString(){        String texto="\n";        texto ="\t"+nombre+"\t"+telefono+"\t"+direccion + "\n";        return texto;     } }

CLASE ESCRITURA

import java.io.*;

public class Escritura {    public FileOutputStream f;    public ObjectOutputStream sf;        /** Creates a new instance of Escritura */    public Escritura() {    }    //Abrir el fichero;    public void abrir(File a) throws IOException{            f= new FileOutputStream(a,true);            sf = new ObjectOutputStream(f);     }    //Escribir en el fichero    public void escribir(Datos d) throws IOException {        if (sf != null)            sf.writeObject(d);    }    //Cerrar el fichero    public void cerrar() throws IOException{        if (sf != null)            sf.close();    }}

CLASE LECTURA

import java.io.*;public class Lectura { /** Creates a new instance of Lectura */ private FileInputStream f; private ObjectInputStream fi; public Lectura() { } public void abrir(File a) throws IOException { f = new FileInputStream(a);

Page 29: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 29

fi = new ObjectInputStream(f); } public Datos leer() throws IOException, ClassNotFoundException{ Datos da = null; if (fi!= null){ try{ da = (Datos) fi.readObject(); }catch (EOFException eof){ System.out.print("Fin de archivo"); } } return da; } public void cerrar() throws IOException{ if (fi != null){ fi.close(); } }}

CLASE EJECUTORAimport java.io.*;public class EjecutorArchivoSerializable {    public static void main( String argv[] )throws IOException  {        File a=new File("/home/usuario/Documentos/agenda.odt");        Escritura bw = new Escritura();        Lectura br = new Lectura();        bw.abrir(a);        bw.escribir(new Datos("Marco","2546788","Las Pitas"));        bw.escribir(new Datos("Andres","2545609","Argelia"));        bw.cerrar();        br.abrir(a);        try{            while(br!=null){                System.out.print(br.leer());            }        }catch (Exception e){               System.out.println("No hay mas objetos");        }        br.cerrar();    }}

EJERCICIOS PROPUESTOS

1. Generar las letras del abecedario mayúsculas y minúsculas combinadas, guardar en un archivo de texto o aleatorio y presentarlas de la siguente manera:

AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXx

YyZz2. Generar la tabla de sumar del 1 al 12 y guardar en un archivo de texto o

aleatorio.TABLA DEL1 1+1=2

Page 30: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 30

1+2=31+3=41+4=51+5=61+6=71+7=81+8=91+9=101+10=111+11=121+12=13

TABLA DEL2

2+1=32+2=42+3=52+4=62+5=72+6=82+7=92+8=102+9=112+10=122+11=13

2+12=14 … y asi sucesivamente...

3. Generar los números del fatorial hasta el 12 y guardar en un archivo de texto o aleatorio.

1! =1*=12! =1*2*=23! =1*2*3*=64! =1*2*3*4*=245! =1*2*3*4*5*=1206! =1*2*3*4*5*6*=720

y asi sucesivamente...

Page 31: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 31

3 ESTRUCTURA LISTA 3.1 Descripción Lógica de la Estructura ListaUna lista, es una colección de elementos homogéneos, entre los elementos existe una relación lineal, en donde cada elemento indica la dirección donde se encuentra el siguiente elemento de la lista.

Representación:Una lista se puede representar de dos formas:

Estática: su tamaño se limita en tiempo de compilación Ej.: arreglos Dinámica: su tamaño puede crecer indefinidamente en tiempo de ejecución Ej.:

listas enlazadas simples, listas enlazadas dobles, listas circulares, pilas y colas.

Características En cada elemento o nodo de la lista a excepción del primero, tiene un único

predecesor se debe indicar donde se encuentra el siguiente elemento. Cada elemento de la lista, a excepción del último tiene un único sucesor. Las listas son flexibles y permiten cambios en la implementación.

Partes de un nodoCampo dato o info

Campo de enlace

Campo dato o info: contiene uno o varios datos y/o objetos Campo de enlace: es la referencia hacia el otro nodo de la lista.

Representación de la estructura en memoria:

Por lo general un nodo de una lista se abstrae en una clase.Ejemplo:

Class Nodo{ int dato; Nodo siguiente; public Nodo (Nodo sig){ Siguiente = sig; } // métodos de la clase} // fin de la clase Nodo

Page 32: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 32

3.2 OperacionesEn una lista se pueden efectuar las siguientes operaciones:

Insertar: Agregar un nuevo nodo a la lista Eliminar: Quitar un nodo de la lista Buscar: Permite encontrar un nodo dentro de la lista Modificar: Actualiza la información de un determinado nodo dentro de la lista

3.3 Tipos de listas 3.3.1 Listas Simplemente Enlazadas

Es una colección de elementos homogéneos cuya relación lineal es determinada por la posición del elemento en la lista.

Una lista simplemente enlazada se caracteriza por lo siguiente:

En cada nodo existe un solo enlace o referencia hacia el siguiente nodo. Solo el último nodo de la lista contendrá una referencia nula o apuntara a null. Esta dada en un solo sentido.

Java inicializa los campos de referencias de un objeto a null durante la construcción del objeto, no es necesario asignar explícitamente null a un campo de enlace.Pero sin embargo no olvide estas asignaciones de null en su código fuente, su ausencia reduce la claridad del código.

TDA:LISTA ENLAZADA SIMPLEElementos: los elementos de una lista simplemente enlazada, son conocidos como nodos, que almacenan

datos simples o estructurados.Estructura: Lineal entre los nodos que forman la lista enlazada simple, cada nodo tiene un único sucesor y

predecesorDominio: si la lista no está vacía el rango serán los elementos que tendrán las posiciones 0,1,2,3…N donde N

es la cantidad de elementos de la lista.OPERACIONES:- INSERTAR-INICIO Utilidad: añadir un elemento al inicio de la lista L

Analiza:Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista Simplemente Enlazada, comenta con tus compañeros y con tu profesora…..!!!

Analiza:Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista Simplemente Enlazada, comenta con tus compañeros y con tu profesora…..!!!

Page 33: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 33

Datos de entrada: la lista L y el nuevo elemento.Datos de salida: la lista L con el nuevo elemento al inicio.Precondición: NingunaPostcondicion: La lista L contiene un elemento nuevo al inicio.

- INSERTAR-FIN

Utilidad: añadir un elemento al final de la lista LDatos de entrada: la lista L y el nuevo elemento.Datos de salida: la lista L con el nuevo elemento al final.Precondición: NingunaPostcondicion: La lista L contiene un elemento nuevo al final.

- INSERTAR-ENTRE-NODOS

Utilidad: añadir un nuevo nodo en un orden especifico dentro de la lista L Datos de entrada: la lista L ,el nuevo elemento y el nodo predecesorDatos de salida: la lista L con el nuevo elemento insertado en el lugar que le corresponde.Precondición: La lista contenga nodosPostcondición: La lista L contiene al elemento nuevo en el orden que le corresponde.

- ELIMINAR-INICIO

Utilidad: quitar un elemento del inicio de la lista LDatos de entrada: la lista L.Datos de salida: la lista L con un nodo menos y el valor del nodo eliminadoPrecondición: la lista L no este vacíaPostcondicion: La lista con un nodo menos (el del inicio)

- ELIMINAR-FIN

Utilidad: quitar un elemento del final de la lista LDatos de entrada: la lista L.Datos de salida: la lista L con un nodo menos y el valor del nodo eliminadoPrecondición: la lista L no este vacíaPostcondicion: La lista con un nodo menos (el del final)

- ELIMINAR- ENTRE-NODOS

Utilidad: quitar un nodo de un orden específico de la listaDatos de entrada: la lista L, y el elemento a eliminarDatos de salida: la lista L con un elemento menosPrecondición: la lista L no esté vacía y que contenga el nodo a eliminarPostcondición: La lista L contiene un elemento menos y corresponde al que se elimino

- BUSCAR-NODO

Utilidad: recorrer la lista L, hasta encontrar un determinado nodo dentro de la lista LDatos de entrada: la lista L ,el elemento a buscarDatos de salida: verdadero si se ha encontrado el nodo caso contrario falsoPrecondición: la lista no esté vacíaPostcondición: Ninguna- MODIFICAR-NODO

Utilidad: modificar un elemento de la lista LDatos de entrada: la lista L ,el elemento a modificar y el nuevo valor para modificar el elemento de la lista L.Datos de salida: NingunaPrecondición: la lista no esté vacíaPostcondición: La lista L con un elemento modificado.

Nivel físico: Implementación de operaciones de Listas Enlazadas Simples

CASOS PARA LA INSERCIÓN DE NODOS:1.- Cuando la lista enlazada simple no existe

Page 34: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 34

2.- Cuando el nodo se debe insertar antes del primer nodo3.- Cuando el nodo se debe insertar después del último nodo4.- Cuando el nodo se debe insertar entre nodos

PASOS PARA LA SOLUCIÓN

Caso 1: Cuando la lista enlazada simple no existe 1.- Leer (valor)2.- Se crea un nodo y se asigna su referencia a top3.- Inicializar su campo de no enlace

Caso 2: Cuando el nodo se debe insertar antes de primero 1.- Leer (valor)2.- Crear un nuevo nodo temporal3.- Inicilizar el campo de no enlace del nodo temporal 4.-Asignar la referencia de inicio de la lista (top),al campo de enlace del nodo temporal5.-Asignar la referencia del nodo temporal al inicio de la lista

Caso 3: Cuando el nodo a insertarse después del último nodo 1.- Leer (valor)2.-Crear un nodo temporal 3.- Inicializar el campo de no enlace del nodo temporal4.- Declarar una variable de referencia aux (auxiliar)5.- Recorrer la lista hasta el final6.-Asignar la referencia del nodo temporal al campo de enlace del último nodo de la

lista

Caso 4 : cuando el nodo debe insertarse entre nodos 1.- Leer(valor)2.- Leer (valor) nodo predecesor3.-Crear un nodo temporal4.- Inicializar el campo de no enlace del nodo temporal5.- Declarar una variable de referencia aux(auxiliar)6.- Recorrer la lista hasta encontrar el nodo predecesor7.-Asignar al campo de enlace del nodo temporal la referencia del nodo sucesor8.- Asignar la referencia del nodo temporal al campo de enlace del nodo predecesor

CASOS PARA LA ELIMINACIÓN DE NODOS:1.- Borrar el primer nodo2.- Borrar cualquier nodo que no sea el primero

PASOS PARA LA SOLUCIÓN

Caso1: borrar el primer nodo 1.- Asignar el enlace del campo siguiente del nodo referenciado por top a top.

Caso 2 : borrar cualquier nodo que no sea el primero 1.- Leer(valor)2.- Localizar el nodo predecesor al nodo que se desea eliminar

Page 35: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 35

3.- Asignar al campo de enlace del nodo predecesor la referencia del nodo sucesor al que se desea eliminar. Si el nodo a eliminar es el último asignar null al campo de enlace del nodo predecesor.

BUSCAR UN NODO1.- Leer (valor)2.- Recorrer la lista hasta encontrar el valor

MODELADO:

ListaSimple- dato: Object // campo dato- sig:ListaSimple // campo de enlace al siguiente nodo- top: ListaSimple // apuntador de cabecera de la lista simple

+ ListaSimple( )+ getDato ( ) : Object+getSig ( ) : ListaSimple+setDato( dato: Object): void+setSig(sig.ListaSimple):void+esVacia( ):Boolean//Inserción de Nodos+insertaVacia(d:Object):void //Caso 1+insertaInicio(d:Object):void //Caso 2+insertaFinal(d:Object):void //Caso 3+entreNodos(np: Object, d:Object):void // Caso 4//Eliminación de Nodos+eliminaInicio( ): void // Caso 1+eliminaNodo( d:Object): void //Caso 2 y 3//Búsqueda+buscarNodo( ):boolean//Modificar nodo+modificaNodo(d:Object, nd:Object):void//Varios+presenta( ):void+cuentaNodos( ):int+cuentaRepetidos(d:Object):int

IMPLEMENTACIÓN EN JAVApublic class ListaSimple {    private Object dato;    private ListaSimple sig;    private ListaSimple top;    public ListaSimple() {        setDato(null);        setSig(null);    }    public Object getDato() {        return dato;    }    public void setDato(Object dato) {        this.dato = dato;    }    public ListaSimple getSig() {        return sig;    }

Page 36: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 36

    public void setSig(ListaSimple sig) {        this.sig = sig;    }    public boolean esVacia() {        if (top == null) {            return true;        } else {            return false;        }    }    //Insercion de Nodos    public void insertaVacia(Object d) {        if (esVacia()) {            top = new ListaSimple();            top.setDato(d);            System.out.println("El nodo insertado es el primero");        } else {            System.out.println("No se ejecuto la operacion, la lista ya contine elementos.");        }    }    public void insertarInicio(Object d) {        if (!esVacia()) {            ListaSimple temp = new ListaSimple();            temp.setDato(d);            temp.setSig(top);            top = temp;        } else {            System.out.println("No puede insertarse al inicio... La lista no contienen nodos");            insertaVacia(d);        }    }    public void insertaFinal(Object d) {        if (!esVacia()) {            ListaSimple temp = new ListaSimple();            temp.setDato(d);            ListaSimple aux;            aux = top;            while (aux.getSig() != null) {                aux = aux.getSig();            }            aux.setSig(temp);        } else {            System.out.println("No se puede insertar al final...La lista esta vacia");        }    }    public void entreNodos(Object np, Object d) {        if (!esVacia()) {            ListaSimple aux;            aux = top;            while ((aux.getDato().equals(np) == false) && (aux.getSig() != null)) {                aux = aux.getSig();            }            if (aux.getDato().equals(np)) {                ListaSimple temp = new ListaSimple();                temp.setDato(d);                temp.setSig(aux.getSig());

Page 37: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 37

                aux.setSig(temp);            } else {                System.out.println("No se puede insertar...Nodo predecesor no existe");            }        } else {            System.out.println("No se puede insertar...La lista esta vacia");        }

    }

EJERCICIOS PROPUESTOS

Implementar los métodos correspondientes a la Lista Simple: eliminación de nodos, búsqueda, modificación y varios.

En java también existe un Api propio para trabajar con listas simples, con la clase ArrayList … INVESTIGA..!!!

3.3.2 Lista Circulares

Una lista circular es aquella en donde la referencia siguiente del último nodo en vez de ser null apunta al primer nodo de la lista. El concepto se aplica tanto a listas de enlace simple como doblemente enlazadas. Se obtiene al considerar el primer nodo de la lista es el sucesor del último nodo.

Se utilizan con frecuencia en procesamiento repetitivo de nodos en un orden específico.

Características

No podemos hablar de primer y último nodo, Para su implementación es necesario utilizar un apuntador general a la lista No existen direcciones nulas, excepto cuando la lista está vacía Si la lista contiene un solo nodo, el campo de enlace entonces apuntara a si

mismo Es posible llegar a cualquier nodo a partir de cualquier posición donde se

encuentre apuntando a la variable de referencia llamada lista

Representación

Analiza:Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista Circular, comenta con tus compañeros y con tu profesora…..!!!

aba|

Analiza:Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista Circular, comenta con tus compañeros y con tu profesora…..!!!

aba|

Page 38: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 38

Nivel físico: Implementación de operaciones de Listas Circulares

MODELADO:

ListaCircular- sig: ListaCircular- dato: Object+ lista: ListaCircular+ ListaCircular ( )+ ListaCircular(d: Object)+getDato( ):Object+ getSig( ): ListaCircular+setDato (d: Object):void+setSig(nodo: ListaCircular):void+insert(d:Object):void+delete(d:Oject): void+search(d:Object):void+update(d:Object, nd:Object):void+printNodos( ): void

Algoritmo para Insertar Nodos- Leer (valor)- Crear un nodo temporal- Fijar el dato- Si la lista está vacía es el primero a insertarse, asignar la referencia del nuevo

nodo a lista sino insertar el nuevo nodo a continuación de lista.- Enlazar el nuevo nodo a lista- Asignar la referencia del nuevo nodo a lista

Algoritmo para eliminar Nodos- Crear una variable auxiliar- Asignar la referencia de lista a la variable auxiliar- Recorrer la lista hasta encontrar el dato a eliminar y lista sea diferente de auxiliar- Si el dato existe verificar que si el último asignar null a lista sino fijar en auxiliar

la referencia del sucesor del nodo a eliminar.

Algoritmo para imprimir Nodos- Crear una variable auxiliar- Asignar a la variable auxiliar la referencia del inicio de lista - Recorrer la lista mientras auxiliar sea diferente de lista- En el recorrido presentar el valor de cada nodo visitado

IMPLEMENTACION DE LA LISTA CIRCULAR public class ListaCircular {

Page 39: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 39

    private ListaCircular sig;    private Object dato;    public ListaCircular lista=null;     // Constructor Basico    public ListaCircular(Object d) {        // Fijamos el dato        lista=new ListaCircular();        lista.setDato(d);        // Reseteamos el apuntador        lista.setSig(lista);    }    public ListaCircular(){        setSig(null);        setDato(null);    }    // Acceso a los elementos de un nodo    public ListaCircular getSig() {        return( sig );    }    public Object getDato() {        return(dato);    }    public void setSig(ListaCircular nodo ) {        sig = nodo;    }    public void setDato( Object d) {        dato = d;    }    public void insert(Object d) {            ListaCircular temp=new ListaCircular();            temp.setDato(d);            if(lista==null){                lista=temp;                lista.setSig(lista);            }else{                temp.setSig(lista.getSig());                lista.setSig(temp);                lista=temp;            }            System.out.println("El dato ha sido insertado correctamente.");    }    public void delete(Object d){      if(lista!=null){        ListaCircular aux;        aux=lista;        do{                aux=aux.getSig();         }while((aux.getSig().getDato()!= d)&&(lista!=aux));        boolean existe = false;        if(aux.getSig().getDato()==d){            existe = true;        }        if(existe==true){           if(aux.getSig()!=lista){               //Varios nodos                aux.setSig(aux.getSig().getSig());

Page 40: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 40

           }else{                if(aux.getSig() == aux){                    //Existe un solo nodo                    lista=null;                }else{                    //El nodo a eliminar esta referenciado por lista                    lista=aux;                    aux.setSig(aux.getSig().getSig());                }            }        }else{            System.out.println("Nodo a eliminar no existe \n");        }      }else{          System.out.println("No se puede eliminar la lista esta vacia \n");      }    }    public boolean search(Object d){    boolean existe = false;      if(lista!=null){        ListaCircular aux;        aux=lista;        do{                aux=aux.getSig();         }while((aux.getSig().getDato()!= d)&&(lista!=aux));        if(aux.getSig().getDato()==d){            existe = true;        }     }     return existe;    }   public void update(Object d, Object nd){    if(lista!=null){        ListaCircular aux;        aux=lista;        do{                aux=aux.getSig();        }while((aux.getSig().getDato()!= d)&&(lista!=aux));        if(aux.getSig().getDato()==d){            aux.getSig().setDato(nd);            System.out.println("El dato ha sido actualizado con exito..");        }else{            System.out.println("El dato no existe... La modificacion no ha tenido exito");        }    }else{        System.out.println("La lista esta vacia...!!!");    }    }    public void print(){        ListaCircular aux;        aux=lista;        if(aux!=null){            do{                System.out.println("["+aux.getDato()+"]");                aux=aux.getSig();            }while(aux!=lista);

Page 41: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 41

        }else{            System.out.println("La lista esta vacia");        } }    } 3.3.3 Listas Ordenadas.

Usa la estructura diccionario en la que se guarda pares de clave-elemento: la clave (k) y el elemento (e). Para lograr mayor generalidad se permite que las claves y los elementos que se guarden en el diccionario sean cualquier clase de objeto.Ejemplo: El registro de alumnos (k,e); k numero de cedula o identificación y e nombre, dirección, teléfono, calificación.

Tipo de Listas Ordenadas.

1. Diccionario no ordenado o genérico: Se supone que no hay relación de orden entre las claves y solo se usa la prueba de igualdad entre ellas.

2. Diccionarios Ordenados. Existen entre las claves una relación de orden total, además determina el orden relativo de dos claves mediante un comparador.

Representación en Memoria.

TDA: DICCIONARIOElementos: Se guardan como elementos cualquier objeto, como un par ordenado: clave K y elemento e.Estructura: Lineal entre cada artículo del diccionario DDominio: depende de la aplicación OPERACIONES:

- INSERT-ELEMENTO Utilidad: Añadir un articulo con elemento e y clave K en el diccionario D.Datos de Entrada: Clave K,objeto o elemento eDatos de Salida: Diccionario D modificado

- REMOVE- ELEMENTO Utilidad: quitar de D un articulo con clave K y regresar el elemento eliminado, si el artículo no existe en el

diccionario regresar un mensaje “clave no existe”Datos de Entrada: Clave KDatos de Salida: Elemento e, o el mensaje en caso de que no hubo éxito en la operación

- ENCONTRAR- ELEMENTO Utilidad: si D contiene un articulo cuya clave sea igual a K, regresa al elemento de ese artículo y si no u n

Analiza:Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista ordenada, comenta con tus compañeros y con tu profesora…..!!!

Analiza:Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista ordenada, comenta con tus compañeros y con tu profesora…..!!!

Page 42: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 42

mensaje indicando “clave no existe”Datos de Entrada: Clave K del objetoDatos de Salida: Elemento e, caso contrario el mensaje si no existe la clave .

- MODIFICAR- ELEMENTO Utilidad: si D contiene un articulo cuya clave sea igual a K, actualizando al elemento de ese artículo y si no

u n mensaje indicando “clave no existe”Datos de Entrada: Clave K del objetoDatos de Salida: mensaje valor ha sido modificado correctamente, caso contrario el mensaje si no existe la

clave .

Nivel físico: Implementación de operaciones de Listas Ordenadas

MODELADO:

ListaOrdenada- clave: int- valor: String- sig:ListaOrdenada

+ top: ListaOrdenada+ListaOrdenada( )+ListaOrdenada(clave:int, valor:String)+getClave( ): int+getSig( ):ListaOrdenada+getValor( ):String+setClave(clave:int):void+setSig(sig:ListaOrdenada):void+setValor(valor:String):void+esVacia( ):Boolean+insert(clave:int, valor:String):void+delete(clave:int):String+search(clave:int):String+update(clave:int, nd String):void+print( ):void

IMPLEMENTACIÓN LISTAS ORDENADASpublic class ListaOrdenada {    private int clave;    private String valor;    private ListaOrdenada sig;    public ListaOrdenada top=null;    //Constructor    public ListaOrdenada(){        this.setClave(0);        this.setValor(null);        this.setSig(null);    }    public ListaOrdenada(int clave,String valor){        top=new ListaOrdenada();        top.setClave(clave);        top.setValor(valor);        top.setSig(null);    }    public int getClave() {        return clave;    }    public ListaOrdenada getSig() {        return sig;

Page 43: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 43

    }    public String getValor() {        return valor;    }    public void setClave(int clave) {        this.clave = clave;    }    public void setSig(ListaOrdenada sig) {        this.sig = sig;    }    public void setValor(String valor) {        this.valor = valor;    }    public boolean esVacia(){        if (top==null){            return true;        }else{            return false;        }    }    public void insert(int clave,String valor){        if(esVacia()){            top= new ListaOrdenada();            top.setClave(clave);            top.setValor(valor);        }else{            ListaOrdenada aux, aux1;            aux=aux1=top;            boolean existe=false;            while((aux.getSig()!=null)&&(clave>aux.getClave())){                aux1=aux;                aux=aux.getSig();            }            if(aux.getClave()==clave){               existe=true;            }            if(existe ==false){                ListaOrdenada temp=new ListaOrdenada();                temp.setClave(clave);                temp.setValor(valor);                //El nodo a insertar es el nodo cabecera                if((top==aux) && (clave < aux.getClave())){                    temp.setSig(top);                    top=temp;                }else                //El nodo a insertar es mayor al apuntado por aux                    if(clave > aux.getClave()){                        temp.setSig(aux.getSig());                        aux.setSig(temp);                     }else{                            //El nodo a insertar es menor al apuntado por aux                            aux1.setSig(temp);                            temp.setSig(aux);                     }            }else{                System.out.println("No se puede insertar... Clave repetida");

Page 44: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 44

            }        }    }    public String delete(int clave){        ListaOrdenada aux,aux1;        aux1=aux=top;        String dato=null;        while((aux.getSig()!=null) && (clave>aux.getClave())){            aux1=aux;            aux=aux.getSig();        }        boolean existe=false;        if(aux.getClave()==clave){            existe=true;            dato=aux.getValor();        }else{            dato=null;        }        if(existe==true){             if(top == aux){                  top=top.getSig();             }else{                if(aux.getSig() == null){                    aux1.setSig(null);                }else{                    aux1.setSig(aux.getSig());                 }             }        }        return dato;    }    public String search(int clave){        String dato=null;        ListaOrdenada aux;        aux=top;        while((aux.getSig()!=null) && (clave > aux.getClave())){            aux=aux.getSig();        }        if(aux.getClave()==clave){            dato=aux.getValor();        }else{            dato="No existe";        }        return dato;    }    public void update(int clave, String nd){        ListaOrdenada aux;        aux=top;        while((aux.getSig()!=null) && (clave > aux.getClave())){            aux=aux.getSig();        }        if(aux.getClave()==clave){            aux.setValor(nd);        }else{            System.out.println("Clave no existe...No se ha modificado");        }

Page 45: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 45

    }    public void print(){        ListaOrdenada aux;        aux=top;        System.out.print("[");        while(aux!=null){            System.out.print(aux.getClave()+" = "+aux.getValor()+ " ");            aux=aux.getSig();        }        System.out.print("]");    }}

En java también existe un api propio para trabajar con Listas Ordenadas se  trata de la Clase HashTable o HashMap INVESTIGA..!!!

3.3.4 Listas Doblemente Enlazadas

Problemas con las Listas Simples: Restringen el movimiento por los nodos a una sola dirección. No se puede atravesar la lista en dirección opuesta a menos que se utilice

primeramente un algoritmo de inversión, lo que llevará algún tiempo. El borrado de nodos, se complica debido a que no se puede eliminar un nodo

arbitrario sin acceder al predecesor del nodo.Una lista doblemente enlazada, es una lista enlazada de nodos, donde cada nodo tiene un par de campos de enlace, el que permite atravesar la lista hacia adelante mediante el campo de enlace sig (siguiente), y hacia atrás con el campo de ente ant(anterior).Es una colección de elementos homogéneos que tiene una relación lineal se da en ambos sentidos.

Características- En cada nodo existe una referencia a su nodo predecesor y sucesor a más del

campo dato o de información.- El recorrido se lo puede hacer en ambos sentidos- Solo, en el nodo inicial o cabecera la referencia al nodo predecesor será null o

puede apuntar al último nodo.- Solo en el nodo final la referencia al nodo sucesor será null o puede apuntar al

primer nodo.

Analiza:Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista Doblemente Enlazada, comenta con tus compañeros y con tu profesora…..!!!

Analiza:Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista Doblemente Enlazada, comenta con tus compañeros y con tu profesora…..!!!

Page 46: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 46

- Se requiere de dos variables de referencia para el recorrido.

Partes de un Nodo Doble

Campo de

enlace anterior

Campo dato o info

Campo de enlace

siguiente

Nivel físico: Implementación de operaciones de Listas Doblemente Enlazadas

Si se utiliza un nodo cabecera en una lista de doble enlace ya no es necesario contar con las referencias primero y último, puesto que el nodo cabecera tiene ambas referencias: su referencia siguiente es el primer elemento de la lista, y su referencia anterior es el último elemento de la lista. De esta forma la lista de doble enlace queda circular de una manera natural, esto facilitará la implementación de la lista doblemente enlazada, quedando la lista de la siguiente manera:

MODELADO:

NodoDoble- ant: NodoDoble- sig: NodoDoble- dato:Object+ NodoDoble()+ setAnt(nodo:NodoDoble):void+ setSig(nodo:NodoDoble):void+setDato(datos:Object):void+ getAnt():NodoDoble+getSig():NodoDoble+ setDato():Object+ insertarAntes (después: NodoDoble,d:Object):void

Page 47: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 47

+ insertarDespues(antes: NodoDoble,d:Object):void+ insertarEntre(antes: NodoDoble,d:Object,después:

NodoDoble):void

ListaDoble+ top: NodoDoble- numeroNodos:int+ ListaDoble()+ longuitud():int- incLongitud():void-decLongitud():void+insertarAtHead(d:Object):void+ insertarAtFinal(d: Object):void+insertarAt(indice:int, d: Object):void+deleteFirst()void+deleteNodo(índice:int):void+ getAt(indice: int): Object+printNodos():void

IMPLEMENTACION LISTAS DOBLESClase: NodoDoblepublic class NodoDoble {    // Referencias al nodo anterior y posterior en la lista    private NodoDoble sig;    private NodoDoble ant;    // Referencia a los datos actuales del objeto    // Esto no funcionaria con tipos basicos, porque no    // se pueden pasar como objetos    private Object dato;    // Constructor Basico    public NodoDoble() {        // Reseteamos los apuntadores        setSig(null);        setAnt(null);

        // En principio, no hay datos        setDato(null);    }    // Construimos un nuevo nodo y lo insertamos en medio    // de los dos que nos indiquen

    public NodoDoble(NodoDoble antes,            NodoDoble despues, String d) {        insertEntre(antes, despues, d);    }    // Inserta un nodo entre dos determinados    // Acceso a los elementos de un nodo    public NodoDoble getAnt() {        return (ant);    }    public NodoDoble getSig() {        return (sig);    }    public Object getDato() {        return (dato);    }

Page 48: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 48

    // Modificacion de los elementos de un nodo

    public void setAnt(NodoDoble nodo) {        ant = nodo;    }    public void setSig(NodoDoble nodo) {        sig = nodo;    }    public void setDato(Object d) {        dato = d;    }    // Inserta un nodo antes del que nos indiquen    public void insertAntes(NodoDoble despues, Object d) {        // Fijamos nuestros apuntadores        setAnt(despues.getAnt());        setSig(despues);        // Fijamos los apuntadores de los otros nodos a nosotros        getAnt().setSig(this);        despues.setAnt(this);        // Fijamos los datos del nodo        setDato(d);    }    // Inserta un nodo despues del que nos indiquen    public void insertDespues(NodoDoble antes, Object d) {        // Fijamos nuestros apuntadores        setAnt(antes);        setSig(antes.getSig());        // Fijamos los apuntadores de los otros nodos a nosotros        antes.setSig(this);        getSig().setAnt(this);        // Fijamos los datos del nodo        setDato(d);    }    public void insertEntre(NodoDoble antes, NodoDoble despues, Object d) {        // Fijamos nuestros apuntadores        setAnt(antes);        setSig(despues);        // Fijamos los apuntadores de los otros nodos a nosotros        antes.setSig(this);        despues.setAnt(this);        // Fijamos los datos del nodo        setDato(d);    }    public void deleteEntre(NodoDoble antes, NodoDoble despues) {        //Fijamos los apuntadores        antes.setSig(despues);        despues.setAnt(antes);    }}Clase: Lista Doblepublic class ListaDoble {    // Usaremos un nodo 'top' para controlar el principio y final    // de la lista doblemente enlazada que estamos implementando,    // lo que nos simplifica bastante las cosas    public NodoDoble top;    // Mantenemos un contador del numero de nodos en la lista

Page 49: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 49

    private int numNodos;    // Constructor basico    public ListaDoble() {        // Inicialmente, no hay ningun nodo        numNodos = 0;        // Creamos nuestro nodo         top = new NodoDoble();        // Hacemos que los apuntadores del nodo lo hagan a        // si mismo, incluso que sus datos se refieran a los suyos        top.insertEntre( top,top,null );        }    // Acceso al numero de nodos    public int longitud() {        return( numNodos );        }    // Modificacion del numero de nodos    private void incLongitud() {        numNodos++;        }    private void decLongitud() {        numNodos­­;        }    // Insertamos los datos que nos indiquen como nueva cabecera    // de la lista    public void insertAtHead( Object d) {        NodoDoble temp = new NodoDoble();        temp.insertDespues( top,d);        incLongitud();        }    // Insertamos los datos que nos indiquen al final de la lista    public void insertAtFinal( Object d) {        NodoDoble temp = new NodoDoble();        temp.insertAntes( top,d);        incLongitud();        }    // Insertamos los datos en la posicion que nos digan, o al    // final de la lista en caso de que no sea tan larga como    // indique el indice    public void insertAt( int indice,Object d) {        // Comprobamos que la lista tenga suficientes nodos        if( longitud() < indice )            {            // Si no los tiene, insertamos al final            insertAtFinal(d);            }        else            {            NodoDoble temp;            NodoDoble aux;

            // Vamos saltando de nodo en nodo hasta llegar al indicado            aux = top;            for( int i=0; i < indice­1; i++ )                aux = aux.getSig();

            // Creamos un nuevo nodo en esa posicion y lo incorporamos a

Page 50: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 50

            // la lista             //   temp= new NodoDoble(aux,aux.getSig(),d);               temp=new NodoDoble();               temp.insertEntre(aux, aux.getSig(), d);                incLongitud();        }   }    // Recupera los datos de un determinado nodo (o del ultimo elemento    // si la lista no tiene tantos nodos), o devuelve null si la    // lista esta vacia    public void deleteFirst(){        if(longitud()==0){            System.out.println("Lista vacia...No se puede eliminar el nodo del inicio");        }else{            System.out.println("Nodo a eliminar :"+top.getSig().getDato());            top.setSig(top.getSig().getSig());            decLongitud();        }    }    public void deleteEnd(){        if(longitud()==0){            System.out.println("Lista vacia...No se puede eliminar el nodo del final");        }else{            System.out.println("Nodo a eliminar :"+top.getAnt().getDato());            top.setAnt(top.getAnt().getAnt());            decLongitud();        }    }    public Object getAt( int indice ) {        // Comprobamos si la lista tiene tantos nodos como indica el indice        if( longitud() < indice )            {            // Comprobamos que la lista no este vacia            if( longitud() == 0 )                // La lista esta todavia vacia                return( null );            else                return (top.getDato());            }        else            {            // Estamos dentro del rango de la lista            NodoDoble aux;

            // Vamos saltando por los nodos hasta alcanzar el pedido            aux = top.getSig();            for( int i=0; i < indice; i++ )                aux = aux.getSig();            // Devolvemos los datos de ese nodo            return( aux.getDato());            }        }       public void printInverso() {        // Comprobamos si la lista tiene tantos nodos como indica el indice        if( longitud() == 0){            // Comprobamos que la lista no este vacia

Page 51: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 51

            System.out.print("La lista esta vacia");        }else{            // Estamos dentro del rango de la lista            NodoDoble aux;            // Vamos saltando por los nodos hasta alcanzar el pedido            aux = top.getAnt();            System.out.println("PRESENTACION EN ORDEN DESCENDENTE\n");            for( int i=longitud(); i > 0; i­­ ){                // presentamos los datos de ese nodo                 System.out.println("Valor nodo:" +i+"\t"+aux.getDato());                //avanzar al anterior nodo de la lista                aux = aux.getAnt();            }         }       }       public void PrintNodos(){        // Comprobamos si la lista tiene tantos nodos como indica el indice        if( longitud() == 0){            // Comprobamos que la lista no este vacia            System.out.print("La lista esta vacia");        }else{            // Estamos dentro del rango de la lista            NodoDoble aux;            // Vamos saltando por los nodos hasta alcanzar el pedido            aux = top;            //System.out.println("PRESENTACION EN ORDEN ASCENDENTE \n");            for( int i=1; i<longitud(); i++ ){                // avanzar al siguiente nodo de la lista                aux = aux.getSig();                System.out.println("\t"+aux.getDato());                //presentamos el valor del nodo            }      }       }     }

EJERCICIOS PROPUESTOS

Implementar el método de eliminación de nodos para la lista doble, según el código fuente desarrollado en clases.

En java también existe un api propio para trabajar con Listas Dobles se trata de la Clase LinkedList INVESTIGA..!!!

Page 52: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 52

4 PILAS

Es una estructura lineal de objetos ordenados tales que estos se obtienen por un solo lado de la estructura siguiendo un sistema definido entre los que tenemos:

UEPS = “ultimo en entrar, primero en salir”LIFO= “Last in Firts out”

Una pila es una estructura de datos en la cual el acceso está limitado al último elemento insertado (el más reciente).

Todas las operaciones que se definan sobre una pila deben de tener costo constante, independientemente del número de elementos de la pila.

Las Operaciones básicas son:Insert PushDelete PopSearch Tope

Analiza:Ejemplos donde están aplicadas las pilas es:En la opción deshacer o rehacer en aplicaciones de ofimáticas.

En el retroceso de páginas de los exploradores de internet.

Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista ordenada, comenta con tus compañeros y con tu profesora…..!!!

Analiza:Ejemplos donde están aplicadas las pilas es:En la opción deshacer o rehacer en aplicaciones de ofimáticas.

En el retroceso de páginas de los exploradores de internet.

Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista ordenada, comenta con tus compañeros y con tu profesora…..!!!

Page 53: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 53

Representación

TDA: PilaElementos: Cualquier objeto, esto depende de la aplicacion a implementarse.Estructura: LinealDominio: La pila tendrá la capacidad de almacenar la cantidad de elementos dependiendo de la aplicación.OPERACIONES:1. METER (PUSH) Utilidad: Agrega un elemento a la pila.Datos de Entrada: Elemento (e), pila (p)Datos de Salida: La pila con un elemento masPrecondiciones: Que la pila este creada y no esté llenaPostcondiciones: La pila con un elemento adicional agregado por el tope de la pila

2. SACAR(POP) Utilidad: eliminar el último elemento que se agrego a la pila.Datos de Entrada: pila (p)Datos de Salida: La pila con un elemento menos y el elemento que se saca a la pilaPrecondiciones: Que la pila no este vacíaPostcondiciones: La pila con un elemento menos que fue eliminado por el tope de la pila.

3. VACIA Utilidad: Verifica si una determinada pila esta vacía o no.Datos de Entrada: la pila que se va a verificarDatos de Salida: valor booleano (true, false)Precondiciones: Que la pila existaPostcondiciones:

4. LLENA Utilidad: Verifica si una determinada pila está llena o noDatos de Entrada: la pila (p) que se va a verificarDatos de Salida: valor booleano (true, false)Precondiciones: que la pila existaPostcondiciones:

Nivel físico: Implementación de operaciones de Pilas

MODELADO:Pila

- dato: String- sig: Pila

+ top: Pila+ Pila ( )+ getDato( ): String+ getSig( ): Pila+ setDato( dato:String):void+ setSig( sig: Pila):void+ esVacia( ):Boolean

Page 54: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 54

+ hacePush(d: String):void+ hacePop( ): void+ query( ): String+print( ): void

Algoritmo: PUSH/INSERTAR/METER/APILAR1.-Leer valor2.-Crear un nuevo nodo que sea tipo pila3.-Inicilizar su campo de no enlace 4.-Enlazar la referencia de top con el nuevo nodo5.-Avanza top

Algoritmo: POP/ELIMINAR/SACAR/DESAPILAR 1._ Verificar si la pila está vacía si no lo está retornar el elemento.2._ Asignar a top, la referencia del siguiente elemento apuntado por top

IMPLEMENTACION DE PILASpublic class Pila {    private String dato;    private Pila sig;    public Pila top=null;        public Pila() {        setSig(null);        setDato(null);    }    public String getDato() {        return dato;    }    public void setDato(String dato) {        this.dato = dato;    }    public Pila getSig() {        return sig;    }    public void setSig(Pila sig) {        this.sig = sig;    }    public boolean esVacia(){        if(top==null)            return true;        else            return false;    }    public void hacePush(String d) {        Pila temp= new Pila();        temp.setDato(d);        temp.setSig(top);        top=temp;        System.out.println( "push( "+top.getDato()+" )" );    }

    public void hacePop() {        if (esVacia()){            System.out.print("No hay elementos en la pila");}

Page 55: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 55

        else{            System.out.println( "pop( "+top.getDato()+" )" );            top=top.getSig();        }    }    public String info(){        if(esVacia())            return null;        else            return top.getDato();    }    public void print(){        Pila aux;        aux=top;        System.out.print("Pila : [");        while(aux!=null){            if(aux.getSig()!=null){                System.out.print(aux.getDato()+ ",");            }else{                System.out.print(aux.getDato());            }            aux=aux.getSig();        }        System.out.print("]\n");    }     public static void main(String[] args) {         Pila p = new Pila();         p.print();         p.hacePush("Franklin");         p.hacePush("Mireya");         p.hacePush("Wilson");         p.hacePush("Gabrielita");         System.out.println("Elemento de la cima de la pila es:"+p.info());         p.hacePush("Xavier");         p.hacePush("July");         p.print();         System.out.println("Elemento de la cima de la pila es:"+p.info());         p.hacePop();         p.hacePop();         p.hacePop();         p.hacePop();         p.hacePush("Nuevo");         p.print();     } 

En java también existe un Api propio para trabajar con la Estructura Pila, se trata de la Clase Stack... INVESTIGA..!!!

Page 56: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 56

5 Colas o Filas

Una cola es una estructura de datos en la cual el acceso está limitado al elemento insertado recientemente.

Además una cola es una colección ordenada de elementos homogéneos en la que solo se puede añadir por el final y eliminar por el frente y se requiere dos punteros, para su manipulación.

Aplica la filosofía FIFO(first in first out) o PEPS (primero en entrar, primero en salir)

Las operaciones básicas son: Insert Encolar Delete Desencolar Search Tope

Representación

TDA: COLA O FILAElementos: cualquier clase de objetos, dependiendo de la aplicación.Estructura: Lineal.Dominio: se maneja cantidades de objetos de acuerdo a la aplicación.OPERACIONES:

1._ INSERTAR /ENCOLAR: Utilidad: Agregar un elemento e, a la fila o cola.Dato de entrada: El elemento e y la cola.Dato de Salida: La cola con un elemento adicional.Precondiciones: que la cola este creada y no esté llena

Analiza:Ejemplos donde se pueden aplicar las colas son:Los drivers de la impresora, todos los trabajos que reciben para su impresión, siempre los colocan en una cola de acuerdo a cómo han llegado.Las colas de los bancos. En los sistemas operativos al momento de asignar algún recurso a los procesos.

Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista ordenada, comenta con tus compañeros y con tu profesora…..!!!

Analiza:Ejemplos donde se pueden aplicar las colas son:Los drivers de la impresora, todos los trabajos que reciben para su impresión, siempre los colocan en una cola de acuerdo a cómo han llegado.Las colas de los bancos. En los sistemas operativos al momento de asignar algún recurso a los procesos.

Piensa en varias aplicaciones informáticas de la vida real, en donde se utilice la estructura: Lista ordenada, comenta con tus compañeros y con tu profesora…..!!!

Page 57: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 57

Postcondiciones: La cola con un elemento más agregado por el final.

2._ ELIMINAR/DESENCOLAR:Utilidad: elimina el primer elemento que se agregó a una colaDato de entrada: La cola a la que se va a quitar el elementoDato de salida: La cola con un elemento menos y el elemento que se eliminóPrecondiciones: La cola este creada y no este vacía.Postcondiciones: La cola con un elemento menos eliminado por el frente de la cola.

3._ VACIA:Utilidad: Verificar si una determinada cola se encuentra vacía o no.Datos de entrada: La cola que se va a verificar.Datos de salida: Booleano, que indique si la cola está vacía o no.Precondiciones: Que la cola a verificar exista Postcondiciones: Ninguna

4._ LLENA:Utilidad: Verificar si una determinada cola este llena o no.Dato de entrada: La cola que se va a verificarDato de salida: Valor booleano que indique si la cola está llena o noPrecondiciones: la cola este creada.Postcondiciones: Ninguna

Nivel físico: Implementación de operaciones de Colas

MODELADO:Cola

- dato: Object- sig : Cola+ top : Cola+ last: Cola+ Cola( )+ Cola (dato: Object)+ getDato( ): Object+ getSig ( ): Cola+ setDato( dato: Object)+ setSig(nodo:Cola )+ esVacia( ):boolean+ encolar(Object d):void+ desencolar( ):void+ print( ):Object

IMPLEMENTACIÓN DE COLASpublic class Cola {    private Object dato;    private Cola sig;    public Cola top;    public Cola last;    public Cola( ){        top = last = null;    }    public Cola(Object dato){        this.dato=dato;        this.sig = null;    }    public Object getDato(){        return dato;    }     public Cola getSig(){        return sig;

Page 58: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 58

    }    public void setSig(Cola nodo){        this.sig=nodo;    }    public boolean esVacia( ){        if(top == null){            return true;        }else{            return false;        }    }    public void vaciar( ){        top = last = null;        }   public void desencolar( ){        if (esVacia( )){            System.out.print("\n Error al desencolar ...");        }else{            System.out.print("\n ­> ["+top.getDato()+"]");            top = top.getSig();        }    }   //Implementacion del examen    public Object desencolarDato(){        Object d=null;        if (esVacia( )){            System.out.print("\n Error al desencolar ...");        }else{            d=top.getDato();            top = top.getSig();        }        return d;    }        public void encolar(Object d){        Cola temp = new Cola(d);        if (esVacia( ) ){            top = last = temp;        }else{            last.setSig(temp);            last = temp;        }        System.out.print("\n <­ ["+last.getDato()+"]");    }    public void print(){        Cola aux;        aux=top;        System.out.print("\n Cola : [");        while(aux!=null){            if(aux.getSig()!=null){                System.out.print(aux.getDato()+ ",");            }else{                System.out.print(aux.getDato());            }            aux=aux.getSig();        }

Page 59: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 59

        System.out.print("]");    }    public static void main(String[] args)throws Exception {       Cola c= new Cola();          c.encolar("Maria");          c.encolar("Jose");          c.encolar("Juan");          c.encolar("Andres");          c.print();          c.desencolar();          c.desencolar();          c.desencolar();          c.desencolar();          c.desencolar();          c.encolar("Xavier");          c.encolar("Gabrielita");          c.encolar("Franklin");          System.out.println("\n Nodo desencolado: "+c.desencolarDato());          c.desencolar();          c.print();    }}

En java también existe un Api propio para trabajar con la Estructura Cola, se trata de la Interfaz Queue, podrias utilizar la colas con prioridad instanciando objetos de la Clase PriorityQueue... INVESTIGA..!!!

Page 60: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 60

6 RECURSIÓN

La recursividad: es una nueva forma de ver las acciones repetitivas permitiendo que un método se llame así mismo para resolver una versión más pequeña del problema original.

El concepto de recursividad va ligado al de repetición. Son recursivos aquellos algoritmos que, estando encapsulados dentro de un método, son llamados desde ella misma una y otra vez, en contraposición a los algoritmos iterativos, que hacen uso de bucles while, do-while, for, etc. 6.1 DefiniciónLa recursividad es una función que se llama a sí misma para dividir un problema en problemas más sencillos, el método recursivo debe estar compuesto de una caso base para el cual ya se conoce un resultado y una llamada al mismo método con una versión ligeramente más sencilla del problema inicial.Algo es recursivo si se define en términos de sí mismo (cuando para definirse hace mención a sí mismo). Para que una definición recursiva sea válida, la referencia a sí misma debe ser relativamente más sencilla que el caso considerado. 6.2 Elementos de la Recursión En la resolución de algoritmos recursivos es imprescindible encontrar estos dos elementos.◦ Axioma: Es un caso donde el problema puede resolverse sin tener que hacer uso de

una nueva llamada a sí mismo. Evita la continuación indefinida de las partes recursivas.

◦ Formula recursiva:Relaciona el resultado del algoritmo con resultados de casos más simples. Se hacen nuevas llamadas a la función, pero están más próximas al caso base.

6.3 Tipos de Recursión

Directa: es la que la función se llama así misma.

Indirecta: es la recursión que se produce cuando la función se llama no así misma sino a otra función (y esta quizás a otra) que termina llamando a la función inicial. Se produce así una cadena:

f (a) → g(b) → h(c) → . . . f (a0)

6.4 Modos de recursiónExisten distintos modos de hacer la recursión:

De cabeza: la recursión de cabeza se produce cuando la llamada recursiva se hace justo al principio del método recursivo, antes que ninguna otra operación.

De cola: por el contrario, en la de cola la llamada se hace al final después de todas las

Page 61: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 61

operaciones intermedias implica la existencia de operaciones antes y después de la llamada recursiva.

Múltiple: se producen varias llamadas, recursivas en distintos puntos del método.

Anidada: la anidada o no primitiva es aquella en la que la recursión se produce en un parámetro de la propia llamada recursiva. Es decir, al hacer la llamada recursiva se utiliza un parámetro que es el resultado de una llamada recursiva.

6.5 Implementación interna en un ordenadorEn un lenguaje de programación, cuando se llama a un método, lo que se hace es que se guarda la dirección de la sentencia ‘llamante’ como dirección de retorno; se asigna nueva memoria para las variables locales del procedimiento, y al finalizar la ejecución del procedimiento, se libera la memoria asignada a las variables locales y se vuelve la ejecución al punto en que se hizo la llamada haciendo uso de la dirección de retorno, dirección de la instrucción que sigue a la instrucción de llamada al método.

Por otro lado, tenemos que estudiar dos conceptos más. Uno es la pila (stack ) y el otro son los registros de activación de los procedimientos. Una pila es una estructura de datos en la que solo cabe añadir o quitar un dato cada vez, pero, tal y como se hace con una pila de libros, por ejemplo, para el dato a extraer solo es accesible el último libro que se apilo.

El registro de activación de un método es un bloque de memoria que contiene información sobre las constantes, variables locales declaradas en el procedimiento y los parámetros que se le pasen en esa llamada al método, junto con la dirección de retorno que corresponde a esa llamada.

Los lenguajes de programación actuales utilizan una pila especial que el sistema tiene para las llamadas a subrutinas. En esta pila el código máquina del programa cada vez que tiene que llamar a un procedimiento guarda su registro de activación. Si dentro de esta subrutina se llama de nuevo así misma en forma recurrente, dado que la creación del registro de activación del propio método se hace sobre una pila sin borrar los registros de activación anteriores, se puede generar uno nuevo para cada llamada recursiva. Al final nos encontramos con que con cada llamada recursiva se están apilando registros de activación sobre los registros de activación de las llamadas anteriores.

Cuando una de las llamadas recursivas se resuelve por fin sin recursión, su registro de activación se ‘quita’ de la pila (se desapila) siguiendo la ejecución del programa por donde iba cuando se llamó esta última vez. Y por tanto siguiendo también con las variables y parámetros que se tenían en aquí el momento. De nuevo, cuando esta llamada se resuelve sin recursión, se repite la disminución de la pila y vuelta al estado anterior.

Debido a la sobrecarga (overhead ) que producen las operaciones sobre la pila, la creación y borrado de los registros de activación, los métodos recursivos consumen

Page 62: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 62

mas tiempo y memoria que los programas no recursivos.

Solo en determinadas ocasiones, debido a la estructura de datos usada en el problema o al planteamiento del mismo la recursión es preferible, y evitar la recursión es bastante más difícil que dar una solución recursiva al problema.

6.6 Verificación de la corrección de un algoritmo recursivoPara comprobar que un algoritmo recursivo funciona correctamente es necesario que siga las tres reglas siguientes:

1. Existe un caso base (por cada llamada recursiva que se haga dentro del algoritmo debe haber un valor) para el cual el algoritmo finalice sin recursión. Por ejemplo, fact(0) =0 sin recursión. En el algoritmo factorial se produce una llamada recursiva con lo cual es suficiente con un caso base.

2. Todos los posibles argumentos de las llamadas recursivas se renvían tendiendo sus valores hacia un caso base. En el caso del factorial, ya que la llamada recursiva que se hace es con fact(n-1) y n se suponía natural, tienden para valores de n > 0 al valor 0.

3. La función es correcta, para valores distintos del caso base. En el caso del factorial, por inducción, tendríamos que si fact(n) = n!, entonces fact(n + 1) = n · fact(n) = (n + 1)!

En general la búsqueda de una solución recursiva de los algoritmos se facilita mediante la localización de los casos bases. Una vez respondidos a ellos, se trata de que el argumento en general tienda a estos valores.

6.7 Conveniencia del uso de la recursividadLa recursión debería de evitarse siempre que se pueda por motivos de eficiencia, Sin embargo, seria justificable emplearla cuando:

• Se sabe que la función no va a generar demasiada profundidad de llamadas recursivas; particularmente por que la pila del sistema donde se guardan todos las variables locales y parámetros, es relativamente pequeña y podría colapsar el sistema.

• Se sabe que la función no va a utilizar estructuras de datos locales demasiado grandes. Si así fuese el caso, aunque la solución se mantuviese como recursiva habría que recurrir a otra forma de mantener los datos.

• Cada llamada no genera a su vez llamadas ya resueltas en otras llamadas que se generarán o se han generado antes. Este problema hay que analizarlo antes y es frecuente en recursión. Es una fuente de ineficiencia usual en recursión el que una función se evalué múltiples veces con el mismo valor de parámetro en las llamadas recursivas generadas internamente.

• La solución no es planteable de forma sencilla de otra manera. Ocurre en muchos casos que la forma recursiva es muy mas clara que la iterativa.

Page 63: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 63

6.8 Ejemplos de programas recursivosEjemplo 1:Factorial de un número

public 

class Factorial {

    static int fac(int n) {        if (n == 1) {            return 1;        } else {            return (n*fac(n ­ 1));        }    }

    public static void main(String[] arg) {        System.out.println("El factorial de 5 es:" + fac(5));    }}Ejemplo 2:Fibonacci

//presenta los n primeros fibonaccipublic class Fibonacci {

public static int fibo(int n) {                if (n < 2) {                   return n;                }                else {

   return fibo(n­1)+fibo(n­2);                                   }

}        public static void main(String[] arg) {            for(int i=0;i<10;i++){                System.out.print(fibo(i)+",");            }        }}

EJERCICIOS PARA RESOLVER EN CLASE

Ejercicio 1. Programar un algoritmo recursivo que permita hacer la división por restas sucesivas.Ejercicio 2. Programar un algoritmo recursivo que permita invertir un número. Ejemplo: Entrada: 123 Salida: 321

Page 64: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 64

Ejercicio 3. Programar un algoritmo recursivo que permita sumar los dígitos de un número. Ejemplo: Entrada: 123 Resultado:6Ejercicio 4. Programar un algoritmo recursivo que permita sumar los elementos de un vector.Ejercicio 5. Programar un algoritmo recursivo que calcule el Máximo común divisor de dos números.Ejercicio 6. Programar un algoritmo recursivo que muestre el numero menor de un vector.Ejercicio 7. Programar un algoritmo recursivo que muestre el numero mayor de un vector.

Page 65: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 65

7 MÉTODOS DE BUSQUEDA Y ORDENACIÓN 7.1 Análisis de AlgoritmosLas estructuras pueden implementarse de diferentes maneras, y es más, existen algoritmos para implementar dichas estructuras. El uso de estructuras de datos adecuadas pueden hacer trivial el diseño de un algoritmo, o un algoritmo muy complejo puede usar estructuras de datos muy simples.Uno de los algoritmos más antiguos conocidos es el algoritmo del matemático griego Euclides. El término algoritmo proviene del matemático Mohammed ibn Musa al-Khowarizmi, matemático Persa (actual Irán), que vivió aproximadamente entre los años 780 y 850 d.C. (Siglo IX) El describió la realización de operaciones elementales en el sistema de numeración decimal. De al-Khwarizmi se obtuvo la derivación algoritmo. 7.2 Clasificación de algoritmos• Algorit m o determinista : en cada paso del algoritmo se determina de forma única el siguiente paso.• Algoritm o n o determinista : deben decidir en cada paso de la ejecución entre varias alternativas y agotarlas todas antes de encontrar la solución.Todo algoritmo tiene una serie de características, entre otras que requiere una serie de recursos, algo que es fundamental considerar a la hora de implementarlos en una máquina. Estos recursos son principalmente:

• El tiempo: período transcurrido entre el inicio y la finalización del algoritmo.• L a memoria : la cantidad (la medida varía según la máquina) que

necesita el algoritmo para su ejecución.Obviamente, la capacidad y el diseño de la máquina pueden afectar al diseño del algoritmo.

En general, la mayoría de los problemas tienen un parámetro de entrada que es el número de datos que hay que tratar, esto es: N.

La cantidad de recursos del algoritmo es tratada como una función de N. De esta manera puede establecerse un tiempo de ejecución del algoritmo que suele ser proporcional a una de las siguientes funciones:

Tiempo de ejecución constante. Significa que la mayoría de las instrucciones se ejecutan una vez o muy pocas.

• N: Tiempo de ejecución lineal. Un caso en el que N valga 40, tardará el doble que otro en que N valga 20. Un ejemplo sería un algoritmo que lee N números enteros y devuelve la media aritmética.

• N2: Tiempo de ejecución cuadrático. Suele ser habitual cuando se tratan pares de elementos de datos, como por ejemplo un bucle anidado doble. Si N se duplica, el tiempo de ejecución aumenta cuatro veces. El peor caso de entrada del algoritmo Quick Sort se ejecuta en este tiempo.

• logN: Tiempo de ejecución logarítmico. Se puede considerar como una gran constante. La base del logaritmo (en informática la más común es la base 2) cambia la constante, pero no demasiado. El programa es más lento cuanto más crezca N, pero es inapreciable, pues logN no se duplica hasta que N llegue a N2.

• N·logN: El tiempo de ejecución es N·logN. Es común encontrarlo en algoritmos como Quick Sort y otros del estilo divide y vencerás. Si N se duplica, el tiempo de ejecución es ligeramente mayor del doble.

• N3 : Tiempo de ejecución cúbico. Como ejemplo se puede dar el de un bucle anidado triple. Si N se duplica, el tiempo de ejecución se multiplica por ocho.

Page 66: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 66

• 2NN

:Tiempo de ejecución exponencial. No suelen ser muy útiles en la práctica por el elevadísimo tiempo de ejecución. El problema de la mochila resuelto por un algoritmo de fuerza bruta -simple vuelta atrás- es un ejemplo. Si N se duplica, el tiempo de ejecución se eleva al cuadrado.

• Algoritmos polinomiales: aquellos que son proporcionales a Nk

. Son en general factibles.

• Algoritmos exponenciales: aquellos que son proporcionales a kN. En general son infactibles salvo un tamaño de entrada muy reducido.

• Notación O-grande: en general, el tiempo de ejecución es proporcional, esto es, multiplica por una constante a alguno de los tiempos de ejecución anteriormente propuestos, además de la suma de algunos términos más pequeños. Así, un algoritmo cuyo tiempo de ejecución sea T = 3N

2 + 6N se puede considerar

proporcional a N2. En este caso se diría que el algoritmo es del orden de N

2, y se

escribe O(N2

)

Los grafos definidos por matriz de adyacencia ocupan un espacio O(N2),

siendo N, el número de vértices de éste.

La notación O-grande ignora los factores constantes, es decir, ignora si se hace una mejor o peor implementación del algoritmo, además de ser independiente de los datos de entrada del algoritmo. Es decir, la utilidad de aplicar esta notación a un algoritmo es encontrar un límite superior del tiempo de ejecución, es decir, el peor caso.

A veces ocurre que no hay que prestar demasiada atención a esto. Conviene diferenciar entre el peor caso y el esperado. Por ejemplo, el tiempo de ejecución del algoritmo Quick Sort es de O(N

2). Sin embargo, en la práctica

este caso no se da casi nunca y la mayoría de los casos son proporcionales a N·logN. Es por ello que se utiliza esta última expresión para este método de ordenación.Una definición rigurosa de esta notación es la siguiente:

Una función g(N) pertenece a O(f(N)) si y sólo si existen las constantes c0 y N0 tales que:

|g(N)| <= |c0·f(N)| , para todo N >= N0.

7.3 Clasificación de problemasLos problemas matemáticos se pueden dividir en primera instancia en dos grupos:

• Problemas indecidibles: aquellos que no se pueden resolver mediante un algoritmo.

• Problemas decidibles: aquellos que cuentan al menos con un algoritmo para su cómputo.

Sin embargo, que un problema sea decidible no implica que se pueda encontrar su solución, pues muchos problemas que disponen de algoritmos para su resolución son inabordables para un computador por el elevado número de operaciones que hay que realizar para resolverlos. Esto permite separar los problemas decidibles en dos:

• Intratables: aquellos para los que no es factible obtener su solución.

• Tratables: aquellos para los que existe al menos un algoritmo capaz de resolverlo en un tiempo razonable.

Los problemas pueden clasificarse también atendiendo a su complejidad. Aquellos problemas para los que se conoce un algoritmo polinómico que los resuelve se denominan clase P. Los algoritmos que los resuelven son deterministas. Para otros

Page 67: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 67

problemas, sus mejores algoritmos conocidos son no deterministas. Esta clase de problemas se denomina clase NP. Por tanto, los problemas de la clase P son un subconjunto de los de la clase NP, pues sólo cuentan con una alternativa en cada paso.

7.4 BÚSQUEDALa búsqueda de un elemento dentro de un array es una de las operaciones más importantes en el procesamiento de la información, y permite la recuperación de datos previamente almacenados. El tipo de búsqueda se puede clasificar como interna o externa, según el lugar en el que esté almacenada la información (en memoria o en dispositivos externos).

Todos los algoritmos de búsqueda tienen dos finalidades:• Determinar si el elemento buscado se encuentra en el conjunto en el que se busca.• Si el elemento está en el conjunto, hallar la posición en la que se encuentra.

Nos centramos en la búsqueda interna. Como principales algoritmos de búsqueda en arrays tenemos la búsqueda secuencial, la binaria y la búsqueda mediante transformación de claves hash.

7.4.1 Búsqueda secuencialConsiste en recorrer y examinar cada uno de los elementos del array hasta encontrar el o los elementos buscados, o hasta que se han mirado todos los elementos del array.

Implementación de la Búsqueda Secuencial

public int secuencial(int A[], int elemb){    int i;    for(i=0;i<A.length;i++){        if(A[i]==elemb)            return i;    }    return ­1;}//El arreglo debe estar ordenadopublic int secuencialOpt(int A[], int elemb){    int i;    for(i=0;A[i]<=elemb && i<A.length ;i++){    }    if(A[i­1]==elemb){        return i­1;    }else{        return ­1;    }}

7.4.2 Búsqueda binaria o dicotómicaLa condición más importante para poder utilizar este algoritmo, es que el array debe estar ordenado.

La búsqueda binaria consiste en dividir el array por su elemento medio en dos subarrays más pequeños, y comparar el elemento con el del centro. Si coinciden, la búsqueda se

Page 68: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 68

termina. Si el elemento es menor, debe estar (si está) en el primer subarray, y si es mayor está en el segundo.

Ejemplo:Para buscar el elemento 3 en el array {1, 2, 3, 4, 5, 6, 7, 8, 9} se realizarían los siguientes pasos:

Se toma el elemento central y se divide el array en dos:{1, 2, 3, 4}- 5 -{ 6, 7, 8, 9}

Como el elemento buscado (3) es menor que el central (5), debe estar en el primer subarray: {1,2,3,4} Se vuelve a dividir el array en dos: {1}- 2 -{3, 4}

Como el elemento buscado es mayor que el central, debe estar en el segundo subarray: {3,4} Se vuelve a dividir en dos: {}- 3 -{4}

Como el elemento buscado coincide con el central, lo hemos encontrado. Si al final de la búsqueda todavía no lo hemos encontrado, y el subarray a dividir está vacío {}, el elemento no se encuentra en el array.

En general, este método realiza log(2,n+1) comparaciones antes de encontrar el elemento, o antes de descubrir que no está. Este número es muy inferior que el necesario para la búsqueda lineal para casos grandes.

Este método también se puede implementar de forma recursiva, siendo la función recursiva la que divide al array en dos más pequeños.

Implementación de la Búsqueda Binariapublic int binaria(int A[], int elemb){    int desde, hasta, medio,pos;    desde=0;    hasta=A.length ­1;    pos=­1;    while(desde <=hasta){        if(desde == hasta){            if(A[desde]== elemb)                pos=desde;            else                pos=­1;            break;        }        medio=(desde+hasta)/2;        if(A[medio]==elemb){            pos=medio;            break;    }else{            if(A[medio]>elemb)                hasta=medio­1;            else                desde=medio+1;        }    }    return pos;

Page 69: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 69

} 7.5 ORDENACIÓNLos métodos de ordenación, búsqueda e intercambio, son operaciones básicas en las que las computadoras emplean la mitad de su tiempo.

Su mayor utilización se dá en las estructuras arreglos y archivos.

La ordenación también es conocida como clasificación, no es más que la operación de organizar un conjunto da datos en un orden dado, que puede ser creciente o decreciente.

Existe gran cantidad de algoritmos diseñados para clasificar listas de elementos, la elección del mejor método depende del tamaño del vector o archivo, el tipo de datos a ordenar y la cantidad de memoria física disponible.

Categorías Interna: Se utiliza para la ordenación de vectores o arreglos, tablas etc. Externa: Se utiliza para la ordenación de datos de un archivo.

Diferencias entre ordenación interna y externaInterna Externa

• Los datos se almacenan en memoria interna, que es de gran velocidad y acceso aleatorio

• Los datos se almacenan en soportes de almacenamiento externo: discos, cintas, que resultan más lentos pero contienen mayor cantidad de información.

7.5.1 Método de IntercambioEl método de intercambio es el más sencillo de todos. Se basa en: la lectura sucesiva de la lista a ordenar, comparando el elemento inferior o superior (dependiendo de la forma del recorrido) de la lista con todos los restantes, efectuando el Intercambio de posiciones cuando el orden resultante no sea correcto.

Ejemplo: a = { 8, 4, 6, 2 }

Pasada 1: Se compara a[0] con todos, así primero se cambia a[0] con a[1] pues a[0] > a[1] y debe ser Ascendente, es decir a[0]<a[1] …y por utimo a[0] con a[3].26{4, 8, 6, 2} => Se intercambia 4 por 8.{4, 8, 6, 2}{2, 8, 6, 4} => Se intercambia 2 por 4.

Pasada 2: El elemento más pequeño esta en a[0] y se analiza la sublista restante, es decir comenzamos en el siguiente elemento a[1]. Al cabo de la pasada, el segundo más chico esta en a[1] y así sucesivamente.{2, 6, 8, 4} => Se intercambia 6 por 8.{2, 4, 8, 6} => Se intercambia 4 por 6.

Pasada 3: Ahora nos toca comparar con el elemento a[2].{2, 4, 6, 8} => Se intercambia 6 por 8.

Page 70: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 70

Se terminan las pasadas y el arreglo o lista queda ordenado.

Análisis del método:

Número de Pasadas = n – 1;

Número Máximo de Comparaciones = (n-1) (n-2)

Tiempo de Ejecución = 0 (n2);donde n es el número de elementos en el arreglo o lista.

Implementación del Método de Intercambio //Ordena ascendentemente por el método de Intercambio    public void intercambio(int a[]){        int aux;        for(int i=0; i<=a.length­2;i++){            for(int j=i+1;j<=a.length­1;j++){                if(a[i]>a[j]){                    aux=a[i];                    a[i]=a[j];                    a[j]=aux;                }            }        }    } 7.5.2 Método de la burbujaEs un método mejorado con respecto al intercambio, en donde los elementos burbujean, es decir, los más grandes, caen al fondo del array (posición n-1) y los más mas chicos suben a la cima (posición 0).

Estudia parejas de elementos Adyacentes, a[0] y a[1], a[1] y a[2]…a[i] y a[i+1]… a[n–2]y a[n–1]. Si a[i+1] < a[i] Entonces los INTERCAMBIA

Ejemplo: {40,21,4,9,10,35}:

Pasada 1:{21, 40, 4, 9, 10, 35} <-- Se cambia el 21 por el 40.{21, 4, 40, 9, 10, 35} <-- Se cambia el 40 por el 4.{21, 4, 9, 40, 10, 35} <-- Se cambia el 9 por el 40.{21, 4, 9, 10, 40, 35} <-- Se cambia el 40 por el 10.{21, 4, 9, 10, 35, 40} <-- Se cambia el 35 por el 40.

Pasada 2:{4, 21, 9, 10, 35, 40} <-- Se cambia el 21 por el 4.{4, 9, 21, 10, 35, 40} <-- Se cambia el 9 por el 21.{4, 9, 10, 21, 35, 40} <-- Se cambia el 21 por el 10.{4, 9, 10, 21, 35, 40}

Ya están ordenados, pero habría que hacer una tercera, cuarta y quinta pasada.

Análisis del método:

Page 71: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 71

Número de Pasadas = n – 1;

Número Máximo de Comparaciones = n(n-1)/2

Tiempo de Ejecución = 0 (n2);dónde n es el número de elementos en el arreglo o lista.

Implementación del Método de la Burbuja //Ordena ascendentemente por el método de la Burbuja    public void burbuja(int a[]){        int aux;        for(int i=0; i<=a.length­1;i++){            for(int j=0;j<a.length­i­1;j++){                if(a[j+1]<a[j]){                    aux=a[j+1];                    a[j+1]=a[j];                    a[j]=aux;                }            }        }    }

7.5.3 Método de selección.Este método consiste en buscar el elemento más pequeño del array y ponerlo en la primera posición; luego, entre los restantes, se busca el elemento más pequeño y se coloca en segundo lugar, y así sucesivamente hasta colocar el último elemento. Por lo tanto, debe realizar sucesivas pasadas hasta que no haya posiciones restantes.

Ejemplo: {40, 21, 4, 9, 10, 35}

Pasada 1:{4, 21, 40, 9, 10, 35} <-- Se coloca el 4, el más pequeño, en primera posición:se cambia el 4 por el 40.Pasada 2:{4, 9, 40, 21, 10, 35} <-- Se coloca el 9, en segunda posición:se cambia el 9 por el 21.Pasada 3:{4, 9, 10, 21, 40, 35} <-- Se coloca el 10, en tercera posición:se cambia el 10 por el 40.Pasada 4:{4, 9, 10, 21, 40, 35} <-- Se coloca el 21, en cuarta posición:ya está colocado.Pasada 5:{4, 9, 10, 21, 35, 40} <-- Se coloca el 35, en quinta posición:se cambia el 35 por el 40.

Análisis del método:

Número de Pasadas = n – 1;

Número Máximo de Comparaciones = n(n-1)/2

Page 72: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 72

Tiempo de Ejecución = 0 (n2);dónde n es el número de elementos en el arreglo o lista.

Implementación del Método de Selección //Ordena ascendentemente por el método de Selección    public void seleccion(int a[]){        int aux, idmenor;        for(int i=0; i<=a.length­1;i++){            aux=a[i];            idmenor=i;            for(int j=i+1;j<a.length;j++){                if(a[j]<aux){                    idmenor=j;                    aux=a[j];                }            }            a[idmenor]=a[i];            a[i]=aux;        }    }

7.5.4 Método de inserción directaEste método lo que se hace es tener una sublista ordenada de elementos del array e ir insertando el resto en el lugar adecuado para que la sublista no pierda el orden. La sublista ordenada se va haciendo cada vez mayor, de modo que al final la lista entera queda ordenada, u otra forma de entender es que, consiste en insertar un elemento en su posición correcta, dentro de una lista que ya está Ordenada

Ejemplo: se tiene {40, 21, 4, 9, 10, 35}

{40, 21, 4, 9, 10, 35} <== La primera sublista ordenada es {40}.Insertamos el 21:{40, 40, 4, 9, 10, 35} <== aux=21;{21, 40, 4, 9, 10, 35} <== Ahora la sublista ordenada es {21,40}.Insertamos el 4:{21, 40, 40, 9, 10, 35} <== aux=4;{21, 21, 40, 9, 10, 35} <== aux=4;{4, 21, 40, 9, 10, 35} <== Ahora la sublista ordenada es {4,21,40}.Insertamos el 9:{4, 21, 40, 40, 10, 35} <== aux=9;{4, 21, 21, 40, 10, 35} <== aux=9;{4, 9, 21, 40, 10, 35} <== Ahora la sublista ordenada es {4,9,21,40}.Insertamos el 10:{ 4, 9, 21, 40, 40, 35} <== aux=10;{4, 9, 21, 21, 40, 35} <== aux=10;{4, 9, 10, 21, 40, 35} <== Ahora la sublista ordenada es {4,9,10,21,40}.Y por último insertamos el 35:{ 4, 9, 10, 21, 40, 40} <== aux=35;{4, 9, 10, 21, 35, 40} <== El array está ordenado.

Análisis del método:

Page 73: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 73

Dónde n es el número de elementos en el arreglo o lista.

Peor de los casos:Número Máximo de Comparaciones = n*(n+1)/2-1;Tiempo de Ejecución = 0 (n2);

Mejor de los casos (cuando la lista o arreglo ya esta ordenada):

Número Máximo de Comparaciones = n – 2; (Todas ellas falsas).

Tiempo de Ejecución = 0 (n);

El caso medio dependerá de cómo están inicialmente distribuidos los elementos.Vemos que cuanto más ordenada esté inicialmente más se acerca a O(n) y cuanto más desordenada, más se acerca a O(n2).El peor caso es igual que en los métodos de burbuja y selección, pero el mejor caso es lineal, algo que no ocurría en éstos, con lo que para ciertas entradas podemos tener ahorros en tiempo de ejecución.

Implementación del Método de Inserción Directa //Ordena ascendentemente por el método de Inserción Directa    public void insercionDirecta(int a[]){        int aux;        int j;        for(int i=0; i<a.length;i++){            aux=a[i];            for(j=i­1;j>=0;j­­){                if(aux > a[j]){                    a[j+1]=aux;                    break;                }else{                    a[j+1]=a[j];                }            }            if(j==­1)              a[0]=aux;        }    }

7.5.5 Método shellDebe su nombre a su inventor D.L.Shell, es un Método Avanzado que se le suele llamar Ordenación Por Inserción con Intervalos Decrecientes, lo cual es una mejora al método de Inserción directa cuando el arreglo o lista tiene una gran cantidad de elementos.En este método no se compara a cada elemento con el de su izquierda, como en el de inserción, sino con el que está a un cierto número de lugares (llamado salto) a su izquierda. Este salto es constante, y su valor inicial es N/2 (siendo N el número de elementos, y siendo división entera). Se van dando pasadas hasta que en una pasada no se intercambie ningún elemento de sitio. Entonces el salto se reduce a la mitad, y se vuelven a dar pasadas hasta que no se intercambie ningún elemento, y así sucesivamente hasta que el salto vale 1.

Ejemplo: se tiene {40, 21, 4, 9, 10, 35}

Page 74: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 74

n = 6Salto = 3; dónde n/2;Primera pasada:{9, 21, 4, 40, 10, 35} <== se intercambian el 40 y el 9.{9, 10, 4, 40, 21, 35} <== se intercambian el 21 y el 10.{9, 10, 4, 40, 21, 35}Salto = 1; dónde salto/2 ;Primera pasada:{9, 10, 4, 40, 21, 35}{9, 4, 10, 40, 21, 35} <== se intercambian el 10 y el 4.{9, 4, 10, 40, 21, 35}{9, 4, 10, 21, 40, 35} <== se intercambian el 40 y el 21.{ 9, 4, 10, 21, 35, 40} <== se intercambian el 35 y el 40.Segunda pasada:{4, 9, 10, 21, 35, 40} <== se intercambian el 4 y el 9.Con sólo 6 intercambios se ha ordenado el array, cuando por inserción se necesitaban muchos más.

Análisis del método:

Tiempo de Ejecución = O(n*(Log2 n));

Dónde n es el número de elementos en el arreglo o lista.

Implementación del Método Shell //Ordena ascendentemente por el método de Shell    public void shellsm(int a[]){        int aux,c,s;        s=a.length;        while (s!=1) {            s=s/2;            c=1;            while(c==1){                c=0;                for(int i=0;i< a.length­s;i++){                    if(a[i] > a[i+s]){                        aux=a[i];                        a[i]=a[i+s];                        a[i+s]=aux;                        c=1;                     }                }            }         }    }

7.5.6 Método de ordenación rápida (quicksort)Este método se basa en la táctica "divide y vencerás" que consiste en ir subdividiendo el array en arrays más pequeños, y ordenar éstos. Para hacer esta división, se toma un valor del array como pivote, y se mueven todos los elementos menores que este pivote a

Page 75: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 75

su izquierda, y los mayores a su derecha. A continuación se aplica el mismo método a cada una de las dos partes en las que queda dividido el array.Normalmente se toma como pivote el primer elemento de array, y se realizan dos búsquedas: una de izquierda a derecha, buscando un elemento mayor que el pivote, y otra de derecha a izquierda, buscando un elemento menor que el pivote. Cuando se han encontrado los dos, se intercambian, y se sigue realizando la búsqueda hasta que las dos búsquedas se encuentran.

Ejemplo: Para dividir el array {21,40,4,9,10,35}, los pasos serían:

{21, 40, 4, 9, 10, 35} <== se toma como pivote el 21. La búsqueda de izquierda a derecha encuentra el valor 40, mayor que pivote, y la búsqueda de derecha a izquierda encuentra el valor 10, menor que el pivote. Se intercambian:

{21, 10, 4, 9, 40, 35} <== Si seguimos la búsqueda, la primera encuentra el valor 40, y la segunda el valor 9, pero ya se han cruzado, así que paramos. Para terminar la división, se coloca el pivote en su lugar (en el número encontrado por la segunda búsqueda), el 9, quedando:

{9, 10, 4, 21, 40, 35} <== Ahora tenemos dividido el array en dos arrays más pequeños: el {9,10,4} y el {40,35}, y se repetiría el mismo proceso.

La implementación es claramente recursiva y suponiendo el pivote el primer elemento del array, el programa sería (en el método main): ordenar(array,0,array.length); // Para llamar a la función.

Análisis del método:Tiempo de Ejecución = O(n(Log n));Dónde n es el número de elementos en el arreglo o lista.

Implementación del Métodos Quicksort

//Ordena ascendentemente por el método de Quick Sort    public void quicks(int []a, int izq, int der){        int i=izq;        int j=der;        int pivote = a[(izq+der)/2];        do{            while(a[i]<pivote){                i++;            }            while(a[j]>pivote){                j­­;            }            if(i<=j){                int aux=a[i];                a[i]=a[j];                a[j]=aux;                i++;                j­­;            }        }while(i<=j);

Page 76: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 76

        if(izq <j){            quicks(a,izq,j);        }        if(i<der){            quicks(a,i,der);        }    } //Presenta los elementos del arreglo     public void presenta(String msg,int a[]){         System.out.print(msg+" :");          System.out.print("[");                 for(int i=0; i<=a.length­1;i++){             if(i<a.length­1){                System.out.print(a[i]+",");                          }else{                System.out.print(a[i]+"]");              }         }         System.out.print("\n");      }

EJERCICIOS PROPUESTOS

Investigar y desarrollar una variación del algoritmo burbuja denominada ordenación por hueco.

Page 77: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 77

8 ÁRBOLES 8.1 Introducción

Los árboles tienen una gran variedad de aplicaciones. Por ejemplo, se pueden utilizar para representar fórmulas matemáticas, para organizar adecuadamente la información, para construir un árbol genealógico, para el análisis de circuitos eléctricos y para numerar los capítulos y secciones de un libro.

Los árboles representan las estructuras no lineales y dinámicas de datos más importantes en computación. Dinámicas porque las estructuras de árbol pueden cambiar durante la ejecución de un programa. No lineales, puesto que a cada elemento del árbol pueden seguirle varios elementos. Los árboles pueden ser construidos con estructuras estáticas y dinámicas. Las estáticas son arreglos, registros y conjuntos, mientras que las dinámicas están representadas por listas.

La definición de árbol es la siguiente: Es una estructura jerárquica aplicada sobre 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, hermano, antecesor, sucesor, ancestro, etc. Formalmente se define un árbol de tipo T como una estructura homogénea que es la concatenación de un elemento de tipo T junto con un número finito de árboles disjuntos, llamados subárbols. Una forma particular de árbol puede ser la estructura vacía.

Terminología básica de la Estructura Árbol

Analiza: Ejemplos donde se aplican los árboles: son los sistemas de ficheros, diagrama modular, eliminatorias deportivas, organigramas de empresas etc, etc…Piensa en otras aplicaciones informáticas de la vida real, en donde se utilice la estructura: Arbol, comenta con tus compañeros y con tu profesora…..!!!

Analiza: Ejemplos donde se aplican los árboles: son los sistemas de ficheros, diagrama modular, eliminatorias deportivas, organigramas de empresas etc, etc…Piensa en otras aplicaciones informáticas de la vida real, en donde se utilice la estructura: Arbol, comenta con tus compañeros y con tu profesora…..!!!

Page 78: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 78

Raíz: único nodo que no tiene antecesor, es decir, sin padre.Rama: arista formado entre dos nodos.

Antecesor: un nodo X es el antecesor de un nodo Y si por alguna de las ramas de X se puede llegar a Y.

Sucesor: un nodo X es sucesor de un nodo Y si por alguna de las ramas de Y se puede llegar a X.

Grado de un nodo: número de descendientes directos que tiene un nodo.

Grado del árbol: es el mayor grado entre sus nodos.

Nodo interno: es aquel que tiene al menos un descendiente o nodo hijo.

Nodo hoja (externo): nodo que no tiene descendientes o no tiene nodos hijos, posee grado 0.

Descendiente directo: hijo

Descendientes: hijo, nieto...

Subárbol: árbol formado por un nodo y sus descendientes

Árbol binario: árbol de grado 2, en donde cada nodo tiene como mucho dos descendientes directos.

Árbol multicamino: Cada nodo puede tener n descendientes directos.

Lista: árbol degenerado de grado 1.

Nivel: número de ramas que hay que recorrer para llegar de la raíz a un nodo; la raízsiempre tiene un nivel de 0.

Profundidad de un nodo: número de predecesores.

Page 79: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 79

Altura del árbol: profundidad máxima de cualquier nodo o el nivel más alto del árbol

Camino: Existe un camino del nodo X al nodo Y, o si existe una sucesión de nodos que permitan llegar desde X a Y.

Formas de representar un árbol1. Mediante un grafo:

Page 80: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 80

Se utiliza la recursión para definir un árbol porque representa la forma más apropiada y porque además es una característica inherente de los mismos.

2. Mediante un diagrama encolumnado:

A continuación veremos en java como se puede declarar una estructura de datos básica (se indicará solamente atributos) para un árbol cualesquiera.

class NodoArbol {int dato; // información del nodo// es un arbol con ramas de hasta 3; NodoArbol nodo1, nodo2, nodo3;// si queremos más ramas deberíamos declarar un array de// objetos de tipo NodoArbol o utilizar Collections,// Vector, ArrayList, que son propias de Java......// Constructor y métodos propios del nodo.

}

Importante: En java también existe un api propio para trabajar con árboles tanto en forma visual como es la clase javax.swing.JTree y todo el paquete javax.swing.tree, así como también clases no visuales como java.util.TreeMap y java.util.TreeSet… INVESTIGA..!!!

8.2 Árboles binarios

A continuación se muestra un ejemplo de árbol binario para expresiones aritméticas, donde los nodos internos son los operadores y los nodos hojas son los operandos.

Analiza: Algunas aplicaciones de los árboles binarios pueden ser: expresiones aritméticas, árboles de decisión, búsqueda (ABB).Piensa en otras aplicaciones informáticas de la vida real, en donde se utilice la estructura: Arbol Binario, comenta con tus compañeros y con tu profesora…..!!!

Analiza: Algunas aplicaciones de los árboles binarios pueden ser: expresiones aritméticas, árboles de decisión, búsqueda (ABB).Piensa en otras aplicaciones informáticas de la vida real, en donde se utilice la estructura: Arbol Binario, comenta con tus compañeros y con tu profesora…..!!!

Page 81: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 81

Un Árbol Binario es como un conjunto finito de elementos que bien está vacío o está formado por una raíz con dos árboles binarios disjuntos, llamados subárbol izquierdo y derecho de la raíz. Las aplicaciones de los arboles binarios son muy variadas ya que se les puede utilizar para representar una estructura en la cual es posible tomar decisiones con dos opciones en distintos puntos.

La representación gráfica de un árbol binario es la siguiente:

Terminología básica árboles binarios

Nodo raíz: es el primer elemento de un árbol binario; un árbol binario sólo tiene un nodo raíz.

Nodo padre: son los nodos que tienen al menos un hijo (derecho y/o izquierdo). Hijo derecho: nodo que se encuentra al lado derecho de otro nodo. Hijo izquierdo: nodo que está al lado izquierdo de otro nodo. Nodo hoja: nodos que no tienen hijos. (Un nodo de un árbol binario puede tener

ninguno, uno o dos hijos.) Nodo hermano: nodos que tienen un mismo padre. Ancestros: nodo padre de un nodo o el padre de algún nodo ancestro. (El nodo raíz

es un ancestro de todos los nodos del árbol.) Nodo descendiente: el hijo de un nodo o el hijo de otro descendiente de ese nodo.

(Todos los nodos del árbol son descendientes del nodo raíz.) Subárbol izquierdo: todos los descendientes por la izquierda de un nodo forman

un subárbol izquierdo, cuya raíz es el hijo izquierdo de ese nodo. Subárbol derecho: todos los descendientes por la derecha de un nodo forman un

subárbol derecho, cuya raíz es el hijo derecho de ese nodo.

Page 82: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 82

Nivel de un nodo: distancia desde la raíz. La raíz está en el nivel cero. Cantidad de nodos por los que se tiene que pasar para llegar a un nodo. (El número máximo de nodos en el nivel n es 2".)

Propiedades de los árboles binarios

Representación en Memoria

Hay dos formas tradicionales de representar un árbol binario en memoria:

• Por medio de datos tipo punteros también conocidos como variables dinámicas o listas.

• Por medio de arreglos. Sin embargo la más utilizada es la primera, puesto que es la más natural para tratar este tipo de estructuras.

Los nodos del árbol binario serán representados como registros que contendrán como mínimo tres campos. En un campo se almacenará la información del nodo. Los dos restantes se utilizarán para apuntar al subarbol izquierdo y derecho del subarbol en cuestión.

Cada nodo se representa gráficamente de la siguiente manera:

Operaciones Básicas

Page 83: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 83

a) Recorrido de un árbol binarioExisten dos formas de recorrer un árbol:

Recorrido en amplitud: Consiste en ir visitando el árbol por niveles. Primero se visitan los nodos de nivel 0(como muchos hay uno, la raíz), después los nodos de nivel 1, así hasta que ya no quedan más. Si se hace el recorrido del árbol siguiente quedará: 4, 2, 6, 5, 8

Recorrido en profundidad: Recorre el árbol por subárboles. Y hay tres maneras de recorrer un árbol: en inorden, preorden y postorden. Cada una de ellas tiene una secuencia distinta para analizar el árbol como se puede ver a continuación:

1. PREORDEN Consiste en visitar el nodo actual (visitar puede ser simplemente mostrar la posición del nodo por pantalla), y después visitar el subárbol izquierdo y una vez visitado, visitar el subárbol derecho

Presorden: 4, 2, 6, 5, 8

2. INORDENSe visita el subárbol izquierdo, el nodo actual y luego se visita el subárbol derecho.

Inorden: 2, 4, 5, 6, 8

3. POSTORDEN Se visita primero el subárbol izquierdo, después el derecho y por último el nodo actual.

Postorden: 2, 5, 8, 6, 4b) Inserción

La inserción tampoco es complicada. Es más, resulta prácticamente idéntica a la búsqueda. Cuando se llega a un árbol vacío se crea el nodo en el puntero que se pasa como parámetro por referencia, de esta manera los nuevos enlaces mantienen la coherencia. Si el elemento a insertar ya existe entonces no se hace nada.

Page 84: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 84

c) BorradoLa operación de borrado si resulta ser algo más complicada. Se recuerda que el árbol debe seguir siendo de búsqueda tras el borrado. Pueden darse tres casos, una vez encontrado el nodo a borrar:1) El nodo no tiene descendientes. Simplemente se borra.2) El nodo tiene al menos un descendiente por una sola rama. Se borra dicho

nodo, y su primer descendiente se asigna como hijo del padre del nodo borrado.

Ejemplo de recorridos en la siguiente expresión aritmética: 2 x (a-1)+(3xb), sin paréntesis.

TDA: ARBOL BINARIOElementos:  guarda un conjunto de nodos. Cada uno de ellos contiene un dato homogéneo (simple o estructurado) único en el árbol.Estructura:  La   organización   de   los   datos   es   una   estructura   en   forma   jerárquica   o   de   niveles, restringiendo la relación de uno a dos como máximo,  sin cumplir ordenamiento alguno.Dominio: Depende de la aplicaciónOPERACIONES:- INSERCIÓN   

Utilidad: Inserta un nuevo elemento dentro del árbol binarioDatos de entrada: el árbol b, donde se va a insertar, y el nuevo elemento eDatos de salida: el árbol b, tiene un nuevo elemento insertado como hojaPrecondición: el árbol b existe y el elemento e no está en el árbolPostcondición: el árbol  b contiene al elemento nuevo insertado como una hoja

- ELIMINACIÓN   Utilidad: elimina un elemento dentro del árbol binarioDatos de entrada: el árbol b, donde se va a eliminar, y el elemento  o dato a eliminarDatos de salida: regresa falso si el dato no se encuentra en el árbol; verdadero si lo encontró y lo pudo eliminar, en cuyo caso, regresa el árbol modificado.Precondición: el árbol b existe y el elemento o dato está en el árbolPostcondición: el árbol  b contiene al elemento menos.

- BUSCAR   Utilidad: busca un elemento dentro del árbol binarioDatos de entrada: el árbol b, donde se va a buscar, y el nuevo elemento e por localizarDatos de salida: regresa falso si el valor no se encuentra en el árbol y un apuntador p almacenará la posición dentro del árbol donde está el valor.Precondición: el árbol b existe Postcondición: ninguna.

- RECORRER   Utilidad: despliega los elementos almacenados en un árbol binarioDatos de entrada: el árbol b a desplegar y el orden en que se desplegarán los elementosDatos de salida: cada nodo en el árbol se procesa exactamente una vez.  El orden en el que se procesarán los nodos depende del valor del orden.  Si el orden es:

Page 85: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 85

PreOrden: raíz­subárbol izquierdo­subárbol derechoPostOrden: subárbol izquierdo­subárbol derecho­raízInOrden: subárbol izquierdo­raíz­subárbol derecho.

Precondición: el árbol b existe Postcondición: ninguna.

Clasificación Existen cuatro tipos de árbol binario:• A. B. Distinto. • A. B. Similares. • A. B. Equivalentes. • A. B. Completos.

B. DistintoSe dice que dos árboles binarios son distintos cuando sus estructuras son diferentes.

A. B. SimilaresDos árboles binarios son similares cuando sus estructuras son idénticas, pero la información que contienen sus nodos es diferente.

A. B. EquivalentesSon aquellos arboles que son similares y que además los nodos contienen la misma información.

A. B. CompletosSon aquellos arboles en los que todos sus nodos excepto los del último nivel, tiene dos hijos; el subarbol izquierdo y el subarbol derecho.

Page 86: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 86

Implementación de Arboles binariosCLASE NODO BINARIO//Definicion de la clase NodoBinarioclass NodoBinario{

int dato;NodoBinario Hizq, Hder;//ConstructoresNodoBinario (int Elem){

dato = Elem;NodoBinario Hizq, Hder = null;

}//Insercion de un elementopublic void InsertaBinario (int Elem){

if(Elem < dato){if (Hizq == null)

Hizq = new NodoBinario(Elem);else

Hizq.InsertaBinario(Elem);}else{

if (Elem > dato){if (Hder == null)

Hder = new NodoBinario (Elem);else

Hder.InsertaBinario(Elem);}

}}

}CLASE NODO LISTA ARBOL

//Definicion de la Clase NodoListaclass NodosListaA{   NodoBinario datos;    NodosListaA siguiente;     //Construtor  Crea un nodo del tipo Object

NodosListaA (NodoBinario  valor){datos =valor;

    siguiente = null;  //siguiente con valor de nulo }

// Constructor Crea un nodo del Tipo Object y al siguiente nodo de la listaNodosListaA (NodoBinario valor, NodosListaA signodo){ 

datos = valor;     siguiente = signodo; //siguiente se refiere al siguiente nodo

}}CLASE COLA PARA EL RECORRIDO(ANCHURA)class Cola{

NodosListaA PrimerNodo;NodosListaA UltimoNodo;String Nombre;

Page 87: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 87

//Constructor construye una lista vacia con un nombre de Listpublic Cola(){ 

this ("Lista");}//Constructor

  public Cola (String s){Nombre = s;

    PrimerNodo = UltimoNodo =null;}//Retorna True si Lista Vaciapublic boolean VaciaLista() {

return PrimerNodo == null;}//Inserta un Elemento al Frente de la Listapublic void InsertaInicio (NodoBinario ElemInser){

if(VaciaLista())     PrimerNodo = UltimoNodo = new NodosListaA (ElemInser);    else     PrimerNodo = new NodosListaA (ElemInser, PrimerNodo);}//Inserta al Final de la Listapublic void InsertaFinal(NodoBinario ElemInser){

if(VaciaLista())        PrimerNodo = UltimoNodo = new NodosListaA (ElemInser);    else        UltimoNodo=UltimoNodo.siguiente =new NodosListaA (ElemInser);}//Eliminar al Iniciopublic void EliminaInicio(){

if(VaciaLista())      System.out.println ("No hay elementos");         // Restablecer  las referencias de PrimerNodo y UltimoNodo  if(PrimerNodo.equals (UltimoNodo))     PrimerNodo = UltimoNodo = null;    else     PrimerNodo = PrimerNodo.siguiente;}//Elimina al finalpublic void EliminaFinal (){    if(VaciaLista())      System.out.println ("No hay elementos");    

// Restablecer  las referencias de PrimerNodo y UltimoNodoif (PrimerNodo.equals (UltimoNodo))

     PrimerNodo = UltimoNodo = null;    else{     NodosListaA Actual =PrimerNodo;

while (Actual.siguiente != UltimoNodo)

Page 88: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 88

Actual = Actual.siguiente;

UltimoNodo =Actual;Actual.siguiente = null;

    }}

} CLASE ARBOLclass Arbol{

Cola Cola = new Cola();NodoBinario Padre;NodoBinario Raiz;//Constructorpublic Arbol(){

Raiz = null;}//Insercion de un elemento en el arbolpublic void InsertaNodo(int Elem){

if(Raiz == null)Raiz = new NodoBinario (Elem);

elseRaiz.InsertaBinario (Elem);

}//Preorden Recursivo del arbolpublic void Preorden (NodoBinario Nodo){

if(Nodo == null)return;

else{System.out.print (Nodo.dato + " ");Preorden (Nodo.Hizq);Preorden (Nodo.Hder);

}}//PostOrden recursivo del arbolpublic void PostOrden (NodoBinario Nodo){

if(Nodo == null)return;

else{PostOrden (Nodo.Hizq);PostOrden (Nodo.Hder);System.out.print (Nodo.dato + " ");

}}//Inorden Recursivo del arbolpublic void Inorden (NodoBinario Nodo){

if(Nodo == null)return;

else{Inorden (Nodo.Hizq);

Page 89: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 89

System.out.print(Nodo.dato + " ");Inorden (Nodo.Hder);

}}

CLASE ARBOL BINARIOclass ArbolBinario{

public static void main (String[]args){Arbol A = new Arbol();A.InsertaNodo (10);A.InsertaNodo (7);A.InsertaNodo (8);A.InsertaNodo (6);A.InsertaNodo (12);A.InsertaNodo (11);A.InsertaNodo (5);A.InsertaNodo (4);A.InsertaNodo (3);A.InsertaNodo (2);System.out.print("El recorrido en Preorden es: ");A.Preorden (A.Raiz);System.out.println();System.out.print("El recorrido en Inorden es: ");A.Inorden (A.Raiz);System.out.println();System.out.print("El recorrido en Postorden es: ");A.PostOrden (A.Raiz);System.out.println();System.out.println("La altura del arbol es: " + A.Altura (A.Raiz));A.Anchura (A.Raiz);

}}SALIDA POR CONSOLAEl recorrido en Preorden es: 10 7 6 5 4 3 2 8 12 11 El recorrido en Inorden es: 2 3 4 5 6 7 8 10 11 12 El recorrido en Postorden es: 2 3 4 5 6 8 7 11 12 10 La altura del arbol es: 6El recorrido en Anchura es: 10 7 12 6 8 11 5 4 3 2 

Page 90: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 90

9 ÁRBOLES BINARIOS DE BÚSQUEDA (ABB)Un árbol binario de búsqueda es aquel que dado un nodo, todos los datos del subárbol izquierdo son menores que los datos de ese nodo, mientras que todos los datos del subárbol, derecho son mayores que sus propios datos. También, se denominan arboles binarios de búsqueda, debido a que se pueden buscar en ellos un valor utilizando un algoritmo de búsqueda binaria similar al empleado en arrays.Los árboles de búsqueda se pueden utilizar como diccionarios y como colas de prioridad.

Propiedad de un árbol búsqueda binaria

Sea x un nodo en un árbol de búsqueda binaria. Si y es un nodo del sub-árbol izquierdo de x, entonces la clave de y tiene que ser ≤ a la clave de x. Si z es un nodo del sub-árbol derecho de x, entonces la clave de x tiene que ser ≤ a la clave de z.

La propiedad del árbol de búsqueda nos permite imprimir o recorrer sus nodos en el orden de sus claves haciendo uso de un simple algoritmo recursivo.

Ejemplo:Construya un árbol binario de búsqueda para la siguiente lista de números: 65, 75, 30, 4, 41, 85.

Árbol binario de búsqueda para nodos con el campo de datos de tipo int.

30 menor que 5541 mayor que 3075 mayor que 5585 mayor que 754 menor que 30

Claves y valores

Si los árboles binarios de búsqueda están ordenados, deben estarlo según alguna clave incluida en cada nodo del árbol.

Un nodo puede contener únicamente la clave, pero suele resultar útil permitir que cada nodo contenga una clave y un valor. Pueden ser de cualquier clase que desee, pero todos los nodos deben contener claves y valores que sean instancias de la misma clase.

La clave se utiliza para analizar el nodo. El valor es un dato adicional del nodo indexado por la clave.

Las estructuras de datos con pares clave/valor suelen recibir el nombre de mapas.

Como ejemplo, consideramos las entradas de una agenda de teléfonos tal como se insertarían en un árbol binario de búsqueda. El apellido del abonado sería la clave y el número de teléfono sería el valor.

55

75

85

41

30

4

Page 91: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 91

Una ventaja fundamental de los árboles de búsqueda es que son en general mucho más rápidos para localizar un elemento que una lista enlazada. Por tanto, son más rápidos para insertar y borrar elementos.

Si el árbol está perfectamente equilibrado esto es, la diferencia entre el número de nodos del subárbol izquierdo y el número de nodos del subárbol derecho es a lo sumo 1, para todos los nodos- entonces el número de comparaciones necesarias para localizar una clave es aproximadamente de logN en el peor caso.

Además, el algoritmo de inserción en un árbol binario de búsqueda tiene la ventaja sobre los arrays ordenados, donde se emplearía búsqueda dicotómica para localizar un elemento de que no necesita hacer una reubicación de los elementos de la estructura para que esta siga ordenada después de la inserción.

Dicho algoritmo funciona avanzando por el árbol escogiendo la rama izquierda o derecha en función de la clave que se inserta y la clave del nodo actual, hasta encontrar su ubicación. El algoritmo de borrado en árboles es algo más complejo, pero más eficiente que el de borrado en un array ordenado.

Eficacia de la búsqueda binaria

• Parece intuitivo pensar que las operaciones básicas del árbol binario de búsqueda deberían requerir un tiempo O (h), donde h es la altura del árbol.

• Pero se deduce que la altura de un árbol binario equilibrado es, aprox., log2(n), donde n es el número de elementos si el árbol permanece equilibrado.

• Se puede demostrar que, si las claves se insertan aleatoriamente en un árbol binario de búsqueda, esta condición se cumplirá y que el árbol permanecerá lo suficientemente equilibrado para que la hora de búsqueda y de inserción sea aproximadamente O (log n).

Creación de un árbol binario de búsqueda

Para crear un árbol binario de búsqueda consideramos el siguiente ejemplo:

Se desea almacenar los números 8, 3, 1, 20, 10, 5, 4 en un árbol binario de búsqueda. Siguiendo la regla, dado un nodo en el árbol todos los datos a su izquierda deben ser menores que todos los datos del nodo actual, mientras que todos los datos a la derecha deben ser mayores que el nodo actual; inicialmente el nodo están vacío y se desea insertar el 8. La única opción es almacenar el nodo en la raíz:

A continuación viene el 3, ya que tres es menor que ocho, el 3 debe ir en el subárbol izquierdo:

8

8

3

Page 92: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 92

A continuación se debe insertar 1, ya que es menor que 8 y que 3, irá a la izquierda y debajo de 3.

El siguiente número es 20, mayor que 8, por lo tanto irá a la derecha de éste número:

Cada nuevo elemento se inserta como una nueva hoja del árbol. El resto de elementos se pueden situar fácilmente, lo cual se muestra en las siguientes figuras:

Nodo de un árbol binario de búsqueda NO difiere en nada de los nodos de un árbol binario, tiene un campo de datos y dos punteros a los subárboles izquierdo y derecho respectivamente.

8

3

1

20

8

3

1

20

8

3

1 10

10

20

8

3

1 5

10

20

8

3

1 5

4

Page 93: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 93

Operaciones en un ABB1. Insertar un nodo

Una característica fundamental que debe poseer el algoritmo de inserción es que el árbol resultante de una inserción en un árbol de búsqueda también ha de ser de búsqueda. El algoritmo de inserción se apoya en la localización de un elemento, de modo que si se encuentra el elemento (clave) buscado, no es necesario hacer nada, en caso contrario se inserta el nuevo elemento justo en el lugar donde se acabado la búsqueda(Es decir donde hacia estado en el estado de existir).La intersección de un nuevo nodo en un árbol de búsqueda siempre se hace como nodo hoja. Para ello se baja por el árbol según el camino de búsqueda.

Por ejemplo: supongamos que queremos construir un ABB a partir del conjunto de enteros {10, 5, 14, 7,12} aplicando reiteradamente el proceso de inserción. El resultado es el que muestra la figura

2. Función de insertar

Se debe declarar dos argumentos un puntero a la raíz del árbol y el dato que tendrá el nodo. La función creara un nuevo nodo y lo inserta en el lugar correcto en el árbol de modo que el árbol permanezca como binario de búsqueda. Los pasos a seguir son:1.- Asignar memoria para una nueva estructura nodo.2.- Buscar en el árbol para encontrar la posición de intersección del nuevo nodo, que se colocara como nodo hoja.3.- Enlazar el nuevo nodo al árbol.

3. Eliminación

La operación de borrado si resulta ser algo más complica debido a que el elemento a borrar puede ser cualquier. Se recuerda que el árbol debe seguir siendo de búsqueda tras el borrado. Pueden darse tres casos, una vez encontrado el nodo a borrar:

Page 94: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 94

Caso 1: Borrar un nodo sin hijos ó nodo hoja : simplemente se borra y se establece a nulo el apuntador de su padre.

Antes Después

Ejemplo: En el árbol de ejemplo, borrar el nodo 3.

1. Localizamos el nodo a borrar, al tiempo que mantenemos un puntero a 'Padre'.

2. Hacemos que el puntero de 'Padre' que apuntaba a 'nodo', ahora apunte a NULL.

3. Borramos el 'nodo'.

Caso 2: El nodo es una hoja o tiene al menos un descendiente por una sola rama: Se borra dicho nodo, y su primer descendiente se asigna como hijo del padre del nodo borrado es decir asignar el enlace del nodo padre.

En el árbol se borra el nodo cuya clave es -1. El árbol resultante es:

Antes Después

Page 95: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 95

Ejemplo: En el árbol de ejemplo, borrar el nodo 4.

1. Localizamos el nodo a borrar ('raíz'). 2. Buscamos el nodo más a la derecha del árbol izquierdo de 'raíz', en este

caso el 3, al tiempo que mantenemos un puntero a 'Padre' a 'nodo'. 3. Intercambiamos los elementos 3 y 4. 4. Hacemos que el puntero de 'Padre' que apuntaba a 'nodo', ahora apunte

a NULL. 5. Borramos el 'nodo'.

Caso 3: Borrar un nodo con dos subárboles hijo no vacías: para mantener la estructura de árbol se pueden seguir dos alternativas:

1. Reemplazar el dato del nodo por la menor de las claves mayores en su subárbol derecho.

2. Reemplazar el dato del nodo por la mayor de las clases menores en su subárbol izquierdo. Se elige la segunda para lo cual como las claves menores están en la rama izquierda, se baja al primer nodo de la rama izquierda, y como la clave mayor está en la rama derecha, se continúa bajando por la rama derecha hasta alcanzar el nodo hoja. Este es el mayor de los menores que reemplaza a la clave del nodo a eliminar.

3. El nodo tiene al menos un descendiente por cada rama. Al borrar dicho nodo es necesario mantener la coherencia de los enlaces, además de seguir manteniendo la estructura como un árbol binario de búsqueda. La solución consiste en sustituir la información del nodo que se borra por el de una de las hojas, y borrar a continuación dicha hoja. ¿Puede ser cualquier hoja? No, debe ser la que contenga una de estas dos claves: la mayor de las claves menores al nodo que se borra. Suponer que se

quiere borrar el nodo 4 del árbol Se sustituirá la clave 4 por la clave 2.

la menor de las claves mayores al nodo que se borra. Suponer que se quiere borrar el nodo 4 del árbol. Se sustituirá la clave 4 por la clave 5.

Page 96: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 96

Más ejemplos:

1. Eliminar el 5 2. Buscamos en menor de las claves mayores.

3. Intercambiamos el valor, y enlazamos el descendiente derecho.

Finalmente el árbol queda así:

Otro Ejemplo: En éste borraremos el elemento 6.

1. Localizamos el nodo a borrar ('raíz'). 2. Buscamos el nodo más a la izquierda del árbol derecho de 'raíz', en este caso

el 12, ya que el árbol derecho no tiene nodos a su izquierda, si optamos por la rama izquierda, estaremos en un caso análogo. Al mismo tiempo que mantenemos un puntero a 'Padre' a 'nodo'.

3. Intercambiamos los elementos 6 y 12. 4. Ahora tenemos que repetir el bucle para el nodo 6 de nuevo, ya que no

podemos eliminarlo.

Page 97: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 97

5. Localizamos de nuevo el nodo a borrar ('raíz'). 6. Buscamos el nodo más a la izquierda del árbol derecho de 'raíz', en este caso

el 16, al mismo tiempo que mantenemos un puntero a 'Padre' a 'nodo'. 7. Intercambiamos los elementos 6 y 16. 8. Hacemos que el puntero de 'Padre' que apuntaba a 'nodo', ahora apunte a

NULL. 9. Borramos el 'nodo', observamos los pasos indicados en la siguiente figura.

Antes Después

Los recorridos en un ABB, es similar que en los árboles binarios

Implementación de Arboles BB

CLASE NODOpublic class NodoArbol {    //miembros de acceso del paquete    NodoArbol nodoIzquierdo;    int datos;    NodoArbol nodoDerecho;    //inicializar datos y hacer de este nodo un nodo hoja    public NodoArbol(int datosNodo){        datos = datosNodo;        nodoIzquierdo = nodoDerecho = null; // el nodo no tiene hijos    }    public NodoArbol(){        datos = 0;        nodoIzquierdo = nodoDerecho = null; // el nodo no tiene hijos    }    //localzar punto de inserccion e insertar nuevo nodo; ignorar valores duplicados    public synchronized void insertar(int valorInsertar){        //insertar en subarbol izquierdo        if (valorInsertar < datos){            //insertar nuevo NodoArbol            if (nodoIzquierdo == null){                nodoIzquierdo = new NodoArbol(valorInsertar);            } else  //continuar recorriendo subarbol izquierdo                nodoIzquierdo.insertar(valorInsertar);        }        //insertar en subarbol derecho        else if(valorInsertar > datos){            //insertar nuevo nodoArbol            if (nodoDerecho == null)

Page 98: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 98

                nodoDerecho = new NodoArbol(valorInsertar);            else//continuar recorriendo subarbol derecho                nodoDerecho.insertar(valorInsertar);        }    }//fin del metodo insertar}//fin de la clase nodoArbol

CLASE ARBOL

public class Arbol {    public NodoArbol raiz;    //construir un objeto arbol vacio de enteros    public Arbol(){        raiz = null;    }    //insertar un nuevo nodo en el arbol de busqueda binaria    public synchronized void insertarNodo(int valorInsertar ){        if (raiz == null)            raiz = new NodoArbol(valorInsertar); //crear el nodo raiz aqui        else            raiz.insertar(valorInsertar); //llamar al metodo insertar    }    //empezar recorrido preorden    public synchronized void recorridoPreorden(){        ayudantePreorden(raiz);    }    //metodo recursivo para realizar rrecorrido postorden        private void ayudantePreorden(NodoArbol nodo) {        if(nodo==null){            return;        }        System.out.print(nodo.datos+" ");//mostrar datos del nodo        ayudantePreorden(nodo.nodoIzquierdo);//rrecorrer subarbol izquierdo                ayudantePreorden(nodo.nodoDerecho);//rrecorrer subarbol Derecho    }    //empezar rrecorrido inorden    public synchronized void recorridoInorden() {                ayudanteInorden(raiz);    }    //metodo recursivo para realizar rrecorrido inorden        private void ayudanteInorden(NodoArbol nodo) {                if(nodo==null){            return;        }        ayudanteInorden(nodo.nodoIzquierdo);//rrecorrido subarbol izquierdo        System.out.print(nodo.datos +" "); //mostrar datos del nodo        ayudanteInorden(nodo.nodoDerecho);  //rrecorrer subarbol derecho    }    //iniciar rrecorrido postorden    public synchronized void recorridoPostorden() {        ayudantePostorden(raiz);

Page 99: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 99

    }    //metodo recursivo para realizar rrecorrido postorden        private void ayudantePostorden(NodoArbol nodo) {        if(nodo==null){            return;        }        ayudantePostorden(nodo.nodoIzquierdo);//recorren subarbol izquierdo        ayudantePostorden(nodo.nodoDerecho);//recorren subarbol Derecho        System.out.print(nodo.datos +" "); //mostrar datos del nodo    }    public synchronized void ayudanteliminar(int dato){        eliminar(dato,this.raiz);    }    NodoArbol aux= this.raiz;    NodoArbol aux1= this.raiz;    public void eliminar(int dato,NodoArbol r){        if (r == null){            System.out.println("nodo no encontrado");        }else{            if(dato<r.datos){                if(r.nodoIzquierdo!=null){                    if(r.nodoIzquierdo.datos==dato){                        aux=r;                    }                }                eliminar(dato,r.nodoIzquierdo);            }else if(dato>r.datos){                if(r.nodoDerecho!=null){                    if(r.nodoDerecho.datos==dato){                        aux1=r;                    }                }                eliminar(dato,r.nodoDerecho);            } else {                NodoArbol q;                q=r;                if(q.nodoDerecho==null && q.nodoIzquierdo==null){                    if(aux!=null){                        aux.nodoIzquierdo=null;                    }else if(aux1!=null){                        aux1.nodoDerecho=null;                    }                }else{                    reemplazar(q);                }                aux=this.raiz;                aux1=this.raiz;                System.out.println("se ha eliminado el elemento ");            }        }            }    public void reemplazar(NodoArbol at ){        NodoArbol a ,b;        b=at ;

Page 100: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 100

        a=at.nodoIzquierdo;        while(a.nodoDerecho!=null){            b=a;            a=a.nodoDerecho;        }        at.datos=a.datos;                if(b==at){            b.nodoIzquierdo=a.nodoIzquierdo;        }else            b.nodoDerecho=a.nodoIzquierdo;        at=a;    }}

//este programa prueba la clase arbol

package arbol;

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class PruebaArbol  {    public static void main(String []args)throws IOException{        InputStreamReader teclado=new InputStreamReader(System.in);        BufferedReader lec=new BufferedReader(teclado);        Arbol arbol=new Arbol();        int valor;        System.out.println("Ingrese un numero de elementos para el arbol");        int num=Integer.parseInt(lec.readLine());        System.out.println("insertando los siguientes valores");        //insertar 10 enteros aleatorios del 0 al 99 en arbol       for(int i=0;i<num;i++){           valor=(int)(Math.random()*100);            if(i==0){                System.out.println("raiz: "+valor);            }           System.out.print(valor+"  ");           arbol.insertarNodo(valor);       }        System.out.println("\n\nRcorrido preorden");        arbol.recorridoPreorden();//realizar recorrido preorden de arbol        System.out.println("\n\nRcorrido Inorden");        arbol.recorridoInorden();//realizar recorrido inorden de arbol        System.out.println("\n\nRcorrido postorden");        arbol.recorridoPostorden();//realizar recorrido postorden de arbol        boolean sigue=true;        do{            System.out.println("ingrese un numero a eliminar");            int nomb=Integer.parseInt(lec.readLine());            arbol.eliminar(nomb,arbol.raiz);            System.out.println("\n\nRcorrido Inorden");            arbol.recorridoInorden();//realizar recorrido inorden de arbol            System.out.println("desea eliminar mas nodos");            String str=lec.readLine();

Page 101: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 101

            if(str.equals("no")){                sigue=false;            }        }while(sigue);    }    }//fin de la clase prueba arbol 

9.1 Árboles balanceadosSe considera que un árbol binario esta balanceado cuando todos sus niveles, excepto el ultimo, están integrados a la máxima capacidad de nodos.

Las investigaciones respecto a esta estructura de datos no han logrado encontrar una técnica eficiente para manejar árboles de búsqueda completamente balanceados; las propuestas han llegado solo a presentar árboles parcialmente balanceados, sin repercutir en la eficiencia de las operaciones de inserción y eliminación de nodos.

La más común y usada de las técnicas es la de los árboles AVL.

Arbol AVL

Un árbol AVL es un árbol binario de búsqueda que trata de mantenerse lo más balanceado posible, conforme se realizan operaciones de inserción y eliminación.

Fueron propuestos en 1962 por los matemáticos rusos Adelson-Velskii y Landis, de donde surge su nombre.

Su contribución principal consistió en presentar algoritmos eficientes de inserción y eliminación de elementos considerando un balanceo en el árbol que, a su vez, repercute en la eficiencia de las búsquedas.

Formalmente, en los árboles AVL se debe cumplir el hecho de que para cualquier nodo del árbol, la diferencia entre las alturas de sus subárboles no exceda una unidad

La especificación del TDA árbol AVL es idéntica a la del TDA árbol binario (ABB), y sólo se considera un cambio en las postcondiciones de las operaciones de INSERTAR y BORRAR para obtener un árbol que cumpla con las restricciones de altura ya explicadas.

Page 102: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 102

TDA: ARBOL AVLElementos: guarda un conjunto de nodos. Cada uno de ellos contienen un dato homogéneo (simple o estruturado) único en el árbol.Estructura: La organización de los datos es una estructura en forma jerárquica o de niveles, restringiendo la relación de uno a dos como máximo, cumpliendo un orden y equilibrio.Dominio: Depende de la aplicaciónOPERACIONES: - INSERCIÓN

Inicialmente, el proceso de inserción de un elemento en un árbol AVL es idéntico al de un ABB: se busca la posición en el árbol en que el nuevo elemento quede como un nodo hoja (puesto que el nuevo nodo es hoja, tendrá un FB igual a cero).Una vez hecha la inserción como si fuera un ABB, se deberá verificar si afecta el balanceo del árbol, según las reglas de los AVL. El mejor de los casos será cuando el nuevo nodo no provoque un desbalanceo, implicando sólo la modificación de los FB de los ancestros al nuevo nodo. El otro caso será cuando ocurra un desbalanceo que obligue a hacer movimientos de apuntadores y de FB para balancearlo.La forma de detectar algorítmicamente en qué caso se hará o no un balanceo en el AVL, se basa en la búsqueda de un nodo pivote. Un nodo pivote es aquel que tiene un FB diferente de cero y es el más cercano de los ancestros del nodo recién insertado. Basados en este concepto, se pueden detectar los siguientes casos:

1. El árbol AVL carece de nodo pivote. Esto significa que todos los ancestros del nuevo nodo tienen un PB igual a cero. En este caso, el nuevo nodo no desbalancea el árbol y sólo se tendrán que ajustar los valores de los FB de todos los ancestros, volviéndose positivos o negativos, según el valor del nuevo elemento.

2. El árbol AVL tiene nodo pivote y el nuevo se ha insertado en el subárbol más pequeño del pivote . En este caso tampoco habrá desbalanceo, pues se igualan las alturas de los dos subárboles del nodo pivote, y sólo se tendrán que ajustar los FB de los ancestros que están a partir del nodo pivote, volviéndose positivos o negativos según el valor del nuevo elemento.

3. El árbol AVL tiene nodo pivote y en el subárbol más grande de éste se inserta el nuevo nodo. En este caso se desbalancea el árbol a partir del nodo pivote y tendrá que realizarse un balanceo.

Page 103: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 103

- ELIMINACIÓN Para eliminar un nodo de un árbol AVL se aplica inicialmente el algoritmo ya conocido para dar de baja un nodo en un ABB normal. Físicamente, este algoritmo sólo da de baja nodos que tienen un hijo o ninguno. Para el caso en que el nodo tiene dos hijos, se hace una sustitución con algún nodo que no tenga hijos o que tenga uno, aplicando el método de ‘el mayor de los menores’, o el de “el menor de los mayores”.Una vez dado de baja el nodo correspondiente, pueden ocurrir dos situaciones:1. El nodo que se borró no provocó un desbalanceo en el árbol; en este caso, sólo se ajustan algunos

factores de balance.2. El nodo que se borró provocó un desbalanceo en el árbol; en este caso, tendrán que ajustarse

algunos apuntadores a través de rotaciones y algunos factores de balance. A diferencia del procedimiento de inserción de un nodo, ahora no se utilizará un nodo pivote, pues una baja puede ocasionar un desbalanceo total en el árbol y más de una rotación.

Al dar de baja un nodo se tendrá que analizar el balanceo de todos los ancestros de la ruta de búsqueda, desde el padre del nodo borrado, hasta el nodo raíz del árbol. Esto se debe a que pueden modificarse las alturas de los subárboles por el balanceo.

Factor de balanceo FB o Factor de Equilibrio FELos nodos de un árbol AVL guardan un valor entre 1 y -1, lo que se conoce como Factor de Balance (FB), y representa la diferencia entre las alturas de sus subárboles.

Un FB igual a cero en un nodo significa que las alturas de sus subárboles son iguales;

Un FB positivo significa que el subárbol derecho es más grande que el izquierdo, y

Un FB negativo que el subárbol izquierdo es más grande que el derecho.

Propiedad de los de arboles AVL

La propiedad de equilibrio: que debe cumplir un árbol para ser AVL asegura que la profundidad del árbol sea O(log(n)), por lo que las operaciones sobre estas estructuras no deberán recorrer mucho para hallar el elemento deseado. Como se verá, el tiempo de ejecución de las operaciones sobre estos árboles es, a lo sumo O (log(n)) en el peor caso, donde n es la cantidad de elementos del árbol. Sin embargo, y como era de esperarse, esta misma propiedad de equilibrio de los árboles AVL implica una dificultad a la hora de insertar o eliminar elementos: estas operaciones pueden no conservar dicha propiedad.

Page 104: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 104

Balanceo en un arbol AVLAdelson-Velskii y Landis detectaron que, ante un problema de desbalance, todos los casos podían resolverse aplicando uno de los cuatro esquemas sencillos de balanceo; a estos esquemas los llamaron rotaciones (por la forma en que se mueven los nodos), y consisten en modificar los apuntadores de ciertos nodos, según el esquema, junto con algunos FB.

Lo más valioso de esta propuesta es que el balanceo afecta sólo los nodos que forman parte del subárbol, cuya raíz es el nodo pivote, dejando intactos los nodos del resto del árbol.

El esquema de la rotación simple, que puede ser izquierda (RSI) o derecha (RSD) implica el movimiento de tres apuntadores y El esquema de la rotación doble, que también puede ser izquierda (RDI) o derecha (RDD), implica el movimiento de cinco apuntadores.

Tipos de rotaciones

1. Rotación simple a la derecha (RD): Para ello debe cumplir con las siguientes condiciones:

El subárbol izquierdo de un nodo sea 2 unidades más alto que el derecho, es decir, cuando su FE sea de -2.

Y además, la raíz del subárbol izquierdo tenga una FE de -1, es decir, que esté cargado a la izquierda.

Ejemplo:Se inserta el número 17 a la izquierda del 22.

Page 105: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 105

2. Rotación simple a la izquierda (RI): Para ello debe cumplir con las siguientes condiciones:

El subárbol derecho de un nodo sea 2 unidades más alto que el izquierdo, es decir, cuando su FE sea de 2.

Y además, la raíz del subárbol derecho tenga una FE de 1, es decir, que esté cargado a la derecha.

Ejemplo:Se insertara el número 3 a la derecha del nodo 2.

3. Rotación doble derecha Izquierda (DI) : Para ello se debe considerar lo siguiente: Cuando el subárbol izquierdo de un nodo sea 2 unidades más alto que el

derecho, es decir, cuando su FE sea 2. Y además, la raíz del subárbol derecho tenga una FE de -1, es decir, que

esté cargado a la izquierda.

Ejemplo:Se inserta el número 39 a la izquierda del 48

Page 106: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 106

4. Rotación doble Izquierda Derecha (ID) : Se observa las siguientes condiciones: Cuando el subárbol derecho de un nodo sea 2 unidades más alto que el

izquierdo, es decir, cuando su FE sea -2. Y además, la raíz del subárbol izquierdo tenga una FE de 1, es decir, que

esté cargado a la derecha.Ejemplo:Se inserta el número 71 a la derecha del 29

Page 107: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 107

Análisis de eficiencia

El análisis matemático de los algoritmos de inserción y eliminación demuestran que es posible buscar, insertar y eliminar un elemento en un árbol balanceado de n nodos en O (logn) unidades de tiempo.Diversos análisis demuestran que son más frecuentes las rotaciones en las operaciones de inserción que en las de eliminación.Mientras se produce aproximadamente una rotación por cada dos inserciones, se produce una rotación por cada cinco eliminaciones.

Page 108: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 108

10 ALMACENAMIENTO HASH 10.1 Búsqueda mediante transformación de claves hashEs un método de búsqueda que aumenta la velocidad de búsqueda, pero que no requiere que los elementos estén ordenados.Consiste en asignar a cada elemento un índice mediante una transformación del elemento. Esta correspondencia se realiza mediante una función de conversión, llamada 10.1.1 Función hash.La correspondencia más sencilla es la identidad, esto es, al número 0 se le asigna el índice 0, al elemento 1 el índice 1, y así sucesivamente. Pero si los números a almacenar son demasiado grandes esta función es inservible.

Por ejemplo, se quiere guardar en un array la información de los 1000 usuarios de una empresa, y se elige el número de DNI como elemento identificativo. Es inviable hacer un array de 100.000.000 elementos, sobre todo porque se desaprovecha demasiado espacio. Por eso, se realiza una transformación al número de DNI para que nos dé un número menor, por ejemplo coger las 3 últimas cifras para guardar a los empleados en un array de 1000 elementos. Para buscar a uno de ellos, bastaría con realizar la transformación a su DNI y ver si está o no en el array.

La función de hash ideal debería ser biyectiva, esto es, que a cada elemento le corresponda un índice, y que a cada índice le corresponda un elemento, pero no siempre es fácil encontrar esa función, e incluso a veces es inútil, ya que puedes no saber el número de elementos a almacenar. La función de hash depende de cada problema y de cada finalidad, y se pueden utilizar con números o cadenas, pero las más utilizadas son:

• Restas sucesivas: Esta función se emplea con claves numéricas entre las que existen huecos de tamaño conocido, obteniéndose direcciones consecutivas. Por ejemplo, si el número de expediente de un alumno universitario está formado por el año de entrada en la universidad, seguido de un número identificativo de tres cifras, y suponiendo que entran un máximo de 400 alumnos al año, se le asignarían las claves:1998-000 --> 0 = 1998000-19980001998-001 --> 1 = 1998001-19980001998-002 --> 2 = 1998002-1998000...1998-399 --> 399 = 1998399-19980001999-000 --> 400 = 1999000-1998000+400...yyyy-nnn --> n = yyyynnn-1998000+(400*(yyyy-1998))

• Aritmética modular: El índice de un número es resto de la división de ese número entre un número n prefijado, preferentemente primo. Los números se guardarán en las direcciones de memoria de 0 a n-1. Este método tiene el problema de que cuando hay n+1 elementos, al menos un índice es señalado por dos elementos (teorema del palomar). A este fenómeno se le llama colisión, y es tratado más adelante. Si el número n es el 13, los números siguientes quedan transformados en:13000000 --> 012345678 --> 713602499 --> 171140205 --> 673062138 --> 6

Page 109: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 109

• Mitad del cuadrado: Consiste en elevar al cuadrado la clave y coger las cifras centrales. Este método también presenta problemas de colisión:123*123 = 15129 --> 51136*136 = 18496 --> 84730*730 = 532900 --> 29301*301 = 90601 --> 06625*625 = 390625 --> 06• Truncamiento: Consiste en ignorar parte del número y utilizar los elementos restantes como índice. También se produce colisión. Por ejemplo, si un número de 8 cifras se debe ordenar en un array de 1000 elementos, se pueden coger la primer, la tercer y la última cifras para formar un nuevo número:13000000 --> 10012345678 --> 13813602499 --> 16971140205 --> 71573162135 --> 715• Plegamiento: Consiste en dividir el número en diferentes partes, y operar con ellas (normalmente con suma o multiplicación). También se produce colisión.

Por ejemplo, si dividimos los número de 8 cifras en 3, 3 y 2 cifras y se suman, dará otro número de tres cifras (y si no, se cogen las tres últimas cifras):13000000 --> 130 = 130+000+0012345678 --> 657 = 123+456+7871140205 --> 118 --> 1118 = 711+402+0513602499 --> 259 = 136+024+9925000009 --> 259=250+000+09

10.1.2 Tratamiento de colisionesPero ahora se nos presenta el problema de qué hacer con las colisiones, qué pasa cuando a dos elementos diferentes les corresponde el mismo índice. Pues bien, hay tres posibles soluciones:

1. Cuando el índice correspondiente a un elemento ya está ocupada, se le asigna el primer índice libre a partir de esa posición. Este método es poco eficaz, porque al nuevo elemento se le asigna un índice que podrá estar ocupado por un elemento posterior a él, y la búsqueda se ralentiza, ya que no se sabe la posición exacta del elemento.

2. También se pueden reservar unos cuantos lugares al final del array para alojar a las colisiones. Este método también tiene un problema: ¿Cuánto espacio se debe reservar? Además, sigue la lentitud de búsqueda si el elemento a buscar es una colisión.

3. Lo más efectivo es, en vez de crear un array de número, crear un array de punteros, donde cada puntero señala el principio de una lista enlazada. Así, cada elemento que llega a un determinado índice se pone en el último lugar de la lista de ese índice. El tiempo de búsqueda se reduce considerablemente, y no hace falta poner restricciones al tamaño del array, ya que se pueden añadir nodos dinámicamente a la lista.

Page 110: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 110

Implementación de la Búsqueda mediante transformación de claves hash

En ésta implementación se aplica la función hash: Aritmética Modular y el método para la resolución de colisiones es la Prueba Lineal o Sondeo Lineal.

//Implementación aplicando la aritmética modularpublic class Hash {    //Atributo    Object [] th;    //Constructor    public Hash(int n){        th=new Object[n];        for(int i=0; i<n;i++){            th[i]=null;        }    }    //Métodos    public void creaTabla(Object[]a, int nmax){        int pos;        for(int i=0; i<a.length;i++){            //Genera la posición del elemento a insertar            //Haciendo uso de una función hash            pos=a[i].hashCode()%nmax;            System.out.println("Elemento :"+a[i]+ " pos = " + pos);            //cuando la función devuelve un valor negativo            if(pos<0){                pos*=­1;            }            if(th[pos]==null){                //Inserta en la tabla sin colisión                th[pos]=a[i];            }else{                while(th[pos]!=null){                    pos++;                    if(pos==th.length){                        pos=0;                    }                }                //Inserta el valor en la tabla hash despues de una colicion                th[pos]=a[i];            }        }        presenta("TABLA HASH",th);    }    public void buscarHash(Object elemb, int nmax){        int e=elemb.hashCode();        if(e<0){            e*=­1;        }        int pos=e%nmax;        if(th[pos]==null){            System.out.print("Elemento no encontrado");        }else{            if(th[pos].equals(elemb)){                System.out.print("Elemento encontrado, "+elemb+ " su posicion es : "+ pos);            }else{

Page 111: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 111

                int j=pos+1;                if(j==th.length){                    j=0;                }                while((th[j]!=elemb)&&(th[j]!=null)&&(j!=pos)){                    j++;                    if(j>=th.length­1){                        j=0;                    }                }                if(th[j].equals(elemb)){                    System.out.print("Elemento encontrado, "+elemb+ " su posicion es : "+ j);                }else{                    System.out.print("Elemento no encontrado");                }            }        }    } public void presenta(String msg,Object a[]){     System.out.print(msg+" [");     for(int i=0; i<=a.length­1;i++){         if(i<a.length­1){            System.out.print(a[i]+",");         }else{            System.out.print(a[i]+"]");         }     }     System.out.print("\n");   }    public static void main(String args[]){        Object l[]= {12,45,76,34,90,45,56,78};        Hash bh=new Hash(l.length*2);        bh.presenta("Elementos a insertar en la Tabla Hash",l);        bh.creaTabla(l,l.length);        bh.buscarHash(34,l.length);    }}CORRIDArun:Elementos a insertar en la Tabla Hash [12,45,76,34,90,45,56,78]Elemento :12 pos = 4Elemento :45 pos = 5Elemento :76 pos = 4Elemento :34 pos = 2Elemento :90 pos = 2Elemento :45 pos = 5Elemento :56 pos = 0Elemento :78 pos = 6TABLA HASH [56,null,34,90,12,45,76,45,78,null,null,null,null,null,null,null]Elemento encontrado, 34 su posicion es : 2BUILD SUCCESSFUL (total time: 0 seconds)

Page 112: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 112

11 GRAFOS 11.1 Introducción

Un grafo es un objeto matemático que se utiliza para representar circuitos, redes, etc. Los grafos son muy utilizados en computación, ya que permiten resolver problemas muy complejos.

Aplicación

Imaginemos que disponemos de una serie de ciudades y de carreteras que las unen. De cada ciudad saldrán varias carreteras, por lo que para ir de una ciudad a otra se podrán tomar diversos caminos. Cada carretera tendrá un coste asociado (por ejemplo, la longitud de la misma). Gracias a la representación por grafos podremos elegir el camino más corto que conecta dos ciudades, determinar si es posible llegar de una ciudad a otra, si desde cualquier ciudad existe un camino que llegue a cualquier otra, etc.

11.2 Representación de grafosUna característica especial en los grafos es que podemos representarlos utilizando dos estructuras de datos distintas. En los algoritmos que se aplican sobre ellos veremos que adoptarán tiempos distintos dependiendo de la forma de representación elegida. En particular, los tiempos de ejecución variarán en función del número de vértices y el de aristas, por lo que la utilización de una representación u otra dependerá en gran medida de si el grafo es denso o disperso.

Analiza: Entre las principales aplicaciones de los grafos tenemos:Circuitos electrónicos, Tarjetas impresas, Circuitos integrados, Redes de transporte, Autopistas, Vuelos, Redes de ordenadores, LANs, Internet, Web, Bases de datos, Diagramas entidad/relación, entre otros…Piensa en otras aplicaciones informáticas de la vida real, en donde se utilice la estructura: Grafo, comenta con tus compañeros y con tu profesora…..!!!

Analiza: Entre las principales aplicaciones de los grafos tenemos:Circuitos electrónicos, Tarjetas impresas, Circuitos integrados, Redes de transporte, Autopistas, Vuelos, Redes de ordenadores, LANs, Internet, Web, Bases de datos, Diagramas entidad/relación, entre otros…Piensa en otras aplicaciones informáticas de la vida real, en donde se utilice la estructura: Grafo, comenta con tus compañeros y con tu profesora…..!!!

Page 113: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 113

Para nombrar los nodos utilizaremos letras mayúsculas, aunque en el código deberemos hacer corresponder cada nodo con un entero entre 1 y V (número de vértices) de cara a la manipulación de los mismos.

11.3 Conceptos Elementales

1. Vértice ( Vertex ): Un punto o un nodo de un grafo. 2. Arco ( Edge ): Una línea que une un vértice con otro vértice del mismo grafo, en

grafos no direccionados, o una fecha que une dos vértices del mismo grafo, en grafos direccionados.

3. Cabeza ( Head ): En grafos direccionados, es el vértice donde llega la flecha. 4. Cola ( Tail ): En grafos direccionados, es el vértice desde donde sale la fecha. 5. Vértices Adjacentes ( Adjancent Edges ): Son dos vértices que están unidos por un

arco. 6. Arcos Incidentes ( Incident Edges ): Son los arcos que inciden en un determinado

vértice.

11.4 Clasificación de los Grafos:1. Según el tipo y cantidad de arcos

o Grafo No Direccionado ( Undirected Graph ): Son grafos donde los arcos unen un par de vértices desordenados. Así, el par (v1,v2) y el (v2,v1) representa el mismo arco.

o Grafo ( Graph ) : Es un sinónimo de grafo no direccionado. Los grafos no direccionados, normalmente se los llama grafos a secas.

o Grafo Completo ( Completed Graph ) : Es un grafo no direccionado donde existe un arco entre cada par de vértices cualesquiera del mismo. El número máximo de arcos que puede tener un grafo de n vértices es n * ( n - 1 ) / 2.

o Grafo Direccionado ( Directed Graph ): Son grafos donde los arcos unen un par de vértices ordenados. Así, el par [v1,v2] y [v2,v1] representan arcos distintos. En el caso del arco [v1,v2], v1 es la cola del arco y v2 en la cabeza. Los arcos de un grafo direccionado se representan con flechas.

Page 114: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 114

o Digrafo ( Digraph ): Es un sinónimo de grafo direccionado.

o Digrafo Completo ( Completed Digraph ): Es un grafo direccionado donde existe un arco entre cada dos vertices cualesquiera del mismo, tanto el que va desde un vértice al otro, como el que retorna. El número máximo de arcos que puede tener un digrafo de n vértices es n * ( n - 1 ).

o Multigrafo ( Multigraph ) : Se aceptan más de un arco uniendo dos vertices. En términos formales, no son grafos.

o Subgrafo ( Subgraph ): Un subgrafo de G es un grafo G', tal que V(G') está incluido en V(G) y E(G') está incluido en E(G).

2. Según la conectividad o Componentes Conectados ( Connected Component ): Tiene distinto

significado según se trate de grafos direccionados o no direccionados.

o Fuertemente Conectado ( Strongly Connected ): Tiene distinto significado según se trate de grafos direccionados o no direccionados.

11.5 Conceptos vinculados al grado

Grado de un Vértice ( Vertex Degree ): Es el número de arcos que inciden sobre el vértice.

Grado Entrante de un Vértice ( Vertex In Degree ): Es el número de arcos para los cuales el vértice es la cabeza.

Grado Saliente de un Vértice ( Vertex Out Degree ): Es el número de arcos para los cuales el vértice es la cola.

Conceptos vinculados al paso

Paso ( Path ): El paso desde un vértice vp a un vértice vq, en un grafo G, es una secuencia de vértices vp, vi1, vi2, ..., vin, vq, tal que (vp,vi1), (vi1,vi2), ..., (vin,vq) son arcos en E(G). Si G es un grafo direccionado, el paso consiste de [vp,vi1], [vi1,vi2], ..., [vin,vq], arcos en E(G).

Paso Simple ( Simple Path :) Es un paso, donde todos los vértices, excepto, posiblemente, el primero y el último, son distintos.

Paso Ciclo ( Cycle Path ): Es um paso simple, donde el primero y último vértice es el mismo vértice.

Longitud del Paso ( Path Length ): El número de vértices en un paso.

11.6 Representación de grafos1. Matriz de adyacencias

Son matrices cuadradas de tantas filas y columnas como vértices tenga el grafo a representar. En las celdas de la matriz se indica si existe un arco entre los vértices que determinan la celda. Un grafo G = (V;A) se representa como G: matriz[V; V ] de boléanos. La componente G [u; v] es 1 si (u; v) 2 A; sino G[u; v] = 0.

Page 115: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 115

Memoria grafos densos

Tiempo de acceso: Lista adyacentes: Lista incidentes:

2. Listas de adyacencia Partiendo de los nodos de cada vértice, evoluciona una lista que informa los nodos que son adyacentes del inicial.

Un grafo G = (V;A) se representa como un vector de listas de vértices indexado por vértices; es decir, G: vector[V ] de V . Cada componente G[v] es una lista de los vértices emergentes y/o incidentes de/a v 2 V.

Memoria: grafos dispersos

Tiempo de acceso: O(grado(G)). Lista adyacentes: O (grado(G)). (Lista incidentes: O(grado(G)) con listas de incidencia.)

Page 116: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 116

11.7 Recorridos o exploración de grafos

A la hora de explorar un grafo, nos encontramos con dos métodos distintos. Ambos conducen al mismo destino (la exploración de todos los vértices o hasta que se encuentra uno determinado), si bien el orden en que éstos son "visitados" decide radicalmente el tiempo de ejecución de un algoritmo, como se verá posteriormente.

En primer lugar, una forma sencilla de recorrer los vértices es mediante una función recursiva, lo que se denomina búsqueda en profundidad. La sustitución de la recursión (cuya base es la estructura de datos pila) por una cola nos proporciona el segundo método de búsqueda o recorrido, la búsqueda en amplitud o anchura.

Page 117: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 117

Suponiendo que el orden en que están almacenados los nodos en la estructura de datos correspondiente es A-B-C-D-E-F... (el orden alfabético), tenemos que el orden que seguiría el recorrido en profundidad sería el siguiente:

A-B-E-I-F-C-G-J-K-H-D

En un recorrido en anchura el orden sería, por contra:

A-B-C-D-E-G-H-I-J-K-F

Es destacable que el nodo D es el último en explorarse en la búsqueda en profundidad pese a ser adyacente al nodo de origen (el A). Esto es debido a que primero se explora la rama del nodo C, que también conduce al nodo D.

En estos ejemplos hay que tener en cuenta que es fundamental el orden en que los nodos están almacenados en las estructuras de datos. Si, por ejemplo, el nodo D estuviera antes que el C, en la búsqueda en profundidad se tomaría primero la rama del D (con lo que el último en visitarse sería el C), y en la búsqueda en anchura se exploraría antes el H que el G.

Recorrido y Búsqueda Primero en Profundidad

Se implementa de forma recursiva, aunque también puede realizarse con una pila. Seutiliza un array val para almacenar el orden en que fueron explorados los vértices.

Para ello se incrementa una variable global id (inicializada a 0) cada vez que se visita un nuevo vértice y se almacena id en la entrada del array val correspondiente al vértice que se está explorando.

Sus pasos a seguir serían:

Visitar vértice inicial vi Visitar vértice adyacente a vi ... proceder así hasta encontrar uno ya visitado... Volver atrás hasta llegar a un vértice con adyacentes sin visitar El recorrido termina cuando volviendo atrás llegamos al vértice inicial vi y no

quedan adyacentes por recorrer

Page 118: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 118

Ejemplo de recorrido primero en profundidad:

Recorrido y Búsqueda Primero en Anchura

La diferencia fundamental respecto a la búsqueda en profundidad es el cambio de estructura de datos: una cola en lugar de una pila.

Sus pasos a seguir son: Visitar vértice inicial vi Visitar todos los vértices adyacentes a vi Al terminar, comenzar a visitar los adyacentes a los adyacentes a vi ... proceder así hasta que no queden vértices por visitar

Page 119: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 119

Ejemplo de recorrido primero en anchura:

Page 120: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 120

Implementación de Grafos: Algoritmo Prim

PROBLEMA:Descripción del problema

Dado un grafo conectado y no dirigido, su árbol abarcador mínimo es un subgrafo en forma de árbol que mantiene la conectividad del grafo y tal que la suma de los pesos de las ramas seleccionadas es mínimo. El algoritmo de Prim resuelve este problema en tiempo polinómico mediante una estrategia voraz(esto es, seleccionar en cada paso lo que más convenga). Las aplicaciones de los árboles abarcadores mínimos son múltiples: obtención de redes eléctricas o de comunicaciones eficientes, creación de laberintos aleatorios, solución aproximada de problema del viajante (TSP - Traveling Salesman Problem), etc.

Solución al problema Para lograr este objetivo, hemos utilizado un algoritmo voraz, que empezará seleccionando la arista de menor coste partiendo de un nodo inicial, es decir el camino de menor recorrido desde un nodo determinado. Luego repetirá dicho proceso seleccionando una nueva arista hasta que todos los nodos sean visitados. Cada uno de estas nuevas aristas será la de menor peso entre las que no estén repetidas y, por lo tanto, permitirá el acceso a un nodo nuevo.El grafo creado para probar el funcionamiento del algoritmo es de cinco nodos y está representado por una matriz de memoria estática. Dicha matriz se inicializa en su totalidad con un valor muy grande (Integer.MaxValue) para que los pesos conocidos de antemano sean menores a dicho valor y el algoritmo funcione correctamente.El algoritmo está implementado en el cuerpo del método caminoMinimo, el cuál ante una invocación en la que se especifique como parámetro real el nodo de partida, devolverá un vector de enteros cuyos valores se irán modificando a medida que se obtengan nuevos caminos de coste menor a los calculados en iteraciones anteriores.Por otra parte, para asegurarse de que un nodo no se repita, se hará uso del método estaRepetido, que recibe como parámetro el vector donde se va almacenando la solución y un número a buscar dentro de dicho vector. La llamada a dicho método retorna verdadero en caso de que el nodo ya forme parte del recorrido y falso en caso contrario.

IMPLEMENTACIÓN DE GRAFOSPara la implementación se ha considerado, empezar con el camino de menor coste repetir seleccionar un nuevo camino hasta que esté completa una red que conecte todos los nodos.

package algoritmoprim; public class Camino {  // Matriz bidimensional de enteros que representa el grafo.  private int grafo[][];   public Camino(int caminos[][]) {    grafo = caminos;  }

Page 121: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 121

   /**   * Método que recorre un vector para comprobar si se encuentra en él un valor   * recibido.   * @param Vector de enteros donde va almacenando la solución.   * @param i Número a buscar dentro del vector.   * @return Devuelve true si lo encuentra.   */  private boolean estaRepetido(int vector[], int i) {    for (int j = 0; j < vector.length; j++) {      if (vector[j] == i) {        return true;      }    }    return false;  }   /**   * Método que recorre el grafo y almacena el camino mínimo en un vector.   * @param inicio Valor que representa el nodo donde comienza el recorrido.   * @return El camino minimo en un vector de enteros.   */  public int[] caminoMinimo(int inicio) {    int numNodos = grafo.length;    int minimo[] = new int[numNodos];    // Inicializar el vector de mínimos a ­1 (para el caso del nodo cero).    for (int i = 0; i < minimo.length; i++) {      minimo[i] = ­1;    }    int longitudCamino = 0;    int menor = 0;    int actual = inicio;    minimo[0] = inicio;    while (longitudCamino < (numNodos ­ 1)) {      // Encontrar el camino mínimo al siguiente nodo      for (int i = 0; i < numNodos; i++) {        if ( (grafo[actual][i] < grafo[actual][menor]) &&            (!estaRepetido(minimo, i))) { // Para evitar repetir nodos.          menor = i;          // Ahora, el nodo siguiente es el del camino mínimo anterior.        }      }      longitudCamino++;      actual = menor;      minimo[longitudCamino] = actual;    }    return minimo;  }   /**   * Método main de la clase Camino donde se crea el grafo utilizado para el   * ejemplo.   * @param args String Parametros de la clase   */  public static void main(String args[]) {

Page 122: Guia Edoo2012

Estructuras de Datos Orientada a Objetos Septiembre/12-Marzo/13 122

    // Vector de soluciones:    int solucion[];    // Crear un grafo de cinco vértices representado por una matriz:    int grafo[][] = new int[5][5];    // Inicializar la matriz representando el grafo:    for (int i = 0; i < 5; i++) {      for (int j = 0; j < 5; j++) {        grafo[i][j] = Integer.MAX_VALUE;      }    }    // Rellenar el grafo con las siguientes aristas con sus respectivos pesos:    grafo[0][1] = 30;    grafo[1][0] = 30;    grafo[0][2] = 15;    grafo[2][0] = 15;    grafo[0][3] = 80;    grafo[3][0] = 80;    grafo[1][2] = 10;    grafo[2][1] = 10;    grafo[1][3] = 60;    grafo[3][1] = 60;    grafo[1][4] = 45;    grafo[4][1] = 45;    grafo[2][3] = 50;    grafo[3][2] = 50;    grafo[2][4] = 25;    grafo[4][2] = 25;    grafo[4][3] = 40;    grafo[3][4] = 40;    // Instancia de la clase camino.    Camino c = new Camino(grafo);    // Encontrar el camino mínimo (empieza desde el nodo 0).    solucion = c.caminoMinimo(0);    // Mostrar el árbol mínimo abarcador. System.out.print("\nÁRBOL MÍNIMO ABARCADOR ­­> Solución: ");    for (int i = 0; i < 5; i++) { // n­1 aristas entre n nodos.      System.out.print(solucion[i] + " ");    }  }}

Tiempo de ejecuciónPara calcular la complejidad del algoritmo lo que hicimos fue obtener el Tiempo de Ejecución (T(n)), separando las operaciones básicas (de duración constante) obteniéndose: T(n) = 11 n² + 8.

Por lo tanto, eliminando las constantes sabemos que la complejidad del algoritmo es O(n²).