Está en la página 1de 79

Programaci on II

Apuntes de c atedra

n 1.3 Versio

Cuadrado Estrebou, Mar a Fernanda Trutner, Guillermo Hern an

Facultad de Ingenier a y Ciencias Exactas

Universidad Argentina de la Empresa

2 El objetivo de este apunte es el de ser una gu a en el dictado de la materia, junto a las explicaciones de los docentes en las clases. Se encuentra en su primera versi on y es por eso que agradeceremos todas las observaciones, comentarios y correciones que nos puedan hacer llegar los alumnos para ir mejor andolo.

Resumen El objetivo del curso de Programaci on II es introducir el concepto de tipos de datos abstractos (TDA), sus especicaciones, implementaciones y aplicaciones. Se utilizar a el lenguaje de programaci on Java como lenguaje de soporte, remarcando que no es el objetivo del curso el lenguaje en s mismo, sino s olo un medio para aplicar los contenidos. Comenzaremos a trabajar con estructuras de datos conocidas por los alumnos de cursos previos, como son las pilas y colas entre otras y continuaremos con otras estructuras m as complejas como son los arboles y grafos.

Indice General
1 Introducci on a Lenguaje Java 1.1 Tipos de datos . . . . . . . . 1.2 Variables . . . . . . . . . . . . 1.3 Operadores . . . . . . . . . . 1.3.1 Aritm eticos . . . . . . 1.3.2 Relacionales . . . . . . 1.3.3 L ogicos . . . . . . . . . 1.4 Estructuras de control . . . . 1.4.1 Bloques . . . . . . . . 1.4.2 Secuencia . . . . . . . 1.4.3 Condicional Simple . . 1.4.4 Condicional m ultiple . 1.4.5 Ciclos . . . . . . . . . 1.5 Arreglos . . . . . . . . . . . . 1.6 Paquetes y salida . . . . . . . 1.7 M etodos . . . . . . . . . . . . 1.8 Clases . . . . . . . . . . . . . 6 6 7 7 7 8 8 9 9 9 9 10 10 12 13 13 15 18 18 19 19 20 21 22 23 25 27 28 28 29 31

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

2 TDA: conceptos y especicaci on 2.1 Tipos de Datos Abstractos (TDA): Denici on 2.2 Especicaci on de un TDA . . . . . . . . . . . 2.3 TDA con estructura lineal . . . . . . . . . . . 2.3.1 Pila . . . . . . . . . . . . . . . . . . . 2.3.2 Cola . . . . . . . . . . . . . . . . . . . 2.3.3 Cola con Prioridad . . . . . . . . . . . 2.3.4 Conjunto . . . . . . . . . . . . . . . . 2.3.5 Diccionario . . . . . . . . . . . . . . . 2.4 Resumen . . . . . . . . . . . . . . . . . . . . .

3 Implementaci on 3.1 Implementaci on de Tipos de Datos Abstractos . . . . . . . . . . . 3.1.1 Implementaci on de PilaTDA . . . . . . . . . . . . . . . . . 3.1.2 Implementaci on de ColaTDA . . . . . . . . . . . . . . . . 4

INDICE GENERAL 3.1.3 Implementaci on de ColaPrioridadTDA 3.1.4 Implementaci on de ConjuntoTDA . . . 3.1.5 Implementaci on de Diccionario . . . . 3.2 An alisis de Costos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5 33 36 37 40 43 43 44 45 46 48 49 54 55 58 58 59 61 61 62 62 64 66 67 69 69 71 72

4 Implementaci on con estructuras din amicas 4.1 Implementaciones din amicas . . . . . . . . . . . . . . . . . . . . 4.1.1 Pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.2 Cola . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.3 Cola con Prioridad . . . . . . . . . . . . . . . . . . . . . 4.1.4 Conjuntos . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.5 Diccionarios . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Comparaci on de costos entre implementaciones . . . . . . . . . . 4.3 Resoluci on de problemas combinando TDAs e implementaciones 5 Arboles 5.1 Conceptos . . . . . . . . . . . . . . . 5.2 TDA Arbol . . . . . . . . . . . . . . 5.3 Arboles binarios . . . . . . . . . . . . 5.4 Recursividad . . . . . . . . . . . . . . 5.5 Arboles Binarios de B usqueda (ABB) 5.5.1 Especicaci on . . . . . . . . . 5.5.2 Implementaci on . . . . . . . . 5.5.3 Recorridos . . . . . . . . . . . 5.5.4 Utilizaci on . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6 Grafos 6.1 Conceptos b asicos . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Especicaci on del TDA . . . . . . . . . . . . . . . . . . . . . . . . 6.3 Implementaciones est aticas y din amicas . . . . . . . . . . . . . . .

Unidad 1 Introducci on a Lenguaje Java


En esta unidad se introducir an los conceptos del lenguaje Java que se van a necesitar a lo largo del curso. No es este un curso para aprender a programar en este lenguaje sino que es un curso en que se lo va a utilizar como herramienta para ejercitar todos los conceptos vistos. Uno de los aspectos importantes a tener en cuenta antes de comenzar, es que el lenguaje es sensible a may usculas y min usculas, es decir se deben utilizar las variables y los m etodos tal cual fueron denidos.

1.1

Tipos de datos

Los tipos de datos b asicos en Java que se van a utilizar a lo largo del curso, son los siguientes: boolean: los valores posibles que pueden tomar las variables de este tipo son true o false u nicamente int: valores enteros que tienen un tama no de 32 bits short: valores enteros que tienen un tama no de 16 bits char: representa a un car acter, y tiene un tama no de 16 bits byte: representa a 8 bits float: es un valor num erico con decimales con un tama no de 32 bits long: es un valor num erico con decimales con un tama no de 64 bits double: es un valor num erico con decimales con un tama no de 64 bits

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION

1.2

Variables

Otro aspecto a considerar es c omo se lleva a cabo la declaraci on de variables en Java, y las mismas pueden ser de la siguiente manera: declaraci on de una variable sola:
<tipo> <nombre_variable> ;

por ejemplo:
int cantidad;

declaraci on de m as de una variable del mismo tipo:


<tipo> <nombre_variable_1>,<nombre_variable_2>,<nombre_variable_3>;

por ejemplo:
int cantidad, contador, resultado;

declaraci on y asignaci on de valor a una variable:


<tipo> <nombre_variable> = <valor>;

por ejemplo:
int contador = 0;

o para el caso de variables del tipo char se debe usar para el valor entre :
char c =f;

Como se vi o en algunos de los ejemplos anteriores para la asignaci on de valores a una variable se utiliza el operador = (por ejemplo: variable = 5). El alcance de la variable est a dado por el bloque en el que se declara. Una variable es visible dentro del bloque en el que fue declarada y dentro de todos los sub-bloques que se denan dentro de este.

1.3
1.3.1

Operadores
Aritm eticos

Las operaciones aritm eticas b asicas sobre n umeros son las siguientes: Para indicar que un n umero es negativo se usa el s mbolo - (por ejemplo -5). Este mismo s mbolo es utilizado tambi en para la operaci on de resta (por ejemplo x = x - 8;). +: operador de suma. *: operador de multiplicaci on.

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION /: operador de divisi on.

%: operador de resto o m odulo, es decir, devuelve el resto de una divisi on (por ejemplo x % 2; el resultado de esta operaci on es 1 si el n umero es impar y 0 si el n umero par). ++: operador de incremento en uno (por ejemplo si tenemos int x = 2; x++;, entonces el valor que toma x es 3). --: operador de decremento en uno (por ejemplo si tenemos int x = 2; x--;, entonces el valor que toma x es 1).

1.3.2

Relacionales

Las operaciones de comparaci on b asicas sobre n umeros son las siguientes: <: operador menor, es decir, si tenemos x < z, la comparaci on devolver a true si x tiene un valor menor que el de z, y false en caso contrario. >: operador mayor, es decir, si tenemos x > z, la comparaci on devolver a true si x tiene un valor mayor que el de z, y false en caso contrario. <=: operador menor o igual, es decir, si tenemos x <= z, la comparaci on devolver a true si x tiene un valor menor o igual que el de z, y false en caso contrario. >=: operador mayor o igual, es decir, si tenemos x >= z, la comparaci on devolver a true si x tiene un valor mayor o igual que el de z, y false en caso contrario. ==1: operador de igualdad, es decir, si tenemos x == z, la comparaci on devolver a true si x tiene un valor igual que el de z, y false en caso contrario. !=: operador distinto, es decir, si tenemos x != z, la comparaci on devolver a true si x tiene un valor distinto que el de z, y false en caso contrario.

1.3.3

L ogicos

Adem as, de las operaciones sobre n umeros est an las operaciones sobre valores l ogicos: !: operador de negaci on, es decir, si tenemos !valor2 , la comparaci on devolver a true si el valor que tiene valor es falso, y false en caso contrario.
Tener especial cuidado de no omitir un signo =, ya que el lenguaje lo tomar a como una asignaci on y no dar a error pero cambiar a el signicado o comportamiento de la operaci on 2 valor debe ser una expresi on de tipo booleano
1

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION ||: operador O l ogico. &&: operador Y l ogico.

1.4

Estructuras de control

Dentro de las instrucciones b asicas veremos la notaci on para secuencia, el condicional, condicional m ultiple y algunos operadores de ciclos.

1.4.1

Bloques

En Java, los bloques de sentencias se delimitan con llaves ({ y }). Se comienza un bloque con una llave de apertura y se naliza con una llave de cierre. En muchos de los casos, si el bloque contiene una u nica sentencia, se pueden omitir las llaves, aunque para evitar errores y malos entendidos, se recomienda utilizarlas siempre. La identaci on se utilizar a a modo simb olico para facilitar la lectura del c odigo, sin embargo el compilador lo ignora totalmente.

1.4.2

Secuencia

Para la separaci on de secuencias de instrucciones se utiliza ;.

1.4.3

Condicional Simple

El condicional simple se utiliza para validar una condici on, y seg un sea verdadera o falsa se ejecuta un bloque de sentencias.
i f (< condicio n _ b o le a na >) { instruccio n 1; instruccio n 2; instruccio n 3; ... } else { instruccio n 4; instruccio n 5; instruccio n 6; ... }

El else en el condicional es opcional. En caso de no utilizar las llaves para armar un bloque de instrucciones, la primera instrucci on ser a la que forme parte del if o else y las siguientes quedan fuera del condicional.

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION

10

1.4.4

Condicional m ultiple

Para las evaluaciones de diferentes condiciones para un mismo valor se puede utilizar el switch. La condici on de evaluaci on en un switch tiene que ser un valor entero (o una expresi on cuya evaluaci on da como resultado un valor entero).
switch ( < e x p r e s i o n _ en t er a >) { cas e v a l o r 1: instruccio n 1; instruccio n 2; ... break ; cas e v a l o r 2: instruccio n 3; instruccio n 4; ... break ; cas e v a l o r 3: instruccio n 5; instruccio n 6; ... break ; default : instruccio n 7; instruccio n 8; ... }

En cada case es aconsejable colocar un break, debido a que si no se coloca un break el lenguaje sigue evaluando las condiciones de los siguientes case, y en caso de que otro sea verdadero tambi en lo ejecuta. Adem as, si la sentencia switch tiene el default y no se coloca un break en cada case, luego de ejecutar el case correspondiente siempre va a terminar ejecutando lo que esta denido dentro del default.

1.4.5

Ciclos

Para la ejecuci on de ciclos vamos a ver tres instrucciones, while, for y do..while. Las dos primeras se pueden ejecutar como m nimo cero veces, a diferencia del do..while que se ejecuta como m nimo una vez, debido a que primero hace la ejecuci on y luego eval ua la condici on.
wh ile ( < c o n d i c i o n _ bo l e an a >) { expresio n 1; expresio n 2; ... }

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION

11

Si luego de la condici on del while no se colocan las llaves, el lenguaje va a considerar como expresi on de ejecuci on solamente la primera, y no las subsiguientes (este mismo comportamiento es v alido para la sentencia for que describiremos a continuaci on). Otra opci on para un ciclo es el for:
for (< inicializacio n _ va r i a bl e > ; < c o n d i c i o n _ bo l ea n a > ; < variacio n _ v ar i ab l e > ) { expresio n 1; expresio n 2; ... }

La variable que se inicializa y utiliza dentro del for puede ser declarada previo al for o dentro del mismo(como en el ejemplo que sigue). De acuerdo a d onde se declare ser a el alcance que tenga, es decir, si se declara en el mismo for s olo se podr a utilizar en las instrucciones dentro del ciclo del for. La variaci on de la variable puede ser un incremento o un decremento. Un ejemplo de uso del for podr a ser para sumar los n umeros del 1 al 10, con lo cual se har a:
i n t suma = 0; f o r ( i n t i = 1; i <= 10 ; i ++) { suma = suma + i ; }

En este caso tenemos declarada la variable i del for en el mismo, ya que no se requiere fuera del el. Ahora supongamos que estamos buscando un valor en un arreglo de enteros de 20 elementos y queremos conocer no s olo si existe el valor, sino en qu e posici on del mismo, en cuyo caso har amos lo siguiente:
i n t b u s c a r V a l o r ( i n t [] a , i n t v a l o r) { boolean e n c o n t r a d o = f a l s e ; in t i; f o r ( i =0; ( i < 20 && ! e n c o n t r a d o) ; i ++) { i f ( a [ i ]== v a l o r) { e n c o n t r a d o = t r u e; } } i f ( encontrado){ return i -1; } else{ // Se d e v u e l v e un v a l o r f u e r a del a r r e g l o para i n d i c a r que no se e n c o n t r o return -1 ; } }

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION Por u ltimo, nos queda presentar el do..while:
do { instruccio n 1; instruccio n 2: ... } wh ile ( < c o n d i c i o n _ b ol e an a >)

12

El do..while, a diferencia del las otros dos sentencias de ciclos, lo que hace primero es ejecutar las instrucciones y luego eval ua la condici on, con lo cual, al menos una vez se ejecutan todas las instrucciones independientemente del valor de la condici on.

1.5

Arreglos

Luego de haber descripto las diferentes sentencias de ciclos vamos a ver como se declaran y usan los arreglos en Java. Declaraci on La forma de declarar un arreglo es la siguiente:
<tipo_datos_arreglos>[] <nombre_arreglo>;

por ejemplo, si queremos declarar un arreglo de enteros har amos lo siguiente: int[] valores;. Dimensionamiento Los arreglos, por tratarse de una estructura de tama no jo, antes de poder utilizarlos se le debe asignar la cantidad de elementos que va a contener, es decir, dimensionarlo:
<nombre_arreglo> = new <tipo_datos_arreglos>[<dimension>]

La palabra reservada new, se utilizar a en el lenguaje, cada vez que se quiera reservar memoria para una variable que no sea simple. Para los enteros, reales y caracteres, como se ha visto, no es necesario hacer la reserva de memoria, ya que la declaraci on de la variable lleva inmersa la reserva de memoria. Por ejemplo, si al arreglo valores utilizado para ejemplicar en la parte de declaraci on, le queremos decir que va a contener 100 elementos, entonces lo que har amos es:
valores = new int[100];

Otra forma de dimensionar un arreglo, y a su vez inicializarlo con valores es la siguiente:


int[] valores = {5,8,15,20};

en este caso el arreglo toma una dimensi on 4, con los valores 5, 8, 15 y 20 en las posiciones 0, 1, 2 y 3 respectivamente. Utilizaci on

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION

13

Debemos tener en cuenta que los arreglos en Java tienen su primer elemento en la posici on cero, es decir, si declaramos un arreglo de dimensi on 100, lo vamos a poder recorrer desde 0 a 99. A continuaci on se ve un ejemplo de recorrido del arreglo valores para inicializarlo con valores:
f o r ( i n t i = 0; i < 100; i ++) { V a l o r e s [ i ] = i + 2; }

1.6

Paquetes y salida

El lenguaje provee conjuntos de librer as que pueden ser utilizadas dentro de nuestros programas. En Java las librer as se llaman paquetes, y se agrupan en sub-paquetes. Por ejemplo hay un paquete net y dentro del mismo hay un paquete URL. Para hacer referencia entonces a la URL, se utilizar a la notaci on de punto, por ejemplo util.URL y si queremos utilizar una funci on de la librer a, hay que invocar un m etodo dentro de la librer a, por ejemplo para recuperar el contenido de una URL se podr a hacer as : util.URL.getContents() Un paquete particular que vamos a utilizar es el que sirve para imprimir por pantalla. Es el paquete System.out y el m etodo se llama println, entonces para imprimir algo, estos son ejemplos:
i n t n = 3; char c = f ; S y s t e m. out . p r i n t l n ( n ) ; S y s t e m. out . p r i n t l n ( c ) ; S y s t e m. out . p r i n t l n ( " Hola ! " ) ;

1.7

M etodos

Por u ltimo, vamos a ver dos conceptos particulares de los lenguajes orientados a objetos como es el caso de Java, que son los m etodos y clases. El concepto de m etodos y clases que daremos es b asico y no tiene por objetivo dar un conocimiento del paradigma de Orientaci on a Objetos, sino dar las herramientas b asicas para poder trabajar a lo largo del curso. En Java todas las operaciones se llevan a cabo a trav es de m etodos (se puede hacer una similitud a funciones y procedimientos de los lenguajes estructurados) los cuales se declaran de la siguiente manera:
< t i p o _ r e t o r n o _ me t o d o > < n o m b r e _ m e to do >( < t i p o _ p a r am e tr o > < p a r a m et ro 1 > ,... , < t i p o _ p a r am e tr o > < p a r a m e t ro _n >) { instruccion1;

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION


instruccion2; ... }

14

En el caso de que el m etodo no devuelva valor se lo declara del tipo void. Por otra parte, el m etodo puede no contener par ametros, en cuyo caso es igualmente obligatorio colocar los par entesis sin ning un par ametro, es decir, se colocar a:
< t i p o _ r e t o r n o _m e t od o > < n o m b r e _ me t od o >() { instruccion1; instruccion2; ... }

A continuaci on daremos dos ejemplos de m etodos, el primero devolver a un valor que es la suma de dos variables que se dan como par ametro, y el segundo ser a un m etodo que no devuelve valor sino que imprime por pantalla los valores de un arreglo dado. Ejemplo 1: Suma de dos valores dados
i n t s u m a r( i n t x , i n t y ) { i n t sum = 0; sum = x + y ; return sum ; }

Esto se puede escribir de la siguiente manera que da el mismo resultado, es decir, son formas equivalentes de decir los mismo:
i n t s u m a r( i n t x , i n t y ) { return ( x + y ) ; }

Ejemplo 2: impresi on por pantalla de los elementos de un arreglo de dimensi on 10.


void i m p r i m i r A r r e g l o ( i n t [] a ) { f o r ( i n t i = 0; i < 10; i ++) { S y s t e m. out . p r i n t l n ( a [ i ]) ; } }

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION

15

1.8

Clases

Luego de haber hablado de los m etodos, nos resta describir el concepto de clases. En los lenguajes Orientados a Objetos siempre vamos a estructurar nuestros programas o sistemas mediante clases. Las clases las podr amos comparar a las estructuras de los lenguajes estructurados, aunque la denici on correcta de las clases es que son la denici on de un objeto, en donde un objeto representa a alguna entidad de la vida real (por ejemplo, un objeto puede ser una persona, una casa, un auto, una formula, etc.). A continuaci on veremos como es la declaraci on y el uso de una clase. Declaraci on Vamos a declarar una clase con sus componentes, esos componentes son variables de la clase y sus m etodos. Para indicar que es una clase se utiliza la palabra reservada del lenguaje class.
c l a s s < n o m b r e _ c la se >{ < t i p o _ v a r ia bl e > < n o m b r e _ v a ri a bl e s >; // v a r i a b l e s de la c l a s e < t i p o _ m e tod o > < n o m b r e _ m et o do > ( < p a r a m e t r o s _ me t od o >) { instruccio n 1; instruccio n 2; ... } }

Como ejemplo, vamos a declarar una clase punto, en donde tenemos dos componentes que representan las coordenadas x e y del punto:
c l a s s Punto{ in t x; in t y; }

Uso de clases como variables El uso de las clases es similar al uso de los tipos primitivos, es decir, se debe declarar una variable del tipo de la clase:
<nombre_clase> <nombre_variable>;

Por ejemplo, si queremos declarar una variable p del tipo Punto debemos hacer:
Punto p;

Y luego antes de poder usar cualquier variable cuyo tipo sea una clase (es decir, no sea una variable de tipo primitivo) se le debe asignar memoria de la siguiente manera:
<nombre_variable> = new <nombre_clase>();

Continuando con el ejemplo de la variable p del tipo Punto, para asignar memoria har amos lo siguiente:

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION


p = new Punto();

16

Cabe aclarar que la declaraci on de una variable y su asignaci on de memoria se puede hacer en una misma instrucci on de la siguiente manera:
<class_name> <nombre_variable> = new <nombre_clase>();

Utilizando lo mencionado anteriormente en nuestro ejemplo nos quedar a:


Punto p = new Punto();

Por u ltimo, nos resta ver como podemos acceder a los componentes de las clases, es decir, las variables3 y m etodos. Para ello se utiliza el punto . de la siguiente manera:
<nombre_variable>.<nombre_componente>

Es decir, si queremos asignarles valores a las coordenadas x e y del punto p lo que har amos es lo siguiente:
p.x = 5; p.y = 10;

En lo referido a m etodos y variables que hemos venido trabajando, existe el concepto de alcance o visibilidad de los m etodos y variables, y es lo que nos permite indicar si una m etodo o variable podr a ser utilizado por qui en usa esa clase o no. Es decir, si un m etodo o variables es privado solo se podr a utilizar dentro de la clase, en cambio si es p ublico podr a ser utilizado tanto dentro de la clase como por qui en usa esa clase. Para indicar que un m etodo o variable es p ublico se utiliza la palabra reservada del leguaje public, y para indicar si es privado la palabra private (por defecto si no se indica nada el lenguaje considera que la variable o m etodo es privada). Supongamos el siguiente ejemplo para mostrar lo mencionado anteriormente:
c l a s s Persona{ S t r i n g n o m b r e; String apellido; S t r i n g c a l l e; i n t n u m e r o; S t r i n g c i u d a d; p u b lic void s e t e a r N o m b r e ( S t r i n g n , S t r i n g a ) { nombre = n; apellido = a; } p u b lic void s e t e a r D i r e c c i o n ( S t r i n g c , i n t n , S t r i n g ciu ) { Calle = c; Numero = n; C i u d a d = ciu ; } } Debemos tener en cuenta que no hemos introducido el concepto de m etodos privados y p ublicos hasta el momento, ya que s olo podr amos acceder desde afuera si el m etodo es p ublico. Este concepto se va a ver en los pr oximos p arrafos. No se ver a en el curso el concepto de variables o m etodos protegidos
3

A LENGUAJE JAVA UNIDAD 1. INTRODUCCION

17

Tenemos una clase que representa una persona, que tiene un nombre, apellido, la calle, n umero y ciudad en donde vive. Para asignarle el nombre y el apellido a la persona tenemos un m etodo p ublico y para asignarle la calle, n umero y ciudad otro. Estos dos m etodos ser an p ublicos y se deber an ser utilizados por qui en usa la clase, pero las variables en donde guardamos esos valores no podr an ser accedidas por qui en usa la clase con lo cual ser an privadas. Para el ejemplo se utilizar a un tipo de dato provisto por Java que es String que simboliza una cadena de caracteres y se puede imprimir como vimos anteriormente.

Unidad 2 TDA: conceptos y especicaci on


En este cap tulo vamos a introducir el concepto de TDA, qu e son, c omo se denen y c omo se utilizan. Vamos a introducir tambi en la notaci on en lenguaje de programaci on que vamos a utilizar. Para los ejemplos, vamos a utilizar los TDA Pila, Cola, Cola con Prioridad, Conjunto y Diccionario.

2.1

Tipos de Datos Abstractos: Denici on

Ya hemos denido en cursos anteriores los conceptos de Tipo de Dato y de Estructura de Dato. Vamos a recordar sus deniciones para poder introducir el nuevo concepto, que ser a el eje de la materia. Cuando hablamos del tipo de dato de una variable, nos referimos al conjunto de valores que puede tomar una variable, y el conjunto de operaciones que se pueden aplicar sobre el mismo. Por ejemplo si tomamos el tipo de dato int sabemos que el conjunto de valores que puede tomar son todos los enteros y el conjunto de operaciones ser an la suma, resta, multiplicaci on, divisi on y todas las dem as que permita el lenguaje utilizado. Se los puede clasicar seg un su contenido en simples o estructurados, seg un contenga un u nico valor o un conjunto de valores. Ejemplos de tipos simples son enteros, reales, caracteres, etc. Ejemplos de estructurados pueden ser arreglos o las estructuras de C. Si son estructurados, se pueden clasicar en homog eneos o heterog eneos seg un sus elementos sean de un mismo tipo(por ejemplo arreglos) o de diferentes tipos (por ejemplo estructuras). Tambi en podr amos clasicarlos en predenidos por el lenguaje o denidos por el usuario. Una estructura de datos es una denici on que se realiza utilizando los mecanismos propuestos por el lenguaje, que permite almacenar un conjunto de valores. Seg un la estructura denida ser a la forma de accederlas. Un tipo de dato abstracto (TDA) es un tipo de dato seg un lo explicado m as arriba, donde el concepto de abstracci on est a asociado al modo en que se denen los TDA. Este modelo estar a formado por las operaciones que tiene y el comportamiento

18

UNIDAD 2. TDA: CONCEPTOS Y ESPECIFICACION

19

asociado a esas operaciones, es decir, estar a centrado en qu e hace el TDA y no c omo lo hace, es decir, la abstracci on signica el ocultamiento del c omo.

2.2

Especicaci on de un TDA

Como dijimos en la denici on de TDA, vamos a separar qu e hace un TDA de c omo lo hace. Y para entender esta diferencia, veremos c omo se pueden denir TDA y utilizarlos sin necesidad de conocer c omo se hace cada una de las operaciones. De hecho, para una misma denici on de TDA puede haber diferentes maneras de realizar lo denido por ese TDA. A la denici on del TDA la llamaremos especicaci on y a la forma de llevar a cabo lo denido por un TDA lo denominaremos implementaci on. Por lo tanto, para un mismo TDA vamos a tener diferentes implementaciones. La notaci on de Java que utilizaremos para especicar TDA es la notaci on de interfaces. Para especicar el TDA Ejemplo, notaremos:
p u b lic i n t e r f a c e E j e m p l o T D A { }

Para especicar una operacion de un TDA utilizaremos un prototipo de un m etodo en Java, que incluye el nombre de la operaci on, los par ametros que recibe con su tipo, y el tipo de dato que retornan. Adem as, se incluir a un comentario de lo que hace la operaci on, si no queda claro del nombre y las precondiciones de la misma. Por ejemplo:
p u b lic i n t e r f a c e E j e m p l o T D A { // D e s c r i p c i o n de la a c c i o n que t i e n e el m e todo i n t m e t o d o 1( i n t a , i n t b ) ; }

2.3

TDA con estructura lineal

Vamos a comenzar a especicar TDA con comportamientos ya conocidos de cursos previos para entender el concepto, para luego avanzar con nuevas estructuras. Durante todo el curso, vamos a suponer que el conjunto de valores que se almacenar an en las diferentes estructuras ser an enteros. Esto no es una restricci on de los TDA ni tampoco del lenguaje, sino una forma de simplicar la codicaci on.

UNIDAD 2. TDA: CONCEPTOS Y ESPECIFICACION

20

2.3.1

Pila

El primer TDA a especicar ser a el tipo de dato abstracto que describe el comportamiento de una estructura pila. La pila es una estructura que permite almacenar conjuntos de valores, eliminarlos y recuperarlos, con la particularidad de que el elemento que se recupera o elimina es el u ltimo que ingres o. Por lo tanto, para poder denir el comportamiento de la pila vamos a utilizar la siguiente lista de operaciones: Apilar: permite agregar un elemento a la pila. Se supone que la pila est a inicializada. Desapilar: permite eliminar el u ltimo elemento agregado a la pila. Se supone como precondici on que la pila no est e vac a. Tope: permite conocer cu al es el u ltimo elemento ingresado a la pila. Se supone que la pila no est a vac a. PilaVac a: indica si la pila contiene elementos o no. Se supone que la pila est a inicializada. InicializarPila: permite inicializar la estructura de la pila. Luego de listar las operaciones del TDA pila vamos a describir el mismo con Java :
p u b lic i n t e r f a c e P i l a T D A { void I n i c i a l i z a r P i l a () ; // s i e m p r e que la pila est e void A p i l a r( i n t x ) ; // s i e m p r e que la pila est e void D e s a p i l a r () ; // s i e m p r e que la pila est e boolean P i l a V a c i a () ; // s i e m p r e que la pila est e i n t Tope () ; }

inicializada i n i c i a l i z a d a y no est e vac a inicializada i n i c i a l i z a d a y no est e vac a

A continuaci on vamos a realizar un ejemplo en donde utilizaremos la PilaTDA denida anteriormente. En el ejemplo, vamos a pasar los elementos de una pila origen a una pila destino, en donde se perder an los elementos de la pila origen y en la pila destino quedar an esos elementos en orden inverso a la origen.
p u b lic void P a s a r P i l a ( P i l a T D A origen , P i l a T D A d e s t i n o ) { wh ile (! o r i g e n . P i l a V a c i a () ) { d e s t i n o. A p i l a r( o r i g e n. Tope () ) ; o r i g e n. D e s a p i l a r () ; } }

UNIDAD 2. TDA: CONCEPTOS Y ESPECIFICACION

21

Otro ejemplo de utilizaci on de la PilaTDA, es si queremos escribir un m etodo que nos devuelva la suma de los valores que contiene la pila. En este caso el m etodo va a retornar un valor del tipo int.
p u b lic i n t S u m a r E l e m e n t o s P i l a ( P i l a T D A p ) { i n t suma = 0; wh ile (! p . P i l a V a c i a () ) { suma = suma + p . Tope () ; p . D e s a p i l a r () ; } return suma ; }

2.3.2

Cola

Luego de haber introducido el concepto de TDA, y para ello utilizar la estructura pila, ahora vamos a ver otra estructura que es la cola. Una cola es una estructura que nos permite almacenar valores, recuperar y eliminar el primer valor ingresado, adem as de que nos permite conocer si la cola tiene o no elementos. Por lo tanto, si analizamos la diferencia en cuanto al comportamiento de una pila y una cola, esa diferencia esta dada en la forma en que recuperan y eliminan los valores en cada estructura. A continuaci on vamos a listar las operaciones, junto a sus comportamientos, que nos permite especicar el TDA de una cola: Acolar: permite agregar un elemento a la cola. Se supone que la cola est a inicializada. Desacolar: permite eliminar el primer elemento agregado a la cola. Se supone como precondici on que la cola no est e vac a. Primero: permite conocer cu al es el primer elemento ingresado a la cola. Se supone que la cola no est a vac a. ColaVac a: indica si la cola contiene elementos o no. Se supone que la cola est a inicializada. InicializarCola: permite inicializar la estructura de la cola. Es decir, el tipo de dato abstracto ColaTDA nos quedar a de la siguiente manera:
p u b lic i n t e r f a c e C o l a T D A { void I n i c i a l i z a r C o l a () ; // s i e m p r e que la cola est e inicializada void A c o l a r( i n t x ) ; // s i e m p r e que la cola est e i n i c i a l i z a d a y no est e vac a

UNIDAD 2. TDA: CONCEPTOS Y ESPECIFICACION


void D e s a c o l a r () ; // s i e m p r e que la cola est e inicializada boolean C o l a V a c i a () ; // s i e m p r e que la cola est e i n i c i a l i z a d a y no est e vac a i n t P r i m e r o () ; }

22

De la misma manera que utilizamos como ejemplo pasar los elementos de una pila a otra, ahora vamos a escribir un m etodo que nos permita pasar los elementos de una cola a otra. En este caso particular, a diferencia de las pilas, por el comportamiento particular de las colas, los elementos en la cola destino quedar an en el mismo orden que en la cola origen.
p u b lic void p a s a r C o l a ( C o l a T D A origen , C o l a T D A d e s t i n o ) { wh ile (! c . C o l a V a c i a () ) { d e s t i n o. A c o l a r( o r i g e n. P r i m e r o () ) ; d e s t i n o. D e s a c o l a r () ; } }

2.3.3

Cola con Prioridad

En las secciones anteriores denimos estructuras en donde los elementos se recuperan y eliminan de acuerdo al orden en que hab an ingresado a la estructura, es decir, en el caso de una pila se pod a recuperar o eliminar el u ltimo elemento ingresado, y en el caso de la cola el primero ingresado. En esta secci on vamos a especicar una estructura que a cada elemento cuando ingresa a la misma se le va a asignar una prioridad, y luego los elementos van a ser recuperados o eliminados de la estructura de acuerdo a esa prioridad. A esta estructura la denominaremos cola de prioridad. Este tipo de estructura es utilizado, por ejemplo, en las colas para embarazadas o discapacitados de los supermercados, o en las colas de espera en las guardias de los hospitales, en d onde en este u ltimo caso la prioridad de atenci on al paciente se le da de acuerdo con el s ntoma de problema de salud que haya llegado al hospital. A continuaci on vamos a listar las operaciones, junto a sus comportamientos, que nos permite especicar el TDA de una cola con prioridad: AcolarPrioridad: permite agregar un elemento a la cola con una cierta prioridad dada. Se supone que la cola est a inicializada. Desacolar: permite eliminar el elemento con mayor prioridad en la cola (en caso de tener dos elementos con la misma prioridad sale el primero ingresado). Se supone como precondici on que la cola no est e vac a.

UNIDAD 2. TDA: CONCEPTOS Y ESPECIFICACION

23

Primero: permite conocer cu al es el elemento de mayor prioridad ingresado a la cola (en caso de tener dos elementos con la misma prioridad devuelve el primero ingresado). Se supone que la cola no est a vac a. ColaVac a: indica si la cola contiene elementos o no. Se supone que la cola est a inicializada. Prioridad: permite conocer la prioridad del elemento con mayor prioridad de la cola. InicializarCola: permite inicializar la estructura de la cola. Es decir, el tipo de dato abstracto ColaPrioridadTDA nos quedar a de la siguiente manera:
p u b lic i n t e r f a c e C o l a P r i o r i d a d T D A { void I n i c i a l i z a r C o l a () ; // s i e m p r e que la cola est e inicializada void A c o l a r P r i o r i d a d ( i n t x , i n t p r i o r i d a d ) ; // s i e m p r e que la cola est e i n i c i a l i z a d a y no est e vac a void D e s a c o l a r () ; // s i e m p r e que la cola est e i n i c i a l i z a d a y no est e vac a i n t P r i m e r o () ; // s i e m p r e que la cola est e inicializada boolean C o l a V a c i a () ; // s i e m p r e que la cola est e i n i c i a l i z a d a y no est e vac a i n t P r i o r i d a d () ; }

Podemos establecer las siguientes conclusiones. Si acolamos todos los elementos con la misma prioridad, la cola con prioridad se comporta como una cola com un. Si acolamos todos los elementos con la prioridad igual a su valor, la cola con prioridad puede ordenar autom aticamente los elementos.

2.3.4

Conjunto

El siguiente tipo de dato abstracto que vamos a denir ser a el conjunto. El conjunto es una estructura que nos permite guardar elementos sin que los mismos se repitan y en donde no se tiene un orden, y adem as nos permite conocer si un elemento dado se encuentra o pertenece a la estructura. Debido a que la estructura no tiene un orden, cuando recuperamos un dato la estructura nos devuelve uno cualquiera que pertenece a ella, y por otro lado cuando queremos eliminar una valor debemos indicarle cu al es. A partir de esta descripci on de comportamiento del conjunto, podemos decir que la lista de operaciones que dene el TDA de conjunto es la siguiente: Agregar: permite agregar un elemento al conjunto. Se supone que el conjunto est a inicializado.

UNIDAD 2. TDA: CONCEPTOS Y ESPECIFICACION

24

Sacar: permite eliminar del conjunto un elemento dado. Se supone como precondici on que el conjunto no est a vac o. Elegir: devuelve un elemento cualquiera del conjunto. Se supone como precondici on que el conjunto no est a vac o. Pertenece: permite conocer si un elemento dado se encuentra en el conjunto. Se supone que el conjunto est a inicializado. ConjuntoVac o: indica si el conjunto contiene elementos o no. Se supone que el conjunto est a inicializado. InicializarConjunto: permite inicializar la estructura del conjunto. Es decir, el tipo de dato abstracto ConjuntoTDA nos quedar a de la siguiente manera:
p u b lic i n t e r f a c e C o n j u n t o T D A { void I n i c i a l i z a r C o n j u n t o () ; // s i e m p r e que el c o n j u n t o est e boolean C o n j u n t o V a c i o () ; // s i e m p r e que el c o n j u n t o est e void A g r e g a r( i n t x ) ; // s i e m p r e que el c o n j u n t o est e i n t E l e g i r () ; // s i e m p r e que el c o n j u n t o est e void S a c a r( i n t x ) ; // s i e m p r e que el c o n j u n t o est e boolean P e r t e n e c e ( i n t x ) ; }

inicializado inicializado i n i c i a l i z a d o y no est e vac o inicializado inicializado

Como ejemplo de uso del ConjuntoTDA, supongamos que queremos indicar si dos conjuntos son iguales, entendiendo que dos conjuntos son iguales si tienen los mismos elementos.
p u b lic boolean S o n C o n j u n t o s I g u a l e s ( C o n j u n t o T D A c1 , C o n j u n t o T D A c2 ) { in t elemento; boolean s o n I g u a l e s = t r u e ; wh ile (! c1 . C o n j u n t o V a c i o () && ! c2 . C o n j u n t o V a c i o () && sonIguales){ e l e m e n t o = c1 . E l e g i r () ; i f (! c2 . P e r t e n e c e( e l e m e n t o ) ) { sonIguales = f a l s e ; } else{ c1 . S a c a r ( e l e m e n t o ) ; c2 . S a c a r ( e l e m e n t o ) ; } }

UNIDAD 2. TDA: CONCEPTOS Y ESPECIFICACION


i f ( c1 . C o n j u n t o V a c i o () && c2 . C o n j u n t o V a c i o () ) { return t r u e ; } else{ return f a l s e ; } }

25

2.3.5

Diccionario

El u ltimo tipo de dato abstracto que vamos a denir en esta unidad ser a el diccionario. La estructura de datos diccionario se caracteriza porque cada valor ingresa a la estructura asociado a una clave, y est as claves existen siempre que tengan valor asociado y son u nicas. En el presente curso se van a analizar dos comportamientos diferentes de la estructura diccionario, el primero de ellos ser a en donde cada clave puede tener asociado un u nico valor, estructura que denominaremos DiccionarioSimple, y el segundo en donde cada clave tiene asociado un conjunto de valores, estructura que denominaremos DiccionarioMultiple. Diccionario Simple A continuaci on vamos a listar las operaciones, junto a sus comportamientos, que nos permite especicar el TDA de un diccionario simple: Agregar: dada una clave y un valor, agrega al diccionario el valor quedando asociado a la clave. Si ya existe la misma clave con otro valor se sobreescribe el valor, dejando el nuevo ingresado. Para poder agregar un par clave/valor la estructura debe estar inicializada. Eliminar: dada una clave elimina el valor asociado a la clave, y por consiguiente la clave ya que el diccionario no puede contener claves sin valores asociados. Si la clave no existe no se hace nada. Se supone que el diccionario esta inicializado. Recuperar: dada una clave devuelve el valor asociado a la clave. La clave dada debe pertenecer al diccionario. Se supone que el diccionario esta inicializado. Claves: devuelve el conjunto de todas las claves denidas en el diccionario. Se supone que el diccionario esta inicializado. InicializarDiccionario: permite inicializar la estructura del diccionario. Es decir, el tipo de dato abstracto DiccionarioSimpleTDA nos quedar a de la siguiente manera:

UNIDAD 2. TDA: CONCEPTOS Y ESPECIFICACION


p u b lic i n t e r f a c e D i c c i o n a r i o S i m p l e T D A { // s i e m p r e que el d i c c i o n a r i o est e void I n i c i a l i z a r D i c c i o n a r i o () ; // s i e m p r e que el d i c c i o n a r i o est e void A g r e g a r( i n t clave , i n t v a l o r) ; // s i e m p r e que el d i c c i o n a r i o est e void E l i m i n a r( i n t c l a v e) ; // s i e m p r e que el d i c c i o n a r i o est e c l a v e e x i s t a en el m i s m o i n t R e c u p e r a r( i n t c l a v e) ; // s i e m p r e que el d i c c i o n a r i o est e C o n j u n t o T D A C l a v e s () ; }

26

inicializado inicializado inicializado i n i c i a l i z a d o y la

inicializado

Diccionario M ultiple El diccionario m ultiple tiene como caracter stica principal que cada clave del diccionario puede tener asociado un conjunto de valores. A continuaci on vamos a listar las operaciones, junto a sus comportamientos, que nos permite especicar el TDA de un diccionario m ultiple: Agregar: dada una clave y un valor, agrega al diccionario el valor quedando asociado a la clave. Una misma clave puede tener asociada un conjunto de valores, pero esos valores no se pueden repetir. Para poder agregar un par clave/valor la estructura debe estar inicializada. Eliminar: dada una clave elimina todos los valores asociados a la clave, y por consiguiente la clave ya que el diccionario no puede contener claves sin valores asociados. Si la clave no existe no se hace nada. Se supone que el diccionario esta inicializado. EliminarValor: dada una clave y un valor se elimina el valor asociado a la clave, y en caso de que la clave o el valor no existan no se hace nada. Si al eliminar el valor, la clave no tiene otros valores asociados se debe eliminar la misma. Se supone que el diccionario esta inicializado. Recuperar: dada una clave devuelve el conjunto de valores asociados a la misma. Si la clave dada no pertenece al diccionario, se debe devolver un conjunto vac o. Se supone que el diccionario esta inicializado. Claves: devuelve el conjunto de todas las claves denidas en el diccionario. Se supone que el diccionario esta inicializado. InicializarDiccionario: permite inicializar la estructura del diccionario. Es decir, el tipo de dato abstracto DiccionarioMultipleTDA nos quedar a de la siguiente manera:

UNIDAD 2. TDA: CONCEPTOS Y ESPECIFICACION


p u b lic i n t e r f a c e D i c c i o n a r i o M u l t i p l e T D A { void I n i c i a l i z a r D i c c i o n a r i o () ; // s i e m p r e que el d i c c i o n a r i o est e inicializado void A g r e g a r( i n t clave , i n t v a l o r) ; // s i e m p r e que el d i c c i o n a r i o est e inicializado void E l i m i n a r( i n t c l a v e) ; // s i e m p r e que el d i c c i o n a r i o est e inicializado void E l i m i n a r V a l o r ( i n t clave , i n t v a l o r) ; // s i e m p r e que el d i c c i o n a r i o est e inicializado C o n j u n t o T D A R e c u p e r a r ( i n t c l a v e) ; // s i e m p r e que el d i c c i o n a r i o est e inicializado C o n j u n t o T D A C l a v e s () ; }

27

2.4

Resumen

Durante esta unidad hemos visto el concepto de tipo de dato abstracto, y la denici on y uso de cinco tipos de datos abstractos como son Pila, Cola, Cola con Prioridad, Conjunto y Diccionario (en sus dos variantes, simple y m ultiple). Como mencionamos cuando denimos un TDA, en donde dijimos que el TDA especica el comportamiento de una estructura independientemente de c omo sea la implementaci on, y que por otra parte, bamos a tener diferentes implementaciones para un mismo TDA, estas diferentes implementaciones es lo que vamos a ver en las unidades siguientes.

Unidad 3 Implementaci on
El objetivo de esta unidad es entender el concepto de implementaci on y su clara diferencia con la especicaci on de un TDA. Para eso vamos a ver diferentes implementaciones de los TDA denidos anteriormente, utilizando como estrategia de implementaci on estructuras de tama no jo, es decir, arreglos. Luego de haber realizado las diferentes implementaciones veremos el costo asociado a cada una de las operaciones de cada TDA de acuerdo a la implementaci on realizada.

3.1

Implementaci on de TDAs

Durante esta secci on veremos diferentes implementaciones de PilaTDA, ColaTDA, ColaPrioridadTDA y ConjuntoTDA. Cuando hablamos de implementaci on nos estamos reriendo a que debemos denir los siguientes puntos: En d onde se va a guardar la informaci on De qu e manera se va guardar esa informaci on, es decir, denir el criterio con que se va a guardar y recuperar los datos Escribir / implementar cada una de las operaciones del TDA que se esta implementando En esta secci on las estructuras utilizada para guardar la informaci on van a ser arreglos, lo cual va a tener una restricci on que es que tienen tama no jo. En secciones posteriores veremos otra forma de guardar la informaci on. Para implementar un TDA en Java, vamos a escribir una clase, a la que le indicaremos que es la implementaci on de un TDA con la palabra reservada implements. Luego deniremos la estructura de datos, y por u ltimo, codicaremos cada uno de los m etodos especicados. Si fuera necesario, se podr an agregar m etodos auxiliares, que ser an internos a la clase.

28

UNIDAD 3. IMPLEMENTACION
p u b lic c l a s s C L A S E implements c l a s e T D A { }

29

3.1.1

Implementaci on de PilaTDA

Como hemos expresado en la unidad anterior, para una misma especicaci on de TDA pueden existir diferentes implementaciones, y de hecho, existen muchas. Por ese motivo para PilaTDA vamos a ver algunas posibles estrategias. Estrategia 1: Implementaci on en donde se guardan los datos en un arreglo y adem as se tiene una variable que indica la cantidad de elementos que se tienen guardados en la pila. Cuando agregamos un nuevo elemento a la pila, el mismo se guarda en la posici on indicada por la variable que me indica la cantidad de elementos. Cuando se tiene que desapilar un elemento de la pila, solo es necesario decrementar en una unidad la variable que me indica la cantidad de elementos. Se puede ver el esquema en la gura 3.1.

Figura 3.1: Implementaci on PilaTDA con Tope al Final A continuaci on se muestra el c odigo de esta implementaci on:
p u b lic c l a s s P i l a T F implements P i l a T D A { i n t [] a ; // a r r e g l o en d o n d e se g u a r d a la i n f o r m a c i o n i n t i n d i c e; // v a r i a b l e e n t e r a en d o n d e se g u a r d a la c a n t i d a d de e l e m e n t o s que se t i e n e n g u a r d a d o s p u b lic void I n i c i a l i z a r P i l a () { a = new i n t [ 1 0 0 ] ; i n d i c e = 0; } p u b lic void A p i l a r( i n t x ) { a [ i n d i c e] = x ; i n d i c e ++; } p u b lic void D e s a p i l a r () { indice - -; }

UNIDAD 3. IMPLEMENTACION

30

p u b lic boolean P i l a V a c i a () { return ( i n d i c e == 0) ; } p u b lic i n t Tope () { return a [ indice -1]; } }

Estrategia 2: Otra variante de implementaci on es utilizar tambi en un arreglo para almacenar los datos y tener una variable que indica la cantidad de elementos que se tienen guardados en la pila, pero cuando agregamos un nuevo elemento a la pila, en vez de hacerlo en la posici on se nalada por la variable que me indica la cantidad de elementos, se guarda en la primera posici on (es decir, la posici on 0 del arreglo). Esto tiene como desventaja que cuando se agrega un elemento se debe hacer un corrimiento del resto de los elementos hacia la derecha, y cuando se desapila un elemento de la pila nuevamente se tiene que hacer un corrimiento de elementos pero esta vez hacia la izquierda. Se puede observar que la variante entre esta implementaci on y la anterior no esta dada en la estructura utilizada para guardar los elementos sino en el criterio utilizado para almacenar esa informaci on. A continuaci on se muestra el c odigo de esta implementaci on:
p u b lic c l a s s P i l a T I implements P i l a T D A { i n t [] a ; // a r r e g l o en d o n d e se g u a r d a la i n f o r m a c i o n i n t i n d i c e; // v a r i a b l e e n t e r a en d o n d e se g u a r d a la c a n t i d a d de e l e m e n t o s que se t i e n e n g u a r d a d o s p u b lic void I n i c i a l i z a r P i l a () { a = new i n t [ 1 0 0 ] ; i n d i c e = 0; } p u b lic void A p i l a r( i n t x ) { f o r ( i n t i = indice -1; i >=0; i - -) a [ i +1] = a [ i ]; a [0] = x ; i n d i c e ++; } p u b lic void D e s a p i l a r () { f o r ( i n t i = 0; i < i n d i c e; i ++) a [ i ] = a [ i +1]; indice - -; } p u b lic boolean P i l a V a c i a () {

UNIDAD 3. IMPLEMENTACION
return ( i n d i c e == 0) ; } p u b lic i n t Tope () { return a [0]; } }

31

Estrategia 3: Podemos mencionar otra estrategia de implementaci on en donde variamos la estructura utilizada para guardar la informaci on, es decir, tambi en utilizamos un arreglo pero para guardar la cantidad de elementos que tenemos en vez de hacerlo en una variable utilizamos la posici on 0 del arreglo.

3.1.2

Implementaci on de ColaTDA

De la misma manera que para la estructura de Pila vamos a presentar diferentes estrategias de implementaci on para la estructura Cola. Todas las estrategias de implementaci on se basar an por el momento en estructuras de arreglos. Estrategia 1: Ultimo elemento ingresado a la cola en la posici on inicial del arreglo : Implementaci on en donde se guardan los datos en un arreglo y adem as se tiene una variable que indica la cantidad de elementos que se tienen guardados en la cola. Cuando agregamos un nuevo elemento a la cola, el mismo se guarda en la posici on cero del arreglo, por lo cual se requiere previo a la inserci on un corrimiento a derecha de los elementos que se encuentran en la cola. Cuando se tiene que desacolar un elemento de la cola, solo es necesario decrementar en una unidad la variable que me indica la cantidad de elementos. A continuaci on se muestra el c odigo de esta implementaci on:
p u b lic c l a s s C o l a P U implements C o l a T D A { i n t [] a ; i n t i n d i c e; p u b lic void I n i c i a l i z a r C o l a () { a = new i n t [ 1 0 0 ] ; i n d i c e = 0; } p u b lic void A c o l a r( i n t x ) { f o r ( i n t i = indice -1; i >=0; i - -) a [ i +1] = a [ i ]; a [0] = x ; i n d i c e ++; } p u b lic void D e s a c o l a r () { indice - -; }

UNIDAD 3. IMPLEMENTACION

32

p u b lic boolean C o l a V a c i a () { return ( i n d i c e == 0) ; } p u b lic i n t P r i m e r o () { return a [ indice -1]; } }

Estrategia 2: Primer elemento ingresado a la cola en la posici on inicial del arreglo : Implementaci on en donde se guardan los datos en un arreglo y adem as se tiene una variable que indica la cantidad de elementos que se tienen guardados en la cola. Cuando agregamos un nuevo elemento a la cola, el mismo se guarda en la posici on indicada por la variable que guarda la cantidad de elementos que tiene la cola hasta el momento. Cuando se tiene que desacolar un elemento de la cola se requiere un corrimiento a izquierda en una posici on de los elementos que se encuentran en la cola. A continuaci on se muestra el c odigo de esta implementaci on:
p u b lic c l a s s C o l a P I implements C o l a T D A { i n t [] a ; i n t i n d i c e; p u b lic void I n i c i a l i z a r C o l a () { a = new i n t [ 1 0 0 ] ; i n d i c e = 0; } p u b lic void A c o l a r( i n t x ) { a [ i n d i c e] = x ; i n d i c e ++; } p u b lic void D e s a c o l a r () { f o r ( i n t i = 0; i < indice -1; i ++) a [ i ] = a [ i +1]; indice - -; } p u b lic boolean C o l a V a c i a () { return ( i n d i c e == 0) ; } p u b lic i n t P r i m e r o () { return a [0]; } }

UNIDAD 3. IMPLEMENTACION

33

Estrategia 3: De la misma manera que para Pilas, podemos mencionar otra estrategia de implementaci on en donde variamos la estructura utilizada para guardar la informaci on, es decir, tambi en utilizamos un arreglo pero para guardar la cantidad de elementos que tenemos en vez de hacerlo en una variable utilizamos la posici on 0 del arreglo.

3.1.3

Implementaci on de ColaPrioridadTDA

Dentro de las posibles implementaciones para la cola de prioridad veremos las siguientes: Estrategia 1: Consideramos como estructuras dos arreglos, en uno de ellos tendremos los elementos y en el otro la prioridad de cada uno de esos elementos. Como veremos se tendr an que mantener ambos arreglos sincronizados en cuanto a que para una posici on dada se tendr a en un arreglo el valor del elemento y en el otro la prioridad que le corresponde a ese elemento. Adem as, como en todos los casos que hemos trabajado con arreglos tendremos una variable en donde llevemos la cantidad de elementos que se tienen. Se puede ver un esquema de esta estrategia en la gura 3.2. El elemento con mayor prioridad estar a en la posici on anterior a la marcada por indice.

Figura 3.2: Implementaci on ColaPrioridadTDA con estrategia 1


p u b lic c l a s s C o l a P r i o r i d a d D A implements C o l a P r i o r i d a d T D A { i n t [] e l e m e n t o s ; i n t [] p r i o r i d a d e s ; i n t i n d i c e; p u b lic void I n i c i a l i z a r C o l a () { i n d i c e = 0; e l e m e n t o s = new i n t [ 1 0 0 ] ; p r i o r i d a d e s = new i n t [ 1 0 0 ] ; } p u b lic void A c o l a r P r i o r i d a d ( i n t x , i n t p r i o r i d a d ) {

UNIDAD 3. IMPLEMENTACION

34

// d e s p l a z a a d e r e c h a los e l e m e n t o s de la cola m i e n t r a s // e s t o s t e n g a n m a y o r o i g u a l p r i o r i d a d que la de x i n t j = i n d i c e; f o r ( ; j >0 && p r i o r i d a d e s [j -1] >= p r i o r i d a d ; j - - ) { e l e m e n t o s [ j ] = e l e m e n t o s[ j -1]; p r i o r i d a d e s[ j ] = p r i o r i d a d e s [j -1]; } e l e m e n t o s[ j ] = x ; prioridades[j] = prioridad; i n d i c e ++; } p u b lic void D e s a c o l a r () { indice - -; } p u b lic i n t P r i m e r o () { return e l e m e n t o s [ indice -1]; } p u b lic boolean C o l a V a c i a () { return ( i n d i c e == 0) ; } p u b lic i n t P r i o r i d a d () { return p r i o r i d a d e s [ indice -1]; } }

Estrategia 2: Otra opci on de implementaci on de las colas de prioridades es considerar un arreglo cuyos elementos representan una estructura (por ser en Java una clase) que contiene el valor y la prioridad asociada a ese valor. Se puede ver un esquema de esta implementaci on en la gura 3.3.

Figura 3.3: Implementaci on de ColaPrioridadTDA con estrategia 2 A continuaci on se muestra el c odigo de esta implementaci on.

UNIDAD 3. IMPLEMENTACION
p u b lic c l a s s C o l a P r i o r i d a d A O implements C o l a P r i o r i d a d T D A { c l a s s Elemento{ i n t v a l o r; in t prioridad; } E l e m e n t o [] e l e m e n t o s ; i n t i n d i c e; p u b lic void I n i c i a l i z a r C o l a () { i n d i c e = 0; e l e m e n t o s = new E l e m e n t o [ 1 0 0 ] ; } p u b lic void A c o l a r P r i o r i d a d ( i n t x , i n t p r i o r i d a d ) { i n t j = i n d i c e;

35

// d e s p l a z a a d e r e c h a los e l e m e n t o s de la cola m i e n t r a s // e s t o s t e n g a n m a y o r o i g u a l p r i o r i d a d que la de x f o r (; j >0 && e l e m e n t o s [j -1]. p r i o r ida d >= p r i o r i d a d ; j - -) { e l e m e n t o s [ j ] = e l e m e n t o s[ j -1]; } e l e m e n t o s[ j ]= new E l e m e n t o () ; e l e m e n t o s[ j ]. v a l o r= x ; e l e m e n t o s[ j ]. p r i o r i d a d = p r i o r i d a d; i n d i c e ++; } p u b lic void D e s a c o l a r () { e l e m e n t o s[ i n d i c e - 1]= n u l l ; indice - -; } p u b lic i n t P r i m e r o () { return e l e m e n t o s [ indice -1]. v a l o r; } p u b lic boolean C o l a V a c i a () { return ( i n d i c e == 0) ; } p u b lic i n t P r i o r i d a d () { return e l e m e n t o s [ indice -1]. p r i o r i d a d ; } }

UNIDAD 3. IMPLEMENTACION

36

3.1.4

Implementaci on de ConjuntoTDA

A continuaci on vamos a llevar a cabo la implementaci on del TDA de conjuntos, a partir de la utilizaci on de un arreglo. En el caso del conjunto debido a que los elementos no tienen un orden, cuando se elimina una elemento se puede colocar el u ltimo elemento que se encuentra en el arreglo en la posici on del elemento a eliminar, y de esta manera evitar el desplazamiento de todos los elementos. Para implementar el m etodo Elegir, dado que la especicaci on no indica cu al es el elemento a recuperar, vamos a recuperar el elemento que est a en la primera posici on del arreglo.
p u b lic c l a s s C o n j u n t o T A implements C o n j u n t o T D A { i n t [] a ; i n t cant ; p u b lic void A g r e g a r( i n t x ) { i f (! t h i s . P e r t e n e c e ( x ) ) { a [ cant ] = x ; cant ++; } } p u b lic boolean C o n j u n t o V a c i o () { return cant == 0; } p u b lic i n t E l e g i r () { return a [ cant - 1]; } p u b lic void I n i c i a l i z a r C o n j u n t o () { a = new i n t [ 1 0 0 ] ; cant = 0; } p u b lic boolean P e r t e n e c e ( i n t x ) { i n t i = 0; wh ile (i < cant && a [ i ]!= x ) i ++; return ( i < cant ) ; } p u b lic void S a c a r( i n t x ) { i n t i = 0; wh ile (i < cant && a [ i ]!= x ) i ++; i f ( i < cant ) { a [ i ] = a [ cant -1]; cant - -;

UNIDAD 3. IMPLEMENTACION
} } }

37

Una implementaci on particular de conjuntos es la que denominamos conjunto de universo acotado, en donde tenemos un arreglo cuyas posiciones representan la presencia o ausencia de un valor en el conjunto. Es decir, si consideramos un conjunto de 15 elementos (del 0 al 14), tendremos un arreglo de 15 posiciones, en donde tendremos por ejemplo un 1 en la posici on 5 si es que el elemento 5 pertenece al conjunto, y 0 en caso contrario. Esta implementaci on tiene limitaciones en cuanto a los valores que puede tomar el conjunto, pero puede ser u til para aquellos casos en donde esta limitaci on no sea un problema ya que tenemos una manera m as eciente de agregar o eliminar un valor del arreglo, as como de conocer si un cierto valor pertenece al mismo. Todas las operaciones sobre este tipo de implementaci on para el conjunto son de costos constantes.

3.1.5

Implementaci on de Diccionario

A continuaci on vamos a llevar a cabo la implementaci on de los TDA de diccionarios, a partir de la utilizaci on de arreglos. En el caso del diccionarioSimple se emplea un u nico arreglo de elementos que se denen por una clave y un valor. mientras que en el diccionarioMultiple vamos a emplear un arreglo de elementos donde cada uno de estos contiene una clave y un arreglo de valores. Dado que las claves y valores de un diccionario no tienen que mantener un criterio de ordenaniento particular, cuando se elimina una elemento se puede colocar (al igual que en la implentaci on del conjunto) el u ltimo elemento que se encuentra en el arreglo en la posici on del elemento a eliminar, y de esta manera evitar el desplazamiento de todos los elementos. Diccionario Simple
p u b lic c l a s s D i c S i m p l e A implements D i c c i o n a r i o S i m p l e T D A { c l a s s Elemento{ i n t c l a v e; i n t v a l o r; } E l e m e n t o [] e l e m e n t o s ; i n t cant ; p u b lic void I n i c i a l i z a r D i c c i o n a r i o () { cant = 0; e l e m e n t o s = new E l e m e n t o [ 1 0 0 ] ; }

UNIDAD 3. IMPLEMENTACION

38

p u b lic void A g r e g a r( i n t clave , i n t v a l o r ) { i n t pos = C l a v e 2 I n d i c e ( c l a v e) ; i f ( pos == -1) { pos = cant ; e l e m e n t o s [ pos ]= new E l e m e n t o () ; e l e m e n t o s [ pos ]. c l a v e = c l a v e; cant ++; } e l e m e n t o s[ pos ]. v a l o r = v a l o r; } p r ivat e i n t C l a v e 2 I n d i c e ( i n t c l a v e ) { i n t i = cant -1; wh ile (i >=0 && e l e m e n t o s [ i ]. c l a v e != c l a v e) i - -; return i ; } p u b lic void E l i m i n a r ( i n t c l a v e) { i n t pos = C l a v e 2 I n d i c e ( c l a v e) ; i f ( pos != -1) { e l e m e n t o s [ pos ] = e l e m e n t o s [ cant -1]; cant - -; } } p u b lic i n t R e c u p e r a r ( i n t c l a v e) { i n t pos = C l a v e 2 I n d i c e ( c l a v e) ; return e l e m e n t o s [ pos ]. v a l o r; } p u b lic C o n j u n t o T D A C l a v e s () { C o n j u n t o T D A c =new C o n j u n t o L D () ; c . I n i c i a l i z a r C o n j u n t o () ; f o r ( i n t i =0; i < cant ; i ++) { c . A g r e g a r( e l e m e n t o s [ i ]. c l a v e) ; } return c ; } }

Diccionario Mutiple
p u b lic c l a s s D i c M u l t i p l e A implements D i c c i o n a r i o M u l t i p l e T D A { c l a s s Elemento{

UNIDAD 3. IMPLEMENTACION
i n t c l a v e; i n t [] v a l o r e s; i n t c a n t V a l o r e s; } E l e m e n t o [] e l e m e n t o s ; in t cantClaves; p u b lic void I n i c i a l i z a r D i c c i o n a r i o () { e l e m e n t o s = new E l e m e n t o [ 1 0 0 ] ; c a n t C l a v e s = 0; } p u b lic void A g r e g a r( i n t clave , i n t v a l o r ) { i n t posC = C l a v e 2 I n d i c e ( c l a v e) ; i f ( posC == -1) { posC = c a n t C l a v e s; e l e m e n t o s [ posC ]= new E l e m e n t o () ; e l e m e n t o s [ posC ]. c l a v e = c l a v e; e l e m e n t o s [ posC ]. c a n t V a l o r e s = 0; e l e m e n t o s [ posC ]. v a l o r e s = new i n t [ 1 0 0 ] ; c a n t C l a v e s ++; } E l e m e n t o e = e l e m e n t o s [ posC ]; i n t posV = V a l o r 2 I n d i c e (e , v a l o r) ; i f ( posV == -1) { e . v a l o r e s[ e . c a n t V a l o r e s ] = v a l o r ; e . c a n t V a l o r e s ++; } } p r ivat e i n t C l a v e 2 I n d i c e ( i n t c l a v e ) { i n t i = c a n t C la ve s -1; wh ile (i >=0 && e l e m e n t o s [ i ]. c l a v e != c l a v e) i - -; return i ; } p u b lic void E l i m i n a r ( i n t c l a v e) { i n t pos = C l a v e 2 I n d i c e ( c l a v e) ; i f ( pos != -1) { e l e m e n t o s [ pos ] = e l e m e n t o s [ c a n t C l av es -1]; c a n t C l av es - -; } } p u b lic void E l i m i n a r V a l o r ( i n t clave , i n t v a l o r) { i n t posC = C l a v e 2 I n d i c e ( c l a v e) ; i f ( posC != -1) { E l e m e n t o e = e l e m e n t o s [ posC ]; i n t posV = V a l o r 2 I n d i c e ( e , v a l o r ) ;

39

UNIDAD 3. IMPLEMENTACION
i f ( posV != -1) { e . v a l o r e s [ posV ] = e . v a l o r e s[ e . c a n t V a l or es -1]; e . c a n t V a lo re s - -; i f ( e . c a n t V a l o r e s ==0) { E l i m i n a r( c l a v e) ; } } } } p r ivat e i n t V a l o r 2 I n d i c e ( E l e m e n t o e , i n t v a l o r) { i n t i = e . c a n t V a l or es -1; wh ile (i >=0 && e . v a l o r e s [ i ]!= v a l o r) i - -; return i ; } p u b lic C o n j u n t o T D A R e c u p e r a r ( i n t c l a v e) { C o n j u n t o T D A c =new C o n j u n t o L D () ; c . I n i c i a l i z a r C o n j u n t o () ; i n t pos = C l a v e 2 I n d i c e ( c l a v e) ; i f ( pos != -1) { E l e m e n t o e = e l e m e n t o s [ pos ]; f o r ( i n t i =0; i < e . c a n t V a l o r e s ; i ++) { c . A g r e g a r ( e . v a l o r e s[ i ]) ; } } return c ; } p u b lic C o n j u n t o T D A C l a v e s () { C o n j u n t o T D A c =new C o n j u n t o L D () ; c . I n i c i a l i z a r C o n j u n t o () ; f o r ( i n t i =0; i < c a n t C l a v e s ; i ++) { c . A g r e g a r( e l e m e n t o s [ i ]. c l a v e) ; } return c ; }

40

3.2

An alisis de Costos

Cuando queremos analizar o comparar diferentes implementaciones necesitamos alg un par ametro o variables en la cual basar esa comparaci on, esas par ametros pueden ser: Cantidad de operaciones llevadas a cabo o utilizadas

UNIDAD 3. IMPLEMENTACION Cantidad de memoria utilizada

41

En el primer caso hablamos de an alisis de complejidad temporal, y en el segundo de complejidad de espacio. En este curso haremos el an alisis de complejidad temporal, y para ello realizaremos un an alisis simplicado, sin entrar en conceptos demostrativos de complejidad temporal. Para el an alisis de costos de complejidad temporal se consideran los siguientes tres criterios a trav es de los cuales clasicaremos el costo de ejecuci on de un m etodo: Costo constante (C): el costo no depende de la cantidad de elementos de entrada. Es el mejor de los costos posibles. Costo lineal (L): el costo depende linealmente de la cantidad de elementos de entrada, es decir que por cada elemento de entrada hay una cantidad constante de operaciones que se ejecutan. Es un costo bueno, aunque siempre depende del contexto. Costo polin omico (P): el costo es mayor a lineal. Un ejemplo de esta categor a ser a el costo cuadr atico. Es un costo no tan bueno, pero la interpretaci on depende del contexto. Pila PilaTI PilaTF InicializarPila C C Apilar L C Desapilar L C Tope C C PilaVacia C C Cola ColaPU InicializarCola C Acolar L Desacolar C Primero C ColaVacia C ColaPI C C L C C ColaPrioridadAO C L (2 n) C C C C

Cola con Prioridad ColaPrioridadDA InicializarCola C AcolarPrioridad L (2 n) Desacolar C Primero C ColaVacia C Prioridad C

UNIDAD 3. IMPLEMENTACION Conjunto InicializarConjunto Agregar Sacar Pertenece Elegir Diccionarios DiccionarioSimpleA DiccionarioMutipleA InicializarDiccionario C C Agregar L L Eliminar L L EliminarValor L Recuperar L L Claves L L Conjunto C L L L C

42

Unidad 4 Implementaci on con estructuras din amicas


En esta unidad vamos a implementar los TDA vistos en unidades anteriores utilizando ahora estructuras din amicas. Una vez implementados, vamos a comparar los costos de estas implementaciones contra las anteriores. Al nal de la unidad vamos a resolver problemas combinando estos TDA y m as de una implementaci on de un mismo TDA.

4.1

Implementaciones din amicas

Las implementaciones din amicas se basan en el concepto de utilizar memoria din amica, es decir que a diferencia de los arreglos, para los cuales denimos y reservamos la cantidad de memoria al momento de su creaci on, en las estructuras din amicas, vamos reservando memoria a medida que se necesita. Asimismo la memoria que ya no se necesita se devuelve al sistema. Por las caracter sticas de Java, la idea de devolver memoria es impl cita, es decir, la memoria que no se utiliza, autom aticamente queda disponible. Este mecanismo se denomina Garbage Collection. La base de una estructura din amica es lo que llamamos c elula o nodo. La idea entonces es especicar un nodo que tenga la capacidad de almacenar un valor. Luego, se van a encadenar tantos nodos como sean necesarios. Cabe recordar aqu que esta implementaci on no afectar a en absoluto el comportamiento del TDA, es decir que todo aquel que haya usado el TDA con una implementaci on est atica, lo podr a seguir usando de la misma forma, con una implementaci on din amica sin modicar nada. Volviendo a los nodos y la forma de encadenarlos, en cada nodo se denir a el espacio para almacenar el valor y para guardar una referencia a otro nodo. As con un nodo, tenemos el valor y la referencia a otro nodo. Esto da lugar a una cadena de nodos potencialmente innita. Un nodo que no apunta a ning un otro

43

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION

44

nodo, tendra un valor especial en esa posici on: null. La estructura del nodo se puede ver en la gura 4.1.

Figura 4.1: Nodo de la estructura din amica lineal As , dos nodos encadenados quedan como en la gura 4.2.

Figura 4.2: Dos nodos encadenados de la estructura din amica lineal Con esto, se puede generalizar a N nodos. Entonces, en Java, la estructura del nodo ser a:
c l a s s Nodo { i n t info ; Nodo sig ; }

4.1.1

Pila

Vamos ahora a implementar el PilaTDA con una estructura din amica. Para ello, recordemos la especicaci on del PilaTDA:
p u b lic i n t e r f a c e P i l a T D A { void I n i c i a l i z a r P i l a () ; void A p i l a r( i n t x ) ; void D e s a p i l a r () ; boolean P i l a V a c i a () ; i n t Tope () ; }

La estrategia entonces ser a mantener una cadena de nodos, manteniendo un puntero al tope de la pila, este apuntar a al siguiente, y as sucesivamente. Si la lista est a vac a, ser a un punterno null. Para agregar un nodo, se lo crea, y se agrega al comienzo de la cadena. Para eliminarlo, simplemente se elimina el primer nodo, dejando el puntero apuntando al segundo si es que existe.

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION


p u b lic c l a s s P i l a L D implements P i l a T D A { Nodo p r i m e r o; p u b lic void I n i c i a l i z a r P i l a () { primero = n u ll ; } p u b lic void A p i l a r( i n t x ) { Nodo aux = new Nodo () ; aux . info = x ; aux . sig = p r i m e r o ; p r i m e r o = aux ; } p u b lic void D e s a p i l a r () { p r i m e r o = p r i m e r o . sig ; } p u b lic boolean P i l a V a c i a () { return ( p r i m e r o == n u l l ) ; } p u b lic i n t Tope () { return p r i m e r o. info ; } }

45

4.1.2

Cola

Recordemos la especicaci on del ColaTDA:


p u b lic i n t e r f a c e C o l a T D A { void I n i c i a l i z a r C o l a () ; void A c o l a r( i n t x ) ; void D e s a c o l a r () ; boolean C o l a V a c i a () ; i n t P r i m e r o () ; }

Con la misma estrategia que para la pila, ahora vamos implementar la cola, esta vez, manteniendo un puntero al primer elemento y uno al u ltimo ya que por el comportamiento de este TDA, se deber a agregar por un extremo y eliminar por el otro. El orden en que estar an los elementos ser a el primero apunta al segundo, el segundo al tercero, as siguiendo, llegando al u ltimo elemento de la cadena que ser a el u ltimo elemento agregado a la Cola.

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION


p u b lic c l a s s C o l a L D implements C o l a T D A { // P r i m e r e l e m e n t o en la cola Nodo p r i m e r o; // U l t i m o e l e m e n t o en la cola , es decir , el u ltimo agregado Nodo u l t i m o; p u b lic void I n i c i a l i z a r C o l a () { primero = n u ll ; ultimo = n u ll ; } p u b lic void A c o l a r( i n t x ) { Nodo aux = new Nodo () ; aux . info = x ; aux . sig = n u l l ; // Si la cola no est a vac a i f ( u l t i m o != n u l l ) u l t i m o . sig = aux ; u l t i m o = aux ; // Si la cola e s t a b a v a c a i f ( p r i m e r o == n u l l ) p r i m e r o = u l t i m o; } p u b lic void D e s a c o l a r () { p r i m e r o = p r i m e r o . sig ; // Si la cola q u e d a v a c a i f ( p r i m e r o == n u l l ) ultimo = n u ll ; } p u b lic boolean C o l a V a c i a () { return ( u l t i m o == n u l l ) ; } p u b lic i n t P r i m e r o () { return p r i m e r o. info ; } }

46

4.1.3

Cola con Prioridad

Recordemos la especicaci on del TDA ColaPrioridad:


p u b lic i n t e r f a c e C o l a P r i o r i d a d T D A {

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION


void I n i c i a l i z a r C o l a () ; void A c o l a r P r i o r i d a d ( i n t x , i n t p r i o r i d a d ) ; void D e s a c o l a r () ; i n t P r i m e r o () ; boolean C o l a V a c i a () ; i n t P r i o r i d a d () ; }

47

Aqu la estrategia ser a modicar el nodo, para que adem as del valor tenga la prioridad incluida:
c l a s s NodoPrioridad{ i n t info ; i n t p r i o r i d a d; N o d o P r i o r i d a d sig ; }

Y luego implementar el TDA manteniendo la cadena de nodos ordenada primero por prioridad y luego por orden de entrada, manteniendo un puntero al elemento con mayor prioridad, que es el primero que se deber a eliminar.
p u b lic c l a s s C o l a P r i o r i d a d L D implements C o l a P r i o r i d a d T D A { NodoPrioridad mayorPrioridad; p u b lic void I n i c i a l i z a r C o l a () { mayorPrioridad = n u ll ; } p u b lic void A c o l a r P r i o r i d a d ( i n t x , i n t p r i o r i d a d ) { // Creo el n u e v o nodo que voy a a c o l a r N o d o P r i o r i d a d n u e v o = new N o d o P r i o r i d a d () ; n u e v o. info = x ; n u e v o. p r i o r i d a d = p r i o r i d a d; // Si la cola est a vac a o bien es m a s p r i o r i t a r i o que // el p r i m e r o hay que a g r e g a r l o al p r i n c i p i o i f ( m a y o r P r i o r i d a d == n u l l || prioridad > mayorPrioridad. prioridad) { n u e v o. sig = m a y o r P r i o r i d a d ; m a y o r P r i o r i d a d = n u e v o; } else { // S a b e m o s que m a y o r P r i o r i d a d no es null N o d o P r i o r i d a d aux = m a y o r P r i o r i d a d ; wh ile ( aux . sig != n u l l && aux . sig . p r i o r ida d >= p r i o r i d a d) { aux = aux . sig ; }

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION


n u e v o. sig = aux . sig ; aux . sig = n u e v o; } } p u b lic void D e s a c o l a r () { m a y o r P r i o r i d a d = m a y o r P r i o r i d a d . sig ; } p u b lic i n t P r i m e r o () { return m a y o r P r i o r i d a d . info ; } p u b lic boolean C o l a V a c i a () { return ( m a y o r P r i o r i d a d == n u l l ) ; } p u b lic i n t P r i o r i d a d () { return m a y o r P r i o r i d a d . p r i o r i d a d ; } }

48

4.1.4

Conjuntos

Para implementar el conjunto, a diferencia de las otras estructuras, no hay orden, por lo tanto la estrategia es simplemente mantener la cadena de nodos y siempre se deber a recorrerla para buscar un elemento o eliminarlo. Aqu presentamos una implementaci on, existen otras que mantienen la cadena ordenada. Con esto se mejoran algunos costos y se empeoran otros. Recordemos entonces la especicaci on del ConjuntoTDA:
p u b lic i n t e r f a c e C o n j u n t o T D A { void I n i c i a l i z a r C o n j u n t o () ; boolean C o n j u n t o V a c i o () ; void A g r e g a r( i n t x ) ; i n t E l e g i r () ; void S a c a r( i n t x ) ; boolean P e r t e n e c e ( i n t x ) ; }

Y la implementaci on propuesta es la siguiente:


p u b lic c l a s s C o n j u n t o L D implements C o n j u n t o T D A { Nodo c ; p u b lic void I n i c i a l i z a r C o n j u n t o () { c = null;

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION


} p u b lic boolean C o n j u n t o V a c i o () { return ( c == n u l l ) ; } p u b lic void A g r e g a r( i n t x ) { /* V e r i f i c a que x no este en el c o n j u n t o */ i f (! t h i s . P e r t e n e c e ( x ) ) { Nodo aux = new Nodo () ; aux . info = x ; aux . sig = c ; c = aux ; } } p u b lic i n t E l e g i r () { return c . info ; } p u b lic void S a c a r( i n t x ) { i f ( c != n u l l ) { // si es el p r i m e r e l e m e n t o de la l i s t a i f ( c . info == x ) { c = c . sig ; } else{ Nodo aux = c ; wh ile ( aux . sig != n u l l && aux . sig . info != x ) aux = aux . sig ; i f ( aux . sig != n u l l ) aux . sig = aux . sig . sig ; } } } p u b lic boolean P e r t e n e c e ( i n t x ) { Nodo aux = c ; wh ile (( aux != n u l l ) && ( aux . info != x ) ) { aux = aux . sig ; } return ( aux != n u l l ) ; } }

49

4.1.5

Diccionarios

Para implementar los diccionarios, como en el caso del conjunto no hay necesidad mentener un orden, por lo tanto la estrategia es simplemente mantener la cadena de nodos y siempre se deber a recorrerla para buscar un elemento o eliminarlo.

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION Diccionario Simple La implementaci on propuesta es la siguiente:
p u b lic c l a s s D i c S i m p l e L implements D i c c i o n a r i o S i m p l e T D A { c l a s s NodoClave{ i n t c l a v e; i n t v a l o r; NodoClave sigClave; } N o d o C l a v e o r i g e n; p u b lic void I n i c i a l i z a r D i c c i o n a r i o () { origen = n u ll ; }

50

p u b lic void A g r e g a r( i n t clave , i n t v a l o r ) { N o d o C l a v e nc = C l a v e 2 N o d o C l a v e ( c l a v e ) ; i f ( nc == n u l l ) { nc = new N o d o C l a v e () ; nc . c l a v e = c l a v e; nc . s i g C l a v e = o r i g e n ; o r i g e n = nc ; } nc . v a l o r = v a l o r ; } p r ivat e N o d o C l a v e C l a v e 2 N o d o C l a v e ( i n t c l a v e) { N o d o C l a v e aux = o r i g e n; wh ile ( aux != n u l l && aux . c l a v e != c l a v e ) { aux = aux . s i g C l a v e; } return aux ; } p u b lic void E l i m i n a r( i n t c l a v e) { i f ( o r i g e n != n u l l ) { i f ( o r i g e n. c l a v e == c l a v e) { o r i g e n = o r i g e n. s i g C l a v e ; } else { N o d o C l a v e aux = o r i g e n ; wh ile ( aux . s i g C l a v e != n u l l && aux . s i g C l a v e . c l a v e != c l a v e) { aux = aux . s i g C l a v e ; } i f ( aux . s i g C l a v e != n u l l ) { aux . s i g C l a v e = aux . s i g C l a v e . s i g C l a v e; }

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION


} } } p u b lic i n t R e c u p e r a r ( i n t c l a v e) { N o d o C l a v e n = C l a v e 2 N o d o C l a v e ( c l a v e) ; return n . v a l o r; }

51

p u b lic C o n j u n t o T D A C l a v e s () { C o n j u n t o T D A c = new C o n j u n t o L D () ; c . I n i c i a l i z a r C o n j u n t o () ; N o d o C l a v e aux = o r i g e n; wh ile ( aux != n u l l ) { c . A g r e g a r( aux . c l a v e ) ; aux = aux . s i g C l a v e; } return c ; } }

Diccionario Multiple La implementaci on propuesta es la siguiente:


p u b lic c l a s s D i c M u l t i p l e L implements D i c c i o n a r i o M u l t i p l e T D A { c l a s s NodoClave{ i n t c l a v e; NodoValor valores; NodoClave sigClave; } c l a s s NodoValor{ i n t v a l o r; NodoValor sigValor; } N o d o C l a v e o r i g e n; p u b lic void I n i c i a l i z a r D i c c i o n a r i o () { origen = n u ll ; }

p u b lic void A g r e g a r( i n t clave , i n t v a l o r ) { N o d o C l a v e nc = C l a v e 2 N o d o C l a v e ( c l a v e ) ; i f ( nc == n u l l ) {

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION


nc = new N o d o C l a v e () ; nc . c l a v e= c l a v e; nc . s i g C l a v e= o r i g e n ; o r i g e n = nc ; } N o d o V a l o r aux = nc . v a l o r e s; wh ile ( aux != n u l l && aux . v a l o r != v a l o r ) { aux = aux . s i g V a l o r; } i f ( aux == n u l l ) { N o d o V a l o r nv = new N o d o V a l o r () ; nv . v a l o r = v a l o r; nv . s i g V a l o r = nc . v a l o r e s; nc . v a l o r e s = nv ; } } p r ivat e N o d o C l a v e C l a v e 2 N o d o C l a v e ( i n t c l a v e) { N o d o C l a v e aux = o r i g e n; wh ile ( aux != n u l l && aux . c l a v e != c l a v e ) { aux = aux . s i g C l a v e; } return aux ; } p u b lic void E l i m i n a r V a l o r ( i n t clave , i n t v a l o r) {

52

i f ( o r i g e n != n u l l ) { i f ( o r i g e n. c l a v e == c l a v e) { E l i m i n a r V a l o r E n N o d o ( origen , v a l o r) ; i f ( o r i g e n . v a l o r e s == n u l l ) { o r i g e n = o r i g e n. s i g C l a v e ; } } else { N o d o C l a v e aux = o r i g e n ; wh ile ( aux . s i g C l a v e != n u l l && aux . s i g C l a v e . c l a v e != c l a v e) { aux = aux . s i g C l a v e ; } i f ( aux . s i g C l a v e != n u l l ) { E l i m i n a r V a l o r E n N o d o ( aux . sigClave , v a l o r) ; i f ( aux . s i g C l a v e. v a l o r e s == n u l l ) { aux . s i g C l a v e= aux . s i g C l a v e. s i g C l a v e ; } } } } } p r ivat e void E l i m i n a r V a l o r E n N o d o ( N o d o C l a v e nodo , i n t v a l o r) {

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION

53

i f ( nodo . v a l o r e s != n u l l ) { i f ( nodo . v a l o r e s. v a l o r == v a l o r) { nodo . v a l o r e s = nodo . v a l o r e s. s i g V a l o r ; } else { N o d o V a l o r aux = nodo . v a l o r e s ; wh ile ( aux . s i g V a l o r != n u l l && aux . s i g V a l o r . v a l o r != v a l o r) { aux = aux . s i g V a l o r ; } i f ( aux . s i g V a l o r != n u l l ) { aux . s i g V a l o r = aux . s i g V a l o r . s i g V a l o r; } } } } p u b lic void E l i m i n a r ( i n t c l a v e) { i f ( o r i g e n != n u l l ) { i f ( o r i g e n. c l a v e == c l a v e) { o r i g e n = o r i g e n. s i g C l a v e ; } else { N o d o C l a v e aux = o r i g e n ; wh ile ( aux . s i g C l a v e != n u l l && aux . s i g C l a v e . c l a v e != c l a v e) { aux = aux . s i g C l a v e ; } i f ( aux . s i g C l a v e != n u l l ) { aux . s i g C l a v e = aux . s i g C l a v e . s i g C l a v e; } } } } p u b lic C o n j u n t o T D A R e c u p e r a r ( i n t c l a v e) { N o d o C l a v e n = C l a v e 2 N o d o C l a v e ( c l a v e) ; C o n j u n t o T D A c = new C o n j u n t o L D () ; c . I n i c i a l i z a r C o n j u n t o () ; i f ( n != n u l l ) { N o d o V a l o r aux = n . v a l o r e s; wh ile ( aux != n u l l ) { c . A g r e g a r ( aux . v a l o r) ; aux = aux . s i g V a l o r; } } return c ; }

p u b lic C o n j u n t o T D A C l a v e s () {

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION


C o n j u n t o T D A c = new C o n j u n t o L D () ; c . I n i c i a l i z a r C o n j u n t o () ; N o d o C l a v e aux = o r i g e n; wh ile ( aux != n u l l ) { c . A g r e g a r( aux . c l a v e ) ; aux = aux . s i g C l a v e; } return c ; } }

54

4.2

Comparaci on de costos

Vamos a comparar los costos de cada implementaci on respecto a la propia con estructuras est aticas. Pila InicializarPila Apilar Desapilar Tope PilaVacia Cola ColaPU InicializarCola C Acolar L Desacolar C Primero C ColaVacia C ColaPI C C L C C ColaLD C C C C C PilaTI PilaTF C C L C L C C C C C PilaLD C C C C C

Cola con Prioridad ColaPrioridadDA InicializarCola C AcolarPrioridad L (2 n) Desacolar C Primero C ColaVacia C Prioridad C Conjunto

ColaPrioridadAO C L (2 n) C C C C

ColaPrioridadLD C L (n) C C C C

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION ConjuntoA InicializarConjunto C Agregar L Sacar L Pertenece L Elegir C Diccionarios InicializarDiccionario Agregar Eliminar EliminarValor Recuperar Claves ConjuntoLD C L L L C

55

DicSimpleA DicMutipleA DicSimpleL DicMutipleL C C C C L L L L L L L L L L L L L L L L L L

4.3

Resoluci on de problemas combinando TDAs e implementaciones

Ejemplo 1: Determinar si una Cola es capic ua.


p u b lic boolean e s C o l a C a p i c u a ( C o l a T D A c ) { C o l a T D A aux1 = new C o l a L D () ; aux1 . I n i c i a l i z a r C o l a () ; i n t cant = 0; P i l a T D A p = new P i l a L D () ; p . I n i c i a l i z a r P i l a () ; wh ile (! c . C o l a V a c i a () ) { aux1 . A c o l a r( c . P r i m e r o () ) ; cant ++; c . D e s a c o l a r () ; } // D e v u e l v e la p a r t e e n t e r a de una d i v i s i o n i n t m i t a d = cant /2; wh ile (! aux1 . C o l a V a c i a () && m i t a d > 0) { p . A p i l a r( aux1 . P r i m e r o () ) ; aux1 . D e s a c o l a r () ; mitad - -; } // R e t o r n a 0 si el n u m e r o es par y 1 si es i m p a r i f (( cant %2) != 0) { aux1 . D e s a c o l a r () ; }

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION

56

wh ile (! p . P i l a V a c i a () && ! aux1 . C o l a V a c i a () ) { i f ( p . Tope () != aux1 . P r i m e r o () ) { return f a l s e ; } p . D e s a p i l a r () ; aux1 . D e s a c o l a r () ; } return ( p . P i l a V a c i a () && aux1 . C o l a V a c i a () ) }

Ejemplo 2: Eliminar los elementos repetidos de una Pila.


p u b lic void e l i m i n a r R e p e t i d o s ( P i l a T D A p ) { P i l a T D A aux = new P i l a L D () ; aux . I n i c i a l i z a r P i l a () ; C o n j u n t o T D A c = new C o n j u n t o L D () ; wh ile (! p . P i l a V a c i a () ) { i n t tope = p . Tope () ; i f (! c . P e r t e n e c e ( tope ) ) { aux . A p i l a r ( tope ) ; c . A g r e g a r ( tope ) ; } p . D e s a p i l a r () ; } wh ile (! aux . P i l a V a c i a () ) { p . A p i l a r( aux . Tope () ) ; aux . D e s a p i l a r () ; } }

Ejemplo 3: Calcular la diferencia sim etrica entre dos conjuntos.


p u b lic C o n j u n t o T D A d i f e r e n c i a S i m e t r i c a S i n O p e r a c i o n e s ( C o n j u n t o T D A c1 , C o n j u n t o T D A c2 ) { C o n j u n t o T D A r e s u l t a d o = new C o n j u n t o L D () ; wh ile (! c1 . C o n j u n t o V a c i o () ) { i n t e l e m e n t o = c1 . E l e g i r () ; i f (! c2 . P e r t e n e c e( e l e m e n t o ) ) { r e s u l t a d o . A g r e g a r ( e l e m e n t o) ; } else{ c2 . S a c a r ( e l e m e n t o ) ; } c1 . S a c a r( e l e m e n t o) ; } wh ile (! c2 . C o n j u n t o V a c i o () ) { i n t e l e m e n t o = c2 . E l e g i r () ;

CON ESTRUCTURAS DINAMICAS UNIDAD 4. IMPLEMENTACION


r e s u l t a d o . A g r e g a r( e l e m e n t o ) ; c2 . S a c a r( e l e m e n t o) ; } return r e s u l t a d o ; }

57

Unidad 5 Arboles
Durante esta secci on vamos a describir el concepto de la estructura de arboles y deniremos en particular el tipo de dato abstracto de los arboles binarios de b usqueda (ABB). Se presentar an los algoritmos de recorridos de arboles. Para la implementaci on y resoluci on de ejercicios con estas estructuras, ser a necesario introducir el tema de recursividad.

5.1

Conceptos

Un arbol representa una estructura jer arquica sobre una colecci on de elementos. Se puede denir como una colecci on de elementos llamados nodos sobre la que se dene una relaci on de paternidad que impone una estructura jer arquica sobre estos nodos. Esta relaci on entre dos elementos dene dos roles, un nodo es el padre y el otro es el hijo. En un arbol todo nodo tiene uno y s olo un padre, excepto un nodo particular al que se denomina la ra z del arbol y que no tiene ning un padre. M as formalmente podemos decir que un arbol es vac o o es un nodo ra z y un conjunto de arboles que dependen de esa ra z. Cada uno de estos arboles, se denomina sub arbol. M as adelante, veremos que esta denici on es especialmente u til al momento de resolver problemas con arboles. Se pueden denir m as t erminos que se utilizar an con los arboles. Un nodo sin hijos se denomina hoja. Todos los nodos que no son ni la ra z ni las hojas se denominan nodos internos. Se denominan descendientes de un nodo al conjunto de elementos de todos sus sub arboles. Se denominan ancestros de un nodo al conjunto de elementos formados por su padre, el padre de su padre y as siguiendo hasta llegar a la ra z del arbol. La profundidad de un nodo es la longitud del camino u nico desde la ra z a ese nodo. La altura del arbol es la mayor de las profundidades de sus nodos. Un solo nodo es por si mismo un arbol, y ese nodo ser a a su vez la ra z del arbol. Tambi en el arbol nulo, es decir, aquel que no contiene nodos es considerado un arbol. 58

UNIDAD 5. ARBOLES

59

Por ejemplo, una estructura de directorios en una PC puede ser representada por un arbol como se ve en la gura 5.1.

Figura 5.1: Estructura de arbol para un directorio Siguiendo con la metodolog a de toda la materia, se trabajar a con arboles de enteros. Por ejemplo, un arbol de enteros como el que se ve en la gura 5.2.

Figura 5.2: Arbol de enteros En el arbol de ejemplo, 2 es la ra z. Las hojas son 45, 1, 54, 98, 43, 7, 1 y 32. Los descendientes de 21 son 1, 4, y 54. Los ancestros de 43 son 7, 87 y 2. La profundidad de 8 es 2. La altura del arbol es 3.

5.2

TDA Arbol

Para denir el TDA del arbol, utilizaremos los conceptos de hijo mayor y hermano siguiente que se pueden ver en la gura 5.3. Dado un nodo de un arbol, el hijo

UNIDAD 5. ARBOLES

60

mayor es el sub arbol que est a m as a la izquierda. En cambio, el hermano siguiente de un nodo, es un sub arbol del mismo padre que el nodo, que sigue a la derecha del mismo.

Figura 5.3: Arbol n-ario De este TDA s olo veremos la especicaci on a modo ilustrativo. No veremos la implementaci on. Las operaciones necesarias son: Valor: Recupera el valor de la ra z del arbol. HijoMayor: Recupera el sub arbol del hijo m as a la izquierda. HermanoSig: Recupera el sub arbol del hermano siguiente. ArbolVacio: Indica si el arbol est a vac o. InicializarArbol: Inicializa el arbol. ElimHijoMConDesc: Elimina el sub arbol m as a la izquierda del arbol dado con todos sus descendientes. ElimHermSConDesc: Elimina el hermano siguiente del arbol dado con todos sus descendientes. CrearArbol: Asigna el valor como ra z del arbol. AgregarHijoM: Agrega el valor dado como ra z del sub arbol del arbol dado. La especicaci on del TDA es la siguiente:

UNIDAD 5. ARBOLES
p u b lic i n t e r f a c e A N a T D A { i n t V a l o r () ; A N a T D A H i j o M a y o r () ; A N a T D A H e r m a n o S i g () ; boolean A r b o l V a c i o () ; void I n i c i a l i z a r A r b o l () ; void E l i m H i j o M C o n D e s c ( i n t x ) ; void E l i m H e r m S C o n D e s c ( i n t x ) ; void C r e a r A r b o l ( i n t r ) ; void A g r e g a r H i j o M ( i n t p , i n t h ) ; }

61

5.3

Arboles binarios

Un caso particular de arboles son los arboles binarios, los cuales cumplen con todas las deniciones dadas previamente, s olo que cada nodo puede tener a lo sumo dos hijos. Es decir cada nodo tiene cero, uno o dos hijos. En estos arboles podemos hablar de hijo izquierdo, hijo derecho, sub arbol izquierdo y sub arbol derecho respectivamente. Se puede ver un arbol binario en la gura 5.4.

Figura 5.4: Arbol binario de enteros

5.4

Recursividad

Debido a la forma en que vamos a representar los arboles, se requiere para la mayor a de sus operaciones la utilizaci on de operaciones recursivas. Vamos a recordar el concepto de recursividad. Cuando hablamos de un m etodo recursivo hablamos de un m etodo que se dene en funci on de s mismo. Siempre nos vamos a encontrar que dentro de ese m etodo

UNIDAD 5. ARBOLES

62

va a haber una llamada o invocaci on a s mismo. Esto, a simple vista llevar a a un m etodo que nunca acabar a su ejecuci on, por lo tanto, vamos a tener que buscar una forma de cortar esta recursi on. Entonces, en todo m etodo recursivo vamos a tener: 1. Un caso base o condici on de corte, en donde se nalice la recursividad 2. Un paso recursivo, o invocaci on al m etodo en s mismo. Debemos tener especial cuidado en que la ejecuci on del algoritmo alcance siempre la condici on de corte, entonces cuando se invoca al m etodo en forma recursiva se debe hacer con los par ametros que tiendan a alcanzar en un punto al caso base que corte la recursividad. Un ejemplo simple de recursividad es el m etodo que calcula el factorial de un n umero:
p u b lic i n t f a c t o r i a l ( i n t n ) { i f ( n == 0) { // caso base return 1; } else{ // Paso r e c u r s i v o en d o n d e se d e c r e m e n t a n para l l e g a r al caso base return n * f a c t o r i a l ( n -1) ; } }

Como vemos, en este ejemplo, la llamada recursiva se hace con un n umero menos al ingresado, con lo cual, suponiendo que el n umero era positivo, en alg un momento se va a alcanzar la condici on de corte, cuando el n umero sea 0.

5.5

Arboles Binarios de B usqueda (ABB)

Los arboles binarios de b usqueda (ABB) son arboles binarios que tienen la particularidad que sus elementos est an ordenados de izquierda a derecha, es decir, dado un nodo X todos los nodos que pertenecen al sub arbol izquierdo de ese nodo X tienen valores menores a el, y todos los nodos que son hijos derechos tienen valores mayores al nodo X. Por otra parte, un arbol ABB no tiene elementos repetidos. Un ejemplo de ABB es el que se ve en la gura 5.5.

5.5.1

Especicaci on

Las operaciones necesarias para utilizar un ABB son:

UNIDAD 5. ARBOLES

63

Figura 5.5: ABB Raiz: recupera el valor de la ra z de un ABB siempre que el mismo est e inicializado y no sea vac o. HijoIzq: devuelve el sub arbol izquierdo siempre que el arbol est e inicializado y no est e vac o. HijoDer: devuelve el sub arbol derecho siempre que el arbol est e inicializado y no est e vac o. ArbolVacio: indica si el arbol est a vac o o no siempre que el arbol est e inicializado. InicializarABB: inicializa el arbol. AgregarElem: agrega el elemento dado manteniendo la propiedad de ABB, siempre que el arbol est e inicializado. EliminarElem: elimina el elemento dado manteniendo la propiedad de ABB, siempre que el arbol est e inicializado. A continuaci on vamos a presentar la denici on del TDA para los arboles ABB:
p u b lic i n t e r f a c e A B B T D A { // s i e m p r e que el a rbol i n t Raiz () ; // s i e m p r e que el a rbol A B B T D A H i j o I z q () ; // s i e m p r e que el a rbol A B B T D A H i j o D e r () ; // s i e m p r e que el a rbol boolean A r b o l V a c i o () ; est e i n i c i a l i z a d o y no est e vac o est e i n i c i a l i z a d o y no est e vac o est e i n i c i a l i z a d o y no est e vac o est e inicializado

UNIDAD 5. ARBOLES
void I n i c i a l i z a r A r b o l () ; // s i e m p r e que el a r b o l est e inicializado void A g r e g a r E l e m ( i n t x ) ; // s i e m p r e que el a r b o l est e inicializado void E l i m i n a r E l e m ( i n t x ) ; }

64

5.5.2

Implementaci on

Existen diversas formas de implementar los ABB. Vamos a presentar una con estructura din amica, pero se debe saber que existen otras implementaciones, incluso algunas con estructuras est aticas. Para esta implementaci on, vamos a denir un nodo, como un valor y sus dos sub arboles. El nodo queda como sigue:
c l a s s NodoABB{ i n t info ; ABBTDA hijoIzq; ABBTDA hijoDer; }

Para la implementaci on, vamos a utilizar la u ltima denici on de arbol que dimos, adaptada a los ABB. La denici on es que un arbol es un conjunto vac o de nodos o un nodo ra z y sus dos sub arboles. Es decir, que para nosotros un arbol con un solo nodo, ser a un nodo y dos sub arboles vac os. Con esta denici on, vamos a implementar el ABBTDA:
p u b lic c l a s s ABB implements A B B T D A{ N o d o A B B raiz ; p u b lic i n t Raiz () { return raiz . info ; } p u b lic boolean A r b o l V a c i o () { return ( raiz == n u l l ) ; } p u b lic void I n i c i a l i z a r A r b o l () { raiz = n u l l ; } p u b lic A B B T D A H i j o D e r () { return raiz . h i j o D e r; } p u b lic A B B T D A H i j o I z q () { return raiz . h i j o I z q;

UNIDAD 5. ARBOLES
} p u b lic void A g r e g a r E l e m ( i n t x ) { i f ( raiz == n u l l ) { raiz = new N o d o A B B () ; raiz . info = x ; raiz . h i j o I z q = new ABB () ; raiz . h i j o I z q . I n i c i a l i z a r A r b o l () ; raiz . h i j o D e r = new ABB () ; raiz . h i j o D e r . I n i c i a l i z a r A r b o l () ; } e l s e i f ( raiz . info > x ) raiz . h i j o I z q . A g r e g a r E l e m ( x ) ; e l s e i f ( raiz . info < x ) raiz . h i j o D e r . A g r e g a r E l e m ( x ) ; }

65

p u b lic void E l i m i n a r E l e m ( i n t x ) { i f ( raiz != n u l l ) { i f ( raiz . info == x && raiz . h i j o I z q . A r b o l V a c i o () && raiz . h i j o D e r . A r b o l V a c i o () ) { raiz = n u l l ; } e l s e i f ( raiz . info == x && ! raiz . h i j o I z q . A r b o l V a c i o () ) { raiz . info = t h i s . m a y o r ( raiz . h i j o I z q ) ; raiz . h i j o I z q. E l i m i n a r E l e m ( raiz . info ) ; } e l s e i f ( raiz . info == x && raiz . h i j o I z q . A r b o l V a c i o () ) { raiz . info = t h i s . m e n o r ( raiz . h i j o D e r ) ; raiz . h i j o D e r. E l i m i n a r E l e m ( raiz . info ) ; } e l s e i f ( raiz . info < x ) { raiz . h i j o D e r. E l i m i n a r E l e m ( x ) ; } else{ raiz . h i j o I z q. E l i m i n a r E l e m ( x ) ; } } } p r ivat e i n t m a y o r( A B B T D A a ) { i f ( a . H i j o D e r () . A r b o l V a c i o () ) return a . Raiz () ; else return m a y o r ( a . H i j o D e r () ) ; } p r ivat e i n t m e n o r( A B B T D A a ) { i f ( a . H i j o I z q () . A r b o l V a c i o () ) return a . Raiz () ;

UNIDAD 5. ARBOLES
else return m e n o r ( a . H i j o I z q () ) ; } }

66

5.5.3

Recorridos

Existen tres recorridos b asicos de un arbol, que se conocen como pre-order, inorder y post-order. Los tres recorridos son recursivos por denici on. Presentaremos la idea de cada uno y el algoritmo para resolverlo. Es importante tener presente qu e realiza cada uno para poder utilizarlos ya que son la base para resolver muchos de los problemas con arboles. Pre-order Este recorrido propone visitar primero los padres y luego cada hijo en el mismo orden, es decir se visita el nodo ra z, y luego cada sub arbol en pre-order. En esta denici on, visitar puede signicar mostrar o cualquier otra acci on que se desee realizar. El algoritmo que hace este recorrido es el siguiente:
p u b lic void p r e O r d e r ( A B B T D A a ) { i f (! a . A r b o l V a c i o () ) { S y s t e m. out . p r i n t l n ( a . raiz () ) ; p r e O r d e r( a . H i j o I z q () ) ; p r e O r d e r( a . H i j o D e r () ) ; } }

El resultado de recorrer en pre-order el arbol de ejemplo de la gura 5.5 ser a: 20, 10, 1, 18, 14, 12, 15, 35, 26, 23, 30, 40. In-order Este recorrido propone visitar in-order el sub arbol izquierdo, luego la ra z y por u ltimo in-order el sub arbol derecho. En esta denici on, visitar puede signicar mostrar o cualquier otra acci on que se desee realizar. Este recorrido es el que en un ABB muestra los elementos ordenados de menor a mayor. El algoritmo que hace este recorrido es el siguiente:
p u b lic void i n O r d e r ( A B B T D A a ) { i f (! a . A r b o l V a c i o () ) { i n O r d e r( a . H i j o I z q () ) ; S y s t e m. out . p r i n t l n ( a . raiz () ) ; i n O r d e r( a . H i j o D e r () ) ; } }

UNIDAD 5. ARBOLES

67

El resultado de recorrer in-order el arbol de ejemplo de la gura 5.5 ser a: 1, 10, 12, 14, 15, 18, 20, 23, 26, 30, 35, 40. Post-order Este recorrido propone visitar primero los hijos en post-orden y luego la raiz. En esta denici on, visitar puede signicar mostrar o cualquier otra acci on que se desee realizar. El algoritmo que hace este recorrido es el siguiente:
p u b lic void p o s t O r d e r ( A B B T D A a ) { i f (! a . A r b o l V a c i o () ) { p o s t O r d e r( a . H i j o I z q () ) ; p o s t O r d e r( a . H i j o D e r () ) ; S y s t e m. out . p r i n t l n ( a . raiz () ) ; } }

El resultado de recorrer en post-order el arbol de ejemplo de la gura 5.5 ser a: 1, 12, 15, 14, 18, 10, 23, 30, 26, 40, 35, 20.

5.5.4

Utilizaci on

Vamos a resolver algunos ejercicios en donde se trabaja con a rboles binarios de b usqueda. Ejercicio 1: Contar la cantidad de nodos de un ABB.
p u b lic i n t C o n t a r( A B B T D A a ) { i f ( a . A r b o l V a c i o () ) { return 0; } else{ return (1 + C o n t a r ( a . H i j o I z q () ) + C o n t a r( a . H i j o D e r () ) ) ; } }

Ejercicio 2: Dado un elemento y un ABB, calcular su profundidad en el arbol.


p u b lic i n t c a l c u l a r P r o f u n d i d a d ( A B B T D A t , i n t x ) { i f ( t . A r b o l V a c i o () ) { return 0; } e l s e i f ( t . Raiz () == x ) { return 0; } e l s e i f ( t . Raiz () > x ) { return (1+ t h i s . c a l c u l a r P r o f u n d i d a d ( t . H i j o I z q () , x ) ) ; }

UNIDAD 5. ARBOLES

68

else{ return (1+ t h i s . c a l c u l a r P r o f u n d i d a d ( t . H i j o D e r () , x ) ) ; } }

Ejercicio 3: Dado un elemento, determinar si est a o no en un ABB.


p u b lic boolean e x i s t e E l e m e n t o E n A B B ( A B B T D A t , i n t x ) { i f ( t . A r b o l V a c i o () ) { return f a l s e ; } e l s e i f ( t . Raiz () == x ) { return t r u e ; } e l s e i f ( t . Raiz () > x ) { return t h i s . e x i s t e E l e m e n t o E n A B B ( t . H i j o I z q () , x ) ; } else{ return t h i s . e x i s t e E l e m e n t o E n A B B ( t . H i j o D e r () , x ) ; } }

Ejercicio 4: Dado un arbol ABBTDA a, devolver todos los nodos pares del mismo.
p u b lic C o n j u n t o T D A n o d o s P a r e s ( A B B T D A a ) { C o n j u n t o T D A r = new C o n j u n t o L D () ; r . I n i c i a l i z a r C o n j u n t o () ; i f (! a . A r b o l V a c i o () ) { i f ( a . raiz () % 2 == 0) { r . A g r e g a r ( a . raiz () ) ; } C o n j u n t o T D A rI = n o d o s P a r e s ( a . H i j o I z q () ) ; C o n j u n t o T D A rD = n o d o s P a r e s ( a . H i j o D e r () ) ; wh ile (! rI . C o n j u n t o V a c i o () ) { i n t x = rI . E l e g i r () ; r. Agregar(x); rI . S a c a r ( x ) ; } wh ile (! rD . C o n j u n t o V a c i o () ) { i n t x = rD . E l e g i r () ; r. Agregar(x); rD . S a c a r ( x ) ; } } return r ; }

Unidad 6 Grafos
En esta unidad se introducir an los conceptos principales de grafos. Se especicar a el TDA grafo y sus posibles implementaciones.

6.1

Conceptos b asicos

Un grafo es un conjunto de de elementos llamados nodos o v ertices y un conjunto de pares de nodos llamados aristas. Cada arista tiene un valor entero asociado al que llamaremos peso. Un grafo sirve para representar una red. Un ejemplo podr a ser una red de computadoras (gura 6.1) o un mapa de rutas que unen ciudades(gura 6.2). Un caso particular de grafos, son aquellos en los que las aristas tienen un sentido y no son de doble sentido, y se denominan grafos dirigidos. En ese caso, la arista tiene un nodo origen y un nodo destino. Se dice que un v ertice tiene aristas entrantes, cuando existe al menos una arista que tiene al v ertice en cuesti on como destino. Se dice que un v ertice tiene aristas salientes, cuando existe al menos una arista que tiene al v ertice en cuesti on como origen. Un v ertice que no tiene aristas entrantes ni salientes es un v ertice aislado. La cantidad de aristas salientes se llama grado positivo de un v ertice. La cantidad de aristas entrantes se llama grado negativo de un v ertice. Se dice que un v ertice b es adyacente de un v ertice a, si existe una arista entre a y b. Un camino, es una sucesi on ordenada de nodos v1 , v2, v3, , vn en donde existe una arista entre v1 y v2 , otra entre v2 y v3 , y as siguiendo hasta vn . El costo del camino es la suma de los pesos de cada arista. Un ciclo es un camino que comienza y termina en un mismo v ertice. Es de especial importancia tener en cuenta este concepto, ya que al momento de comenzar a recorrer los grafos si nos econtramos con un ciclo podr amos entrar en un camino sin salida si no tenemos en cuenta esta situaci on y la tratamos. Se dice que un v ertice es alcanzable desde otro si existe un camino que una al segundo con el primero. 69

UNIDAD 6. GRAFOS

70

Figura 6.1: Red de computadores

Figura 6.2: Mapa de ciudades

UNIDAD 6. GRAFOS

71

Se entiende por aristas paralelas, a un par de aristas con mismo origen y mismo destino. Se dene como bucle, una arista que tiene igual origen y destino. A los efectos del curso, vamos a trabajar con: grafos dirigidos, sin aristas paralelas ni bucles, en donde los nodos son n umeros enteros, los pesos son enteros positivos. Dado el grafo de la gura 6.3 los v ertices son 1, 2, 3, 4, 5, 6, 7, 8 y 10. Las aristas son (1,2), (2,1), (1,3), (3,4), (3,5), (4,6), (5,6), (6,5) y (8,10). El peso de cada una es 12, 10, 21, 32, 9, 10, 10, 12, 87 y 10 respectivamente. El nodo 3 tiene una arista entrante y dos salientes. El nodo 7 no tiene ninguna arista entrante ni saliente, por ende es un nodo aislado. Existe un camino entre el nodo 1 y el 4, su costo es 53. Adem as el nodo 4 es alcanzable desde 1.

Figura 6.3: Ejemplo de grafo

6.2

Especicaci on del TDA

Para utilizar un grafo, deniremos las siguientes operaciones: InicializarGrafo: inicializa el grafo. AgregarVertice: agrega un nuevo v ertice al grafo, siempre que el grafo est e inicializado y el v ertice no exista. EliminarVertice: elimina el v ertice dado siempre que el v ertice exista. Vertices: devuelve el conjunto de v ertices de un grafo, siempre que el grafo est e inicializado.

UNIDAD 6. GRAFOS

72

AgregarArista: agrega una arista al grafo entre los v ertices dados y con el peso dado, siempre que existan ambos v ertices pero no exista una arista entre ambos. EliminarArista: elimina la arista entre los v ertices dados, siempre que esta arista exista. ExisteArista: indica si el grafo contiene una arista entre los v ertices dados, siempre que los v ertices existan. PesoArista: devuelve el peso de la arista entre los v ertices dados, siempre que la arista exista. Entonces queda la siguiente especicaci on del GrafoTDA:
p u b lic i n t e r f a c e G r a f o T D A { void I n i c i a l i z a r G r a f o () ; // s i e m p r e que el g r a f o est e i n i c i a l i z a d o y no e x i s t a el nodo void A g r e g a r V e r t i c e ( i n t v ) ; // s i e m p r e que el g r a f o est e i n i c i a l i z a d o y e x i s t a el nodo void E l i m i n a r V e r t i c e ( i n t v ) ; // s i e m p r e que el g r a f o est e inicializado C o n j u n t o T D A V e r t i c e s () ; // s i e m p r e que el g r a f o est e i n i c i a li za do , no e x i s t a la arista , pero e x i s t a n a m b o s n o d o s void A g r e g a r A r i s t a ( i n t v1 , i n t v2 , i n t peso ) ; // s i e m p r e que el g r a f o est e i n i c i a l i z a d o y e x i s t a la a r i s t a void E l i m i n a r A r i s t a ( i n t v1 , i n t v2 ) ; // s i e m p r e que el g r a f o est e i n i c i a l i z a d o y e x i s t a n los n o d o s boolean E x i s t e A r i s t a ( i n t v1 , i n t v2 ) ; // s i e m p r e que el g r a f o est e i n i c i a l i z a d o y e x i s t a la a r i s t a i n t P e s o A r i s t a ( i n t v1 , i n t v2 ) ; }

6.3

Implementaciones est aticas y din amicas

Vamos a proponer dos implementaciones del TDA, una est atica y otra din amica. La implementaci on est atica es una implementaci on con matrices de adyacencia. Una matriz de adyacencia, es una matriz cuadrada donde la cantidad de las y columnas est a dada por la cantidad de nodos del grafo. Adem as el contenido de cada celda es el peso de la arista con origen en el n umero de la y destino en el n umero de columna. Ahora bien, en Java, los ndices de las matrices van de cero en adelante, en forma consecutiva. No es el caso de los nodos, que pueden tener valores no cont nuos. Por lo tanto, vamos a tener que utilizar un mapeo que nos indique en qu e ndice

UNIDAD 6. GRAFOS

73

de la matriz est a el nodo que buscamos. Entonces, al nombre del nodo lo vamos a llamar internamente etiqueta. Por ejemplo para el grafo dado de la gura 6.3, la matriz ser a la que se ve en la gura 6.4 y el mapeo entre etiquetas e ndices se puede ver en la gura 6.5

Figura 6.4: Matriz de adyacencia

Figura 6.5: Etiquetas de mapeo entre v ertices e ndices de la matriz


p u b lic c l a s s G r a f o M A implements G r a f o T D A { s t a t i c i n t n = 100; i n t [][] MAdy ; i n t [] E t i q s; i n t c a n t N o d o s; p u b lic void I n i c i a l i z a r G r a f o () { MAdy = new i n t [ n ][ n ]; E t i q s = new i n t [ n ]; c a n t N o d o s = 0; } p u b lic void A g r e g a r V e r t i c e ( i n t v ) { E t i q s[ c a n t N o d o s] = v ; f o r ( i n t i =0; i <= c a n t N o d o s ; i ++) {

UNIDAD 6. GRAFOS
MAdy [ c a n t N o d o s ][ i ] = 0; MAdy [ i ][ c a n t N o d o s] = 0; } c a n t N o d o s ++; } p u b lic void E l i m i n a r V e r t i c e ( i n t v ) { i n t ind = V e r t 2 I n d i c e ( v ) ; f o r ( i n t k =0; k < c a n t N o d o s ; k ++) MAdy [ k ][ ind ] = MAdy [ k ][ c a n t No dos -1]; f o r ( i n t k =0; k < c a n t N o d o s ; k ++) MAdy [ ind ][ k ] = MAdy [ c a n t N od os -1][ k ]; E t i q s[ ind ] = E t i q s[ c a n t N o dos -1]; c a n t N o dos - -; } p r ivat e i n t V e r t 2 I n d i c e ( i n t v ) { i n t i = c a n t No dos -1; wh ile (i >=0 && E t i q s[ i ]!= v ) i - -; return i ; } p u b lic C o n j u n t o T D A V e r t i c e s () { C o n j u n t o T D A Vert =new C o n j u n t o L D () ; Vert . I n i c i a l i z a r C o n j u n t o () ; f o r ( i n t i =0; i < c a n t N o d o s ; i ++) { Vert . A g r e g a r ( E t i q s[ i ]) ; } return Vert ; } p u b lic void A g r e g a r A r i s t a ( i n t v1 , i n t v2 , i n t peso ) { i n t o = V e r t 2 I n d i c e ( v1 ) ; i n t d = V e r t 2 I n d i c e ( v2 ) ; MAdy [ o ][ d ] = peso ; } p u b lic void E l i m i n a r A r i s t a ( i n t v1 , i n t v2 ) { i n t o = V e r t 2 I n d i c e ( v1 ) ; i n t d = V e r t 2 I n d i c e ( v2 ) ; MAdy [ o ][ d ]=0; } p u b lic boolean E x i s t e A r i s t a ( i n t v1 , i n t v2 ) { i n t o = V e r t 2 I n d i c e ( v1 ) ; i n t d = V e r t 2 I n d i c e ( v2 ) ; return MAdy [ o ][ d ] ! = 0 ; }

74

UNIDAD 6. GRAFOS

75

p u b lic i n t P e s o A r i s t a ( i n t v1 , i n t v2 ) { i n t o = V e r t 2 I n d i c e ( v1 ) ; i n t d = V e r t 2 I n d i c e ( v2 ) ; return MAdy [ o ][ d ]; } }

Para el caso de la implementaci on din amica, llamaremos a la implementaci on lista de adyacencia. La idea es tener una lista encadenada de nodos (a los que llamaremos NodoGrafo). Cada nodo tiene su valor, una referencia al pr oximo nodo y adem as una referencia a la lista de aristas que tienen a ese nodo como origen. Una arista (a la que llamaremos NodoArista), tiene una referencia al nodo destino de esta arista, el peso y una referencia a la pr oxima arista de esa lista. Entonces para el grafo del ejemplo de la gura 6.3 tenemos la la representaci on de la gura 6.6 donde los c rculos son los NodoGrafo y los rect angulos los NodoArista.

Figura 6.6: Lista de adyacencia La representaci on de los nodos y las aristas es la siguiente:
c l a s s N o d o G r a f o{ i n t nodo ; N o d o A r i s t a a r i s t a; N o d o G r a f o s i g N o d o; }

UNIDAD 6. GRAFOS
c l a s s N o d o A r i s t a{ i n t e t i q u e t a; NodoGrafo nodoDestino; NodoArista sigArista; }

76

Entonces, la implementaci on con listas de adyacencia es la siguiente:


p u b lic c l a s s G r a f o L A implements G r a f o T D A { N o d o G r a f o o r i g e n; p u b lic void I n i c i a l i z a r G r a f o () { origen = n u ll ; } p u b lic void A g r e g a r V e r t i c e ( i n t v ) { // El v e r t i c e se i n s e r t a al i n i c i o de la l i s t a de n o d o s N o d o G r a f o aux = new N o d o G r a f o () ; aux . nodo = v ; aux . a r i s t a = n u l l ; aux . s i g N o d o = o r i g e n; o r i g e n = aux ; } /* * Para a g r e g a r una n u e v a a r i s t a al grafo , p r i m e r o se d e b e n * b u s c a r los n o d o s e n t r e los c u a l e s se va a g r e g a r la arista , * y l u e g o se i n s e r t a s o b r e la l i s t a de a d y a c e n t e s del nodo * o r i g e n ( en este caso n o m b r a d o como v1 ) */ p u b lic void A g r e g a r A r i s t a ( i n t v1 , i n t v2 , i n t peso ) { N o d o G r a f o n1 = V e r t 2 N o d o ( v1 ) ; N o d o G r a f o n2 = V e r t 2 N o d o ( v2 ) ; // La n u e v a a r i s t a se i n s e r t a al i n i c i o de la l i s t a // de n o d o s a d y a c e n t e s del nodo o r i g e n N o d o A r i s t a aux = new N o d o A r i s t a () ; aux . e t i q u e t a = peso ; aux . n o d o D e s t i n o = n2 ; aux . s i g A r i s t a = n1 . a r i s t a; n1 . a r i s t a = aux ; } p r ivat e N o d o G r a f o V e r t 2 N o d o ( i n t v ) { N o d o G r a f o aux = o r i g e n; wh ile ( aux != n u l l && aux . nodo != v ) { aux = aux . s i g N o d o; } return aux ; }

UNIDAD 6. GRAFOS

77

p u b lic void E l i m i n a r V e r t i c e ( i n t v ) { // Se r e c o r r e la l i s t a de v e r t i c e s para r e m o v e r el nodo v // y las a r i s t a s con este v e r t i c e. // D i s t i n g u e el caso que sea el p r i m e r nodo i f ( o r i g e n. nodo == v ) { o r i g e n = o r i g e n . s i g N o d o; } N o d o G r a f o aux = o r i g e n; wh ile ( aux != n u l l ) { // r e m u e v e de aux t o d a s las a r i s t a s h a c i a v t h i s . E l i m i n a r A r i s t a N o d o ( aux , v ) ; i f ( aux . s i g N o d o != n u l l && aux . s i g N o d o. nodo == v ) { // Si el s i g u i e n t e nodo de aux es v , lo e l i m i n a aux . s i g N o d o = aux . s i g N o d o. s i g N o d o; } aux = aux . s i g N o d o; } } /* * Si en las a r i s t a s del nodo e x i s t e * una a r i s t a h a c i a v , la e l i m i n a */ p r ivat e void E l i m i n a r A r i s t a N o d o ( N o d o G r a f o nodo , i n t v ) { N o d o A r i s t a aux = nodo . a r i s t a; i f ( aux != n u l l ) { // Si la a r i s t a a e l i m i n a r es la p r i m e r a en // la l i s t a de n o d o s a d y a c e n t e s i f ( aux . n o d o D e s t i n o . nodo == v ) { nodo . a r i s t a = aux . s i g A r i s t a; } else { wh ile ( aux . s i g A r i s t a != n u l l && aux . s i g A r i s t a . n o d o D e s t i n o . nodo != v ) { aux = aux . s i g A r i s t a ; } i f ( aux . s i g A r i s t a != n u l l ) { // Q u i t a la r e f e r e n c i a a la a r i s t a h a c i a v aux . s i g A r i s t a = aux . s i g A r i s t a. s i g A r i s t a ; } } } } p u b lic C o n j u n t o T D A V e r t i c e s () { C o n j u n t o T D A c = new C o n j u n t o L D () ; c . I n i c i a l i z a r C o n j u n t o () ;

UNIDAD 6. GRAFOS

78

N o d o G r a f o aux = o r i g e n; wh ile ( aux != n u l l ) { c . A g r e g a r( aux . nodo ) ; aux = aux . s i g N o d o; } return c ; } /* * Se e l i m i n a la a r i s t a que t i e n e como o r i g e n al v e r t i c e v1 * y d e s t i n o al v e r t i c e v2 */ p u b lic void E l i m i n a r A r i s t a ( i n t v1 , i n t v2 ) { N o d o G r a f o n1 = V e r t 2 N o d o ( v1 ) ; E l i m i n a r A r i s t a N o d o ( n1 , v2 ) ; } p u b lic boolean E x i s t e A r i s t a ( i n t v1 , i n t v2 ) { N o d o G r a f o n1 = V e r t 2 N o d o ( v1 ) ; N o d o A r i s t a aux = n1 . a r i s t a; wh ile ( aux != n u l l && aux . n o d o D e s t i n o. nodo != v2 ) { aux = aux . s i g A r i s t a ; } // Solo si se e n c o n t r o la a r i s t a buscada , aux no es null return aux != n u l l ; } p u b lic i n t P e s o A r i s t a ( i n t v1 , i n t v2 ) { N o d o G r a f o n1 = V e r t 2 N o d o ( v1 ) ; N o d o A r i s t a aux = n1 . a r i s t a; wh ile ( aux . n o d o D e s t i n o. nodo != v2 ) { aux = aux . s i g A r i s t a ; } // Se e n c o n t r o la a r i s t a e n t r e los dos n o d o s return aux . e t i q u e t a ; } }

Bibliograf a
[AA98] J. Hopcroft Y J. Ullman A. Aho. Estructuras de Datos y Algoritmos. Addison Wesley, Ubicaci on en biblioteca UADE: 681.3.01/A292, 1998. [Wei04] Mark Allen Weiss. Estructuras de datos en JAVA. Addison Wesley, Ubicaci on en biblioteca UADE: 004.43 WEI est [1a] 2004, 2004. [yJC06] J. Lewis y J. Chase. Estructuras de Datos con Java. Dise no de Estructuras y Algoritmos. Addison Wesley Iberoamericana, 2006. [yRT02] M. Goodrich y R. Tamassia. Estructura de Datos y Algoritmos en Java. Editorial Continental, 2002.

79