You are on page 1of 47

Factores de Calidad:

Factores externos: cualidad del software que puede ser detectada por un usuario (sin
conocer el cdigo fuente).
Factores internos: cualidad del software que puede ser percibida por el programador
(conociendo el cdigo fuente).
Correctitud: el programa respeta la especificacin (para una entrada dada produce la
salida esperada).
Robustez: el programa es capaz de manejar entradas no contempladas por la
especificacin (se espera que se degrade graciosamente). Ejemplo: recibe un entero
negativo cuando espera un positivo. Crtica en situaciones industriales.
Extensibilidad: capacidad de agregarle funcionalidad al software.
Portabilidad: habilidad del software con mnimo cambio en otro hardware o sistema
operativo.
Reusabilidad: capacidad de usar el cdigo en la construccin de otros programas.
Eficiencia: capacidad del software de requerir pocos recursos de computo (tiempo de CPU
y memoria).
Facilidad de uso: capacidad del software para ser usador por usuarios con distinta
habilidad.

Excepciones:
Las excepciones son eventos inesperados que ocurren durante la ejecucin de un
programa. Puede ser resultado de una condicin de error o una entrada incorrecta. En POO las
excepciones son objetos lanzados por un cdigo que detecta una condicin inesperada. Las
excepciones capturadas por otro cdigo que repara la situacin (o el programa termina con
error en ejecucin).
En Java las excepciones son subclases de la clase Exception. Los mtodos deben especificar en su
signatura las excepciones que pueden lanzar. Una excepcin se lanza desde una sentencia throw
void mtodo( parmetros formales )
{
try
{
.
sentencia_que_puede_producir_excepcin();
.
}
catch( tipo_excepcion e )
{
cdigo para manejar la excepcin e
}
Finally
{
codigo que siempre se ejecuta
}
}

Interfaces:
Una interfaz es una coleccin de declaraciones de mtodos (y sin atributos) que luego van
a ser implementados por una o ms clases. Una clase que implementa una interfaz debe
implementar todos los mtodos provistos por la interfaz.

Clases Wrapper:
En ocasiones es muy convenientes tratar a los datos primitivos (int, boolean, etc) como
objetos. Las clases wrapper se usan como cualquier otra.
Genericidad:
Una clase genrica permite encapsular una estructura cuyo comportamiento es
independiente del tipo de las componentes. Permite definir esquemas de clases que pueden
instanciarse de varias maneras.

Genericidad paramtrica: un tipo genrico es un tipo que no es definido en compilacin


sino en tiempo de ejecucin y permite definir una clase en fusin de parmetros formales
de tipo que abstraen los tipos de algunos datos internos de una clase. Dada una clase
genrica vamos a instanciar algunos objetos usando parmetros actuales de tipo.

Estructuras de Datos:
Una estructura de datos es una forma de organizar un conjunto de datos (elementales o
no). Cada una de las unidades que la componen se denomina celda. En general se accede a la
estructura de datos globalmente o a cada una de las celdas que la componen en forma particular.
As como las estructuras de datos se crean con el objetivo de facilitar la manipulacin de datos
individualmente como un todo. Desde la perspectiva de su representacin en memoria, una
estructura de datos es una coleccin de variables organizadas de alguna manera.
Algoritmo:
Un algoritmo es una secuencia de pasos que al ejecutarse permiten realizar una tarea en
una cantidad finita de tiempo.
Tiempo de ejecucin:
Es el tiempo de corrida de un programa sobre una maquina en particular y para una
determinada muestra de datos de entrada.

Orden de tiempo: Es una funcin T(n) que se asocia al programa (n = tamao de entrada).
Esta funcin representa el nmero de instrucciones ejecutarse sobre una maquina ideal.
Las ventajas de esta funcin son: Se independiza la evolucin de aspectos ajenos al
algoritmo y puede calcularse sobre el algoritmo sin necesidad de implementarlo
previamente.

El tiempo de ejecucin de un algoritmo depende de la cantidad de operaciones primitivas


realizadas, estas toman tiempo constantes (arbitrario) porque dependes del compilador y
hardware subyacente.

Notacin asinttica (Big-Oh): sean F(n) y G(n) dos funciones de los naturales a los reales,
F(n) es O(G(n)) si y solo si existe un c real mayor que 0 y un n0 natural mayor que 1 tales
que F(n)<=c. G(n) para todo n>=n0 (se lee F(n) es big-oh de G(n) o F(n) es orden de G(n))
Regla de la suma: Si f1(n) es O(g1(n)) y f2(n) es O(g2(n)) entonces f1(n) + f2(n) es
O(max(g1(n),g2(n)).
Regla del producto: Si f1(n) es O(g1(n)) y f2(n) es O(g2(n)) entonces f1(n)*f2(n) es
O(g1(n)*g2(n)).
BigOmega: Sean f(n) y g(n) funciones de los naturales en los reales. f(n) es (g(n)) ssi
existen c real positivo y n0 natural tales que f(n) cg(n) para todo n n0.
BigTheta: Sean f(n) y g(n) funciones de los naturales en los reales. f(n) es (g(n)) ssi f(n) es
(g(n)) y f(n) es (g(n)).
Nota: BigTheta quiere decir c1g(n) f(n) c2g(n)
Reglas para calcular T(n) a partir del cdigo fuente de un algoritmo:
Paso 1: Determinar el tamao de la entrada n.
Paso 2: Aplicar las siguientes reglas en forma sistemtica:
TP(n) = constante si P es una accin primitiva
TS1;;Sn(n) = TS1(n) + + TSn(n)
Tif B then S1 else S2(n) = TB(n) + max(TS1(n),TS2(n))
Tfor(m;S)(n)=m*TS(n) donde m=cant_iteraciones(for(m;S))
Twhile B do S (n)=m*(TB(n) + TS(n)) donde m=cant_iteraciones(while B do S)
Tcall P(n) = TS(n) donde procedure P; begin S end
Tf(e)(n) = Tx:=e(n) + TS(n) donde function f(x); begin S end

Clculo de tiempo de algoritmo recursivo:


Paso 1: Determinar la entrada
Paso 2: Determinar el tamao de la entrada
Paso 3: Definir una recurrencia para T(n)
Paso 4: Obtener una definicin no recursiva para T(n)
Paso 5: Determinar orden de tiempo de ejecucin
Paso 6: Hacer prueba por induccin para ver que las expresiones para T(n) de (3) y (4) son
equivalentes.

ED - Arreglos y listas:
Secuencias:
Una secuencia de elementos [a1,a2,,an] tiene:
-

Una longitud n
Primer elemento (a 1)
Cada elemento ai (i=2,,n-1) tiene siguiente a i-1
Cada elemento ai(i=2,,n) tiene previo a i+1
Los elementos son homogneos (del mismo tipo)

Formas de representar una secuencia:


-

Arreglos
Archivos
Lista enlazada

Secuencia: Implementacin con arreglo


Ventajas:
El arreglo reside en memoria principal.
El arreglo es homogneo.
Recuperar una componente toma orden uno.
Desventajas:
El arreglo tiene un tamao mximo.
Insertar un elemento tiene orden lineal en la cantidad de elementos del arreglo.
Eliminar un elemento tiene orden lineal en la cantidad de elementos del arreglo.
Secuencia: Implementacin con archivos
Ventajas:
El archivo es homogneo.
El archivo no tiene tamao acotado.
Desventajas:
El archivo reside en memoria secundaria.
Recuperar un registro tiene orden lineal (en archivos secuenciales).
Insertar un elemento tiene orden lineal.
Eliminar un elemento tiene orden lineal.
Secuencia: Implementacin con lista
Una lista enlazada es una coleccin de nodos que considerado juntos forman un orden
lineal. En una lista simplemente enlazada cada nodo es un objeto que almacena una referencia a
un elemento y una referencia, llamada siguiente, a otro nodo.

Lista doblemente enlazada: cada nodo conoce un elemento, el nodo anterior y el nodo
siguiente. Hay dos maneras de implementar una lista doblemente en lazada, una es
manteniendo referencia al primer y ltimo elemento, o bien usando nodos centinela al
principio y al final para evitar casos especiales al insertar y eliminar.

Lista circular: cada nodo conoce al nodo siguiente y el ltimo nodo conoce al primero

TDA pila:
Es una coleccin de objetos actualizada usando una poltica LIFO (last in firts out)
Operaciones:
-

Push(e): inserta el elemento e en el tope de la pila.


Pop(): elimina el elemento del tope de la pila y lo entrega como resultado. Si se aplica a
una pila vaca se produce una situacin de error.
isEmpty(): retorna verdadero si la pila no contiene elementos y falso en caso contrario.
top(): retorna el elemento del tope de la pila. Si se aplica a una pila vaca produce una
situacin de error.
size(): retorna un entero natural que indica cuantos elementos hay en la pila.

Aplicaciones de la pila:

Navegador web: registro de pginas visitadas


Editor de texto: implementacin de mecanismo de tecla retroceso y escape
Ejecucin de procedimientos y funciones: organizacin de los registros de activacin
Validacin de cdigo HTML
Compilacin de una expresin y clculo de su valor: paso de notacin infija a postfija

Implementacin:
Usando un arreglo: El tipo de la pila es guardado en una variable t, donde t es el ndice en
la pila. Cuando t =-1 la pila esta vaca. La cantidad de elementos es t+1. Cada mtodo corre en
tiempo constante O(1). Se mantiene una constante CAPACITY para indicar el tamao total del
arreglo. Al escoger un numero arbitrario de CAPACITY, generalmente grande, se est ocupando un
espacio en memoria que seguramente no se va a utilizar. Por el contrario, si se quieren agregar
elementos a la pila se lanzara una excepcin, o bien puede aumentarse el tamao del arreglo. Esta
implementacin con un arreglo es muy til cuando se tiene un valor estimado de la cantidad de
elementos que se agregaran a la pila
Usando una estructura enlazada: el tope de la pila est en la cabeza de la estructura. Las
operaciones son en tiempo constante O(1) y el espacio ocupado en memoria es O(n) donde n es la
cantidad de elementos de la estructura. Todas las inserciones y retiros se hacen desde la cabeza
de la estructura
TDA Cola:
Es una coleccin de objetos actualizada siguiendo una poltica FIFO (first in first out)
Operaciones:

Enqueue(e): pone el elemento e al final de la cola.


Dequeue(): elimina el elemento del frente de la cola y lo retorna. Si la cola esta vaca se
produce un error.
Front(): retorna el elemento del frente de la cola. Si la cola esta vaca de produce un error.
isEmpty(): retorna verdadero si la cola no contiene elementos y falso en caso contrario.
size(): retorna un entero natural que indica cuantos elementos hay en la cola.

Aplicaciones:

Colas de pedidos para atencin por orden de llegada.


Buffer de entrada salida.
Socket (estructura de datos para comunicar dos programas): un programa inserta (encola)
datos en el socket y otro programa los consume (desencolando).

Implementaciones:
Usando arreglo circular: la variable f indica el primer elemento de la cola, es decir el
primero en ser removido, la variable r seala la prxima celda habilitada del arreglo. La cola esta
vaca cuando f=r. para evitar ndices fuera del arreglo se utiliza el arreglo circular en donde las
variables f y r pasan a la posicin 0 del arreglo despus de haber llegado al final, esto se hace
usando mod n, donde n es la longitud del arreglo. La cola no puede tener ms de n-1 elementos. El
tamao de la cola es (n-f+r) al igual que la pila con arreglo solo es eficiente cuando conocemos una

cantidad aproximada de los elementos que contendr la cola. El tiempo de ejecucin de la


operaciones son todos de O(1).
Usando estructura enlazada: el frente de la cola est en la cabeza de la lista. Se remueve
por la cabeza y se ingresan por la cola. El tiempo de ejecucin son de O(1)
TDA ArrayList (vector):
Implementa una secuencia S=[X1,X2,,Xn] de elementos de tipo genrico E, donde n es la
longitud de S. la posicin de cada elemento es un entero i entre 0 y n-1, tal que la posicin de X1 es
0, la de X2 es 1, , la de Xn es n-1
Operaciones:

isEmpty(): retorna verdadero si la lista no contiene elementos y falso en caso contrario.


size(): retorna un entero natural que indica cuantos elementos hay en la lista.
get(i): retorna el elemento i-esimo de la lista; ocure un error si i<0 o i>size-1.
set(i,e): reemplaza con e al elemento i-esimo; ocure un error si i<0 o i>size-1.
Add(i,e): agrega un elemento e a la posicin i; ocure un error si i<0 o i>size-1.
Remove(i): elimina el elemento i-esimo de la lista.

TDA lista (node list o linked list)


Para implementarlo usaremos estructura simple o doblemente enlazada, adems de la
posicin de nodo en lugar de un ndice para referirnos a la ubicacin de un elemento en la lista.
Posiciones: para abstraer y unificar las diferentes formas de almacenar elementos en
varias implementaciones de una lista, introducimos el concepto de Position. Este esquema
determina que cada posicin almacena un elemento y existe un mtodo para obtenerlo.
Operaciones:

First(): retorna la posicin del primer elemento de la lista; lanza error si la lista esta vaca.
Last(): retorna la posicin del ltimo elemento de la lista; lanza error si la lista est vaca.
Prev(p): retorna la posicin que precede al elemento en la posicin p; lanza error si p=first.
Next(p): retorna la posicin del elemento que sigue al elemento en la posicin p; lanza
error si p=last.
set(p,e): reemplaza el elemento en la posicin p con e; retornando el elemento que estaba
antes en la posicin p.
addFirst(e): inserta un nuevo elemento e como primer elemento.
addLast(e): inserta un nuevo elemento e como ltimo elemento.
addBefore(p,e): inserta un nuevo elemento e antes de la posicin p.
addAfter(p,e):inserta un nuevo elemento e luego de la posicin p.

remove(p): elimina y retorna el elemento en la posicin p invalidando dicha posicin.

Segunda implementacin: con lista simplemente en lazada y celda de encabezamiento (nodo


dummy). Esta implementacin usa posicin indirecta, que es, la posicin P i del elemento i es la
direccin del nodo anterior al nodo que contiene a i.

Ventajas:
addBefore y addAfter tiene orden O(1)
no hay casos especiales como testear que se inserta al principio de la lista o la lista est
vaca ya que siempre est al menos la celda de encabezamiento.
Desventajas:
addLast, Last y Prev siguen teniendo orden lineal en la cantidad de elementos de la lista.
Tercera implementacin: Usa una lista simplemente enlazada y mantiene una referencia al
primer y ltimo elemento, la posicin puede ser directa (sin nodo dummy) o indirecta (con nodos
dummy).
Ventajas:
addLast(e) y last() tienen orden O(1).
Desventajas:
hay casos especiales cuando se elimina al principio y al final, sobre todo cuando la lista
mide 1.
prev(p) sigue siendo de orden lineal en la cantidad de elementos de la lista (hay que
recorrer desde el principio).

Cuarta implementacin: Usa una lista doblemente enlazada con referencia al primer y
ltimo nodo y dos celdas de encabezamiento (una al principio y otra al final)
Ventajas:
cada nodo conoce el siguiente nodo y al nodo anterior.
todas las operaciones tienen orden 1.

Desventajas:
mayor uso de espacio.

Iteradores:
Un iterador es un patrn de diseo que abstrae el recorrido de los elementos de una
coleccin. Un iterador consiste en una secuencia S, un elemento actual corriendo sobre S, y una
manera de avanzar al siguiente elemento de S, hacindolo el nuevo elemento actual.
Mtodos de un elemento iterador:

hasNext(): testea si hay elementos para recorrer en el iterador.


next(): retorna el siguiente elemento del iterador.

Operaciones para una coleccin iterable:

Iterator(): retorna un iterador para los elementos de la coleccin.

rbol:
Un rbol T se define como un conjunto de nodos almacenando elementos tales que los nodos
tienen una relacin padre-hijo, que satisface:

Si T no es vaco, tiene un nodo especial, llamado la raz de T, que no tiene padre.


Cada nodo V de T diferente de la raz tiene un nico nodo padre W.
Cada nodo con padre w es hijo de W.

Definicin recursiva
Un rbol T es:

Vaco (no tienen nodos).


Es un nodo R (llamado la raz de T) y un conjunto (posiblemente vaco) de rboles
T1,T2,,Tk cuyas races R1,R2,,Rk son hijos de R.

Definicin recursiva de rbol no vaco:

Un nodo hoja R llamado raz de T.


Es un nodo R (llamado la raz de T) y un conjunto (posiblemente vaco) de rboles
T1,T2,,Tk cuyas races R1,R2,,Rk son hijos de R.

Relaciones entre nodos


-

Nodos hermanos: dos nodos con el mismo padre se llaman hermanos.


Nodos externos u hojas: un nodo V es externo si no tiene hijos.
Nodo interno: un nodo V es interno si tiene uno o ms hijos (esto incluye a la raz).
Ancestro(u,v): un nodo U es ancestro de un nodo V si U es igual a V o U ancestro del padre
de V.
Ancestro propio: un nodo U es ancestro de un nodo V si U es distinto a V y U ancestro del
padre de V.
Descendiente(u,v): un nodo U es descendiente de V si V es un ancestro de U.
Descendiente propio(u,v): u descendiente propio de v si u es descendiente de V y u es
distinto de V.
Sub-rbol: el sub-rbol de T con raz en el nodo V es el rbol consistiendo de todos los
descendientes de V.
Arco: un arco de un rbol T es un par de nodos (u,v) tales que u es padre de v o viceversa.
Camino: un camino de T es un secuencia de nodos tales que cualquier par de nodos
consecutivos en la secuencia forman un arco.

Arboles Ordenados:
Un rbol se dice ordenado si existe un orden lineal para los hijos de cada nodo, es decir, se
puede identificar el primer hijo, el segundo hijo y as sucesivamente. Tal orden se visualiza de
izquierda a derecha de acuerdo a tal ordenamiento.

Mtodos de rbol:
Position:

Element(): retorna el objeto almacenado en esta posicin.

Mtodos de acceso:

Root(): retorna la raz del rbol, lanza error si el rbol esta vaco.
Parent(v): retorna el padre de V, y lanza error si v es la raz.
Children(v): retorna una coleccin iterable conteniendo los hijos del nodo v, si el rbol es
ordenado, children los mantiene en orden. Si v es una hoja children(v) es vaca.

Mtodos de consulta:

isInternal(v): testea si v es un nodo interno.


isExternal(v): testea si v es una hoja.
isRoot(v): testea si v es la raz.

Mtodos genricos:

size(): retorna el nmero de nodos del rbol.


isEmpty(): testea si el rbol tiene o no nodos.
Iterator(): retorna un iterador con los elementos ubicados en los nodos del rbol.
Position(): retorna una coleccin iterable de los nodos del rbol.
Replace(v,e): reemplaza con e y retorna el elemento ubicado en V.

Metodos de modificacin:

createRoot(e): crea un nodo raz con rotulo e.


addFirstChildren(p,e): agrega un primer hijo al nodo p, con rotulo e.
addLastChildren(p,e): agrega un ltimo hijo al nodo p, con rotulo e.
addBefore(p,rb,e): agrega un nodo con rotulo e como hijo de un nodo padre p dado. El
nuevo nodo se agregara antes de otro nodo hermano rb tambin dado.
addAfter(p,lb,e): agrega un nodo con rotulo e como hijo del padre p dado. El nuevo nodo
se agregara a continuacin de otro nodo lb tambin dado.
removeExternalNode(p): elimina la hoja p.
removeInternalNode(p): elimina el nodo interno p. los hijos del nodo eliminado lo
reemplazaran en el mismo orden en el que aparecen. La raz se puede eliminar si tiene un
nico hijo.
removeNode(p): elimina el nodo p.

Profundidad y altura:

Profundidad de un nodo v en un rbol T: Es la longitud del camino desde la raz de T hasta


el nodo v, es igual a la cantidad de ancestros propios de v.
Algoritmo:
Profundidad(T,v)
si v es la raz de T entonces
retornar 0
sino
retornar 1+Profundidad (T,w) donde w es el padre de v en T
Tiempo de ejecucin: es del orden de dv donde dv es la profundidad de v en T.

Longitud de un camino: es la cantidad de arcos de un camino.


Altura de un nodo V en un rbol T: Es la longitud del camino ms largo a una hoja en el
subrbol con raz V.

Primera solucin:
Altura(T)
h0
para cada vrtice v en T hacer
si b es una hoja en T entonces
hmax(h,profundidad(T,v))
retornar h
Tiempo de ejecucin: Taltura(n) es igual a O(n2).

Segunda solucin:
Altura(T,v)
si v es una hoja en T entonces
retornar 0
sino
h0
para cada hijo w de v en T hacer
hmax(h,altura(t,w))
retornar 1+h
Tiempo de ejecucin: Taltura(n) es igual a O(n2).

Altura de un rbol T: la altura del nodo raz de T.

Recorridos: un recorrido de un rbol T es una manera sistemtica de visitar todos los nodos de T.

Los recorridos bsicos son:

Preorden: En el recorrido preorden de un rbol T, la raz r de T se visita primero y luego se


visitan recursivamente cada uno de los subrboles de r. si el rbol es ordenado los
subrboles se visitan en el orden en el que aparecen.
Algoritmo:
preorden(T,v)
visitar(T,v)
para cada hijo w de v en T hacer
preorden(T,w)
Tiempo de ejecucin: si n es la cantidad de nodos del rbol T, el tiempo de ejecucin de
preorden es O(n), asumiendo una visita de O(1). Es decir, preorden corre en tiempo lineal
en el tamao del rbol.

Postorden: En el recorrido postorden de un rbol T, la raz r de T se visita luego de visitar


recursivamente cada uno de los subrboles de r. si el rbol es ordenado los subrboles ser
visitan en el orden en el que aparecen.
Algoritmo:
Postorden(T,v)
para cada hijo w de v en T hacer
Postorden(T,W)
Visitar(T,v)
Tiempo de ejecucin: si el rbol T tiene n nodos entonces el tiempo de postorden es O(n)
asumiendo una visita de O(1).

Inorden: En el recorrido inorden (o simtrico) de un rbol T con raz r, primero se recorre


recursivamente el primer hijo de la raz r, luego se visita la raz y luego se visita
recursivamente al resto de los hijos de r. Si el rbol es ordenado se visitan en el orden en
que aparecen.
Algoritmo:
Inorden(T,v)
si v es hoja en T entonces
Visitar(T,v)
sino
wprimer hijo de v en T
inorden(T,w)
visitar(T,v)
mientras w tiene hermanos en T hacer
whermano de w en t
inorden(T,w)

Por niveles:
o Nivel: es un subconjunto de nodos que tienen la misma profundidad.
o Recorrido por niveles: visita todos los nodos con profundidad p antes de recorrer
todos los nodos de p+1.
Algoritmo:
Niveles(T)
Colanew cola()
Cola.enqueue(t.root())
Cola.enqueue(null) //esto sirve para detectar el fin de lnea
mientras not cola.isEmpty() hacer
vcola.dequeue()
si v es distinto de null entonces
vistar(T,v)
para cada hijo w de v en T hacer
cola.enqueue(w)
sino
imprimir fin de lnea //accin al terminar un nivel
si not cola.isEmpty() entonces
cola.enqueue(null)
Tiempo de ejecucin: sea hi la cantidad de hijos del nodo i
T(n)= c1+ni=1 (c2+c3hi)=c1+c2n+c3(n-1)=O(n).

Representacin de arboles
-

Del padre: cada nodo conoce solo a su rotulo y al padre.

Representacin lista de hijos: cada nodo conoce su rotulo (elemento) y la lista de sus
nodos hijos. El rbol conoce el nodo raz del rbol.

Padre + lista de hijos [GT]: el rbol conoce la raz. Cada nodo conoce el rotulo, la lista de
nodos hijos y el nodo padre.

Hijo extremo izquierdo - hermano derecho: cada nodo conoce su rotulo y la identidad de
su hijo extremo izquierdo y de su hermano derecho (se puede combinar con la
representacin del padre de ser necesario).

Representacin con arreglo (HEI-HD):

Arboles Binarios:
Un rbol binario es un rbol ordenado que cumple:
1. Cada nodo tiene a lo sumo dos hijos.
2. Cada nodo hijo es o bien, hijo izquierdo o hijo derecho.
3. El hijo izquierdo precede al hijo derecho en el orden de los hijos del nodo.
Un subrbol que tiene como raz al hijo izquierdo, se llama subrbol izquierdo, anlogamente
para el derecho. En un rbol binario propio, cada nodo tiene 0 o 2 hijos. Si un rbol binario no es
propio entonces es impropio.
Aplicaciones:
Sirve para representar los resultados asociados a un conjunto de preguntas con respuesta si
o no. Cada nodo interno se asocia con una pregunta. Se comienza en la raz y con cada pregunta
se va a la izquierda o a la derecha dependiendo de la respuesta. Cuando se llega a una hoja se
tiene un resultado al cual se llega al partir de las respuestas dados en los ancestros de la hoja.

Una expresin aritmtica puede representarse con un rbol binario. Las hojas almacenan
constantes o variables. Los nodos internos almacenan los operadores (+,-,*,/):

Crear un arbol de exprecion aritmetica (parsing):


Algoritmo:
Parse(exp)
si exp no tienen una operacin entonces
retornar un rbol vinario hoja conteniendo exp
sino
opultimo_operador(exp)
T1parse(izqueirda(exp,op))
T2parse(derecha(exp,op))
retornar un rbol binario con op como rotulo de la raz y T 1 y T2 como hijos
izquierdo y derecho respectivamente

Calcular un rbol de expresin aritmtica: cada nodo en un rbol de expresin tiene un valor
asociado:

Si el nodo es externo, si valor es el de la variable/constante.


Si el nodo es interno, su valor est definido por la aplicacin de la operacin a los valores
de sus hijos.

Algoritmo:
Evaluar(rbol_exp)
si rbol_exp es una hoja entonces
retornar el valor del rotulo de rbol_exp
sino
oprotulo de raz de rbol_exp
v1 evaluar(left(rbol_exp))
v2 evaluar(right(rbol_exp))
retornar aplicar(op,v1,v2)

Definicin recursiva de rbol Binario


Un rbol binario T es o bien vaco, o consiste de:

Un nodo r llamado la raz de t que contiene un rotulo.


Un rbol binario, llamado el subrbol izquierdo de T.
Un rbol binario, llamado el subrbol derecho de T.

Operaciones de ABB (el rbol binario es una especializacin de Tree que adems soporta los
mtodos de acceso adicionales):

Left(v):Retorna el hijo izquierdo de v y ocurre un error si v no tiene hijo izq.


Right(v): Retorna el hijo der de v y ocurre un error si v no tiene hijo der.
hasLeft(v): Testea si v tiene hijo izquierdo.
hasRight(v): Testea si v tiene hijo derecho.

Mtodos de modificacin:

addRoot(e): (o createRoot(e)) agrega un nodo raz con rotulo e, lanza error si ya hay una
raz.
insertLeft(v,e): crea un nodo w hijo izquierdo de v con rotulo e, lanza error si v ya tiene
hijo izquierdo.
insertRight(v,e): anlogo a insertLeft.
remove(v): elimina el nodo v (si v tiene un hijo, reemplaza a v por su hijo, si v tiene 2 hijos,
entonces ocurre un error).
attach(v,T1,T2): setea T1 como hijo izquierdo de v y T2 como hijo derecho de v (error si v no
es hoja).

Representacin de rbol binario con arreglos


La componente 0 no se usa. La raz se almacena en la componente 1. El hijo izquierdo de la
componente i se almacena en la componente 2*i. El hijo derecho de la componente i se almacena
en la componente 2*i+1. Puede haber componentes vacas si el rbol no es lleno (propio) capitulo
7 [GT].

Cola con prioridad:


Una cola con prioridad almacena una coleccin de elementos que soporta:

insercin de elementos arbitraria.


eliminacin de elementos en orden de prioridad (el elemento de 1ra prioridad puede ser
eliminado en cualquier momento).

Nota: una cola con prioridad almacena sus elementos de acuerdo a su prioridad relativa y no
expone una nocin de posicin a sus clientes.
Clave vs prioridad
-

Clave: atributo de un individuo que sirve para identificarlo en un conjunto de individuos.


Ejemplo: DNI, nuero de libreta, numero de afiliado, etc.
Prioridad: atributo de un individuo que sirve para pesar al individuo en un conjunto de
individuos Ejemplo: promedio de un alumno, cantidad de dinero depositado en el banco
por un cliente, cantidad de aos que una persona es cliente de un negocio.

Comparacin de claves con rdenes totales: una cola con prioridad necesita un criterio de
comparacin que sea un orden total para poder resolver siempre la comparacin entre
prioridades. es un orden total si y solo si:

Reflexivo: k k (se relaciona consigo mismo, o sea contiene la identidad).


Antisimtrico: si K1 K2 y K2 K1 entonces K1 = K2.
Transitiva: k1k2 y k2k3, entonces k1k3.

TDA Cola con prioridad:


Una cola con prioridad es una coleccin de elementos, llamados valores, los cuales tienen
asociado una clave que es provista en el momento que el elemento es insertado. Un par clavevalor insertado en una cola con prioridad se llama una entrada (k, v).
Operaciones fundamentales:

Insert(k,v): inserta un valor v con clave k en PQ


RemoveMin(): Retorna y remueve de PQ una entrada con la clave ms pequea
Size(): Retorna el nmero de entradas en PQ
isEmpty(): testea si p es vaco
min(): retorna (pero no remueve) una entrada de PQ con la clave ms pequea

Implementaciones:
lista no ordenada:
Insert: Se inserta al principio de la lista.
Min, removeMin: Para hallar el mnimo o removerlo es necesario recorrer toda la lista.
lista ordenada:
Insert: Para insertar en forma ordenada es necesario recorrer toda la lista en el peor
caso.
Min, removeMin: El mnimo es el primer elemento de la lista.

Cola con prioridad implementada con Heap:


Un heap es un rbol binario que almacena una coleccin de entradas en sus nodos y se
satisface dos propiedades adicionales:

Propiedad de orden del heap (rbol parcialmente ordenado): en un heap T, para cada
nodo v distinto de la raz, la clave almacenada en v es mayor o igual que la clave
almacenada en el padre de v.
Propiedad de rbol binario completo: un heap T con altura H es un rbol binario completo
si los nodos de los niveles 0, 1, 2,, h-1 tiene 2 hijos y el nivel h-1 todos los nodos internos
estas a la izquierda de las hojas y hay a lo sumo un nico nodo con un hijo (que debe ser
izquierdo).

Propiedad de un heap: Un heap T con n entradas tiene una altura h = piso(log n)


Demostracin: como t es completo,
-

La cantidad n de nodos mnima ser con el nivel h-1 lleno y un nodo en el nivel h:
n 1+2+4++2h-1+1 = 2h-1+1 = 2h
Luego, es h log2n.

La cantidad n de nodos es mxima cuando el nivel h est lleno:


n 1+2+4++2h = 2h+1-1
Luego, hlog2(n+1)-1

Por lo tanto, como h es entero, entonces h = piso(logn)


Aplicacin
Heap Sort: Su objetivo es ordenar un arreglo A de N enteros en forma ascendente.
Algoritmo:
HeapSort(a,n)
cola new ColaConPriodidad()
para i 0..n-1 hacer
cola.insert(a[i])
para i 0..n-1 hacer
a[i] cola.removeMin()
Tiempo de ejecucin: Theapsort(n) = O(n.log2(n))
Mapeo
Un mapeo permite almacenar elementos de tal manera que puedan ser localizados
rpidamente usando una clave. Un elemento generalmente tiene informacin til adems de su
clave. Por ejemplo, un alumno tiene clave Libreta pero almacena nombre, fecha de nacimiento,

direccin, telfono, correo electrnico, etc. Un mapeo puede ser interpretado como una funcin
de dominio K y codominio V. Un mapeo puede ser interpretado como un conjunto de entradas
(k,v) donde k tiene tipo K y v tiene tipo V.
Operaciones de TDA Mapeo
Dado un mapeo M:
-

Size(): Retorna el nmero de entradas M.


isEmpty(): Testea si M es vaco.
get(k): si M contiene una entrada e con clave igual a k, retorna el valor de e. En caso
contrario retorna null.
Put(k,v): Si M no tiene una entrada con clave k, entonces agrega una entrada (k,v) a M y
retorna null. Si M ya tiene una entrada e con clave k, reemplaza el valor con v en e y
retorna el valor viejo de e.
Remove(k): remueve de M la entrada con clave k y retorna su valor. Si M no tiene entrada
con clave k, retorna null. Si M no tiene entrada con clave k, retorna null.
Keys(): Retorna una coleccin iterable de las claves en M. Keys().Iterator() retorna un
iterador de valores.
Entries(): Retorna una coleccin iterable con la entradas de M. Entries().iterator() retorna
un iterador de entrada.

Diccionarios
Un diccionario almacena pares clave-valor (k,v) (como los mapeos). Las claves son de tipo K y
los valores de tipo V genricos (como los mapeos). A diferencia de los mapeos, un diccionario
puede almacenar claves repetidas. Existen dos tipos de diccionarios:
-

Diccionarios no ordenados: las claves solo se comparan por igual.


Diccionarios ordenados: hay una relacin de orden total definida para las claves

Operaciones:
Dado un diccionario D no ordenado:

Size(): retorna el nmero de entradas de D.


isEmpty(): testea si D est vaco.
find(k): si D contiene una entrada e con clave igual a k, entonces retorna e, sino retorna
null.
findAll(k): retorna una coleccin iterable conteniendo todas las entradas con clave igual a
k.
insert(k,v): inserta en D una entrada e con clave k y valor v y retorna la entrada e.
remove(e): remueve de D una entrada e, retornando la entrada removida. Ocurre un error
si e no est en D.
entries(): retorna una coleccin iterable con las entradas clave-valor de D.

Tabla Hash:
Una de las formas ms eficientes de implementar un mapeo o diccionario es en ciertos
casos usando una tabla hash. Aunque, como vimos antes, el tiempo de ejecucin de las
operaciones de un mapeo con n entradas y una tabla hash es de O(n), las tabla hash puede
usualmente hacer que las operaciones sean O(1). En general, una tabla hash consiste de dos
componentes, un arreglo de buckets y una funcin hash
-

Hash abierto: consiste en mantener en cada componen de esta tabla hash una lista de
entradas. Las colisiones determinan ms de un elemento en cada lista. Para buscar,
insertar o eliminar una entrada a partir de una clave, aplicamos la funcin hash sobre
dicha clave, accedemos de forma constante al bucket y recorremos la lista de entradas
arreglo de buckets: un arreglo de cubetas para implementar una tabla de hash es un
arreglo A de n componentes, donde cada celda de A es una coleccin de pares clave-valor
funcin de hash H: dada una clave k y un valor v, h de k es un entero en el intervalo [0,n-1]
tal que la entrada (k, v) se inserta en la cubeta A[H(k)]
colisin: dada 2 claves k1 y k2 tales que k1 k2, se produce una colisin cuando H(k1)=H(k2)
(las entradas de una cubeta tienen claves colisionadas)

Hashin con claves genricas


-

Paso 1 (hash code): dada una clave k, obtener un nmero entero llamado cdigo de hash a
partir de K.
Paso 2 (funcin de compresin): a partir del cdigo de hash obtener un valor entre 0 y n-1
(mdulo de n [(ai+b)mod p]mod n donde ay b son enteros al azar y p es un primo mayor
a n).

Distribucin uniforme: todos los eventos tienen la misma probabilidad.


Distribucin uniforme de claves: la probabilidad de que una clave termine en un bucket
determinado es constante y es igual a 1/n donde n es la cantidad de buckets de la tabla hash.
-

Hash cerrado: En hash cerrado se tiene un arreglo de N buckets. Cada bucket almacena a
lo sumo una entrada. Dada la clave k y un valor v la funcin de hash H indica cual es la
componente H(k) del arreglo en la cual se almacena la entrada (k,v). Dada dos claves k1 y
k2 tales que k1 k2, si H(k1)=H(k2) entonces se produce una colisin.

Polticas para la resolucin de colisiones:


-

Lineal (Lineal Probing): si tratamos de insertar una entrada en un bucket A[i] que ya est
ocupado (H(k)=i), entonces tratamos de colocarlo en A[(i+1) mod N] y si ya est ocupado
A[(i+2) mod N] y asi sucesivamente hasta encontrar un lugar libre. Este mtodo conserva
espacio pero complica a la hora de remover. Adems la bsqueda a travs de muchas
celdas de la tabla hash ralentiza el proceso de bsqueda considerablemente.
Cuadrtica (quadratic Probing): involucra iterablemente tratar en los buckets
A[(i+f(j))modN] donde j es 0,1,2, y f(j)=j2. Aunque N sea primo esta estrategia podra no
encontrar un bucket vaco en A si el arreglo de buckets esta medio lleno.
Hash doble (Double Hashing): elegimos una segunda funcin hash H2, y si H mapea alguna
entrada a un bucket ocupado, entonces se trata con los buckets A[(i+f(j))modN] donde j es
0,1,2, y f(j)=j*H2(k). la segunda funcin hash no debe estar evaluada en 0. Una opcin
comn es H2(k)=q-(k mod q) para algn numero primo q<N, N debera ser primo tambin.

Estos mtodos ahorran ms espacio que el hash abierto pero no son necesariamente ms
rpidos. En resumen, si el espacio es un problema se deberan utilizar los mtodos de hash
cerrado, de lo contrario los mtodos de hash abierto resultan ser eficaz
Ventajas y desventajas
- Del lineal: el hashing lineal tiende a agrupar entradas con claves con mismo valor de hash.
Si el arreglo es muy pequeo, se mezclan las claves ki con distinto hash y la bsqueda se
hace muy lenta porque degenera en buscar linealmente en un arreglo. Para hacer que

esto funcin N tiene que ser mucho mayor que n con lo que las claves se agrupan por su
valor de hash ([GT] sugiere que n/N sea menor que 0.5=).
Del cuadrado: la ventaja es que evita los patrones de agrupamiento de hash lineal pero
crea otro tipo que se llama agrupamiento secundario. Si N no es primo, puede no
encontrar un slot vaco aunque exista.

Captulo 9 de [GT]
rbol binario de bsqueda (ABB)
Un ABB es una estructura de datos til para implementar conjuntos, mapeos y diccionarios. En
un ABB las claves en los nodos se hallan ordenadas de una manera particular. El tiempo de
insertar, recuperar y eliminar es proporcional a la altura de ABB. Si el rbol tiene n claves, la altura
del ABB se halla entre el log2n y n. una ABB es un rbol binario tal que:

Es vaco.
Es un nodo con rotulo k e hijos T izq y Tder tales:
K claves de Tizq.
K claves de Tder.
Tizq y Tder son ABB.

Insercin en un ABB: las nuevas claves siempre se insertan como hijo de un nodo hoja
Algoritmo:
Insertar(k, nodov)
//comienza en la raz
si nodov es vaco entonces
Crear un nodo hoja con rotulo k
sino
si k < clave(nodov) entonces
Insertar(k,hijo izquierdo de nodo v)
sino
si k < clave(nodov) entonces
Insertar(k, hijo derecho de nodo v)
sino
si k = clave(nodov) entonces
Reemplazar rotulo de nodo v
Tiempo de ejecucin: sea h = altura de ABB y sea n = cant claves de ABB

Con lo cual T(h) = O(h).


La altura en el peor caso es h=n (se da cuando se hicieron inserciones de claves en forma
ascendente o descendente). La altura en el mejor caso es h = log2 (las inserciones produjeron un
rbol balanceado)

Bsqueda:
Buscar(k,nodov)
//comienza en la raz
si el nodov es vacio entonces
return k no se encuentra en ABB
sino
si clave(nodov)=k entonces
return k si se encuentra en ABB
sino
si clave(nodov)>k entonces
return buscar(k, hijo izquierdo nodov)
sino //clave(nodov)<k
return buscar(k, hijo derecho nodov)
Tiempo de ejecucin: O(log2n) si el rbol esta balanceado y O(n) si no lo est.
Eliminacin:

Paso 1: buscar el nodo P con clave k a eliminar.


Paso 2 (cuatro casos):
P es una hoja: eliminarlo.
P tiene solo hijo izquierdo: hacer el by-pass del padre de P con el hijo izquierdo de P.
P tiene solo hijo der: hacer el by-pass del padre de P con el hijo der de P
P tiene dos hijos: reemplazar el rotulo de P con el de sucesor inorder y eliminar el sucesor
inorder de p.

Tiempo de eliminar: Teliminar(h) = O(h)


Variaciones:

Implementacin de mapeo con ABB: los nodos en lugar de solo claves tienen entradas (k, v).
Implementacin de diccionario:
Opcin 1 (ms sencilla): los nodos tienen una clave y una lista de entradas con la misma
clave. Tfind(n) = O(h+s) con n= cant entradas, h= altura de ABB y s= largo de la lista de
entradas.
Opcion2 (ms compleja): los nodos tienen una entrada y las claves repetiras se ramifican a
la derecha. Tfind(n) = O(h) (pero ojo, ahora h es potencialmente mayor a la altura de la
opcin 1). Capito 10 de [GT].

Grafos:
Un grafo G=(V,E) es un conjunto V de vrtices (o nodos) y un conjunto E, contenido en
VxV, de aristas o arcos. Intuitivamente E permite representar una relacin entre elementos de V.

Arco: un arco (u,v) puede ser:

Dirigido: (u,v) es un par ordenado.


No dirigido: (u,v) en realidad es {u,v} y (u,v) es lo mismo que (v,u).

Grafo dirigido (digrafo): sus arcos son dirigidos.


Grafo no dirigido (simplemente grafo): sus arcos son no dirigido.
Arcos e que inciden en un vrtice v: e = {(x,y) en E: y=v}.
Arcos e que emergen en un vrtice v: e = {(x,y) en E: x=v}.
Grado de incidencia/entrada de un vrtice v: Es la cantidad de arcos que inciden en v.
Grado de emergencia/salida de un vrtice v: Es la cantidad de arcos que emergen de v.
Grafo pesado: es un grafo donde las aristas contienen una etiqueta (o peso cuando las etiquetas
son numricas).
Multi(di)grafo: es un (di)grafo donde el conjunto de arcos es una coleccin. Es decir puede haber
ms de un arco entre cada par de vrtices (se llaman arcos paralelos).
Cmino: un camino es una secuencia alternante de vrtices y arcos tales que empieza en un
vrtice y termina en otro y cada arco es incidente en sus vrtices predecesor y sucesor.
Ciclo (simple): un camino que comienza y termina en el mismo vrtice () si repetir arcos.
Ciclo (camino) dirigido: un ciclo (camino) donde las aristas tienen direccin y son recorridos en su
direccin.
Sub-grafo: un sub-grafo H de un grafo G es un grafo donde los vrtices de H son un subconjunto de
los vrtices de G y los arcos de H son un subconjunto de los arcos de G.
Grafo abarcador: es un sub-grafo de G que contiene todos los vrtices de G.
Grafo conexo: un grafo G es conexo si para 2 vrtices cualquiera de G hay un camino entre ellos
Componentes conexas: si un grafo no es conexo sus sub-grafos maximales conexos se llaman
componentes conexos.
Bosque: un bosque es un grafo sin ciclos.
rbol: un rbol es un bosque conexo (un grafo conexo sin ciclos). Los arboles de los temas
anteriores se llaman con raz (rooted tree). Los rboles de grafos se llaman rboles libres (free
tree).
rbol abarcador: sub-grafo abarcador que es un rbol libre.

TDA Grafo
El tipo de dato abstracto exporta 3 sorts:
-

Graph<V;E>: es un grafo pesado de vrtices con rtulos de tipo V y arcos con rtulos de
tipo E.
Vertex<V>: la posicin de un vrtice con rotulo de tipo V.
Edge<E>: la posicin de un arco con rotulo de tipo E.

Mtodos de Graph
-

Vrtices(): retorna una coleccin iterable con todos los vetices del grafo
Edges(): retorna una coleccin iterable con todos los arcos del grafo.
incidenEdeges(v): retorna una coleccin iterable con todos los arcos incidentes sobre un
vrtice v.
emegergentEdges(v): (o successorEdges) retorna una coleccin iterable con todos los
arcos emergentes de un vrtice v.
opposite(v,e): retorna el otro vrtice w del arco e = (v,w). Ocurre un error si e no es
incidente o emergente de v.
endVertices(e): retorna un arreglo (de dos componentes) conteniendo los vrtices del arco
e.
areAdyacente(v,w): testea si los vrtices v y w son adyacentes.
replace(v,x): remplaza el rotulo del vrtice v con x.
replace(e,x): remplaza el rotulo del arco e con x.
insertVertex(x): inserta y retorna un nuevo vrtice con rotulo x.
insertEdge(v,w,x): inserta un arco con rotulo x entre los vrtices v y w.
insertDirectedEdge(v,w,x): inserta un arco dirigido con rotulo x entre los vrtices v y w.
removeVertex(v): elimina el vrtice v y todos sus arcos adyacentes y retorna el rotulo de v.
removeEdge(e): elimina el arco e y retorna el rotulo almacenado en e.

Estructura de datos para grafos:

Lista de arcos:

Lista de adyacencia:

Matriz de adyacencia:

Captulo 13 de [GT]
Recorridos de Grafos
-

En Profundidad (Depth-First Search o DFS): Equivale al recorrido pre o post orden en


rboles, ms un testeo para no volver a recorrer un sub-grafo ya explorado. Una bsqueda
en profundidad permite recorrer todos los vrtices de un grafo de manera ordenada. Su
funcionamiento consiste en ir expandiendo todos y cada uno de los nodos que va
localizando, de forma recurrente, en un camino concreto. Cuando ya no quedan ms
nodos que visitar en dicho camino, regresa (backtracking), de modo que de repite el
mismo proceso con cada uno de los hermanos del nodo ya procesado.
Algoritmo:
DFSShell( G : Grafo )
para cada vrtice v de G hacer
marcar v como no visitado
para cada vrtice v de G hacer
si v no est visitado entonces
DFS( G, v )
DFS( G : Grafo; v : Vrtice )
procesamiento de v previo al recorrido
marcar a v como visitado
para cada vrtice w adyacente a v en G hacer
si w no est visitado entonces
DFS( G, w )
procesamiento de v posterior al recorrido

Tiempo de ejecucin: TDFS(n,m) = O(n+m).

Opciones para implementar las marcas de visitado

Usar un mapeo externo al grafo de Vertex<V> en Boolean


o Ventaja: No hay que modificar el grafo que ya programamaos.
o Desventaja: El tiempo de marcar y desmarcar puede tendeer a O(n)
Agregar un boolean a la clase Vertice de Grafo
o Desventaja: Por cada algoritmo que escribo tengo que ensuciar el grafo
agregando atributos.
Decorar los vrtices del Grafo
o Ventaja: En forma abstracta mantengo toda la informacin del DFS y de
futuros algoritmos.
o Desventajas: Hay que modificar lo que ya programamos.

Bosque del DFS


Al orientar los arcos en la direccin en la que son explorados durante el recorrido, se
distinguen:

Arcos de descubrimiento o rbol (discovery o tree edges): Arcos que llevan a


vrtices no visitados.
Arcos de retroceso (back edges): Arcos que llevan a vrtices que ya fueron
visitados.

Algoritmo:
DFS( G : Grafo; v : Vrtice )
Marcar a v como visitado
para cada arco e en G.incidentEdges(v) hacer
si e no est visitado entonces
w G.opposite(v, e )
si w no est visitado entonces
etiquetar a e como arco de descubrimiento
DFS( G, w )
sino
etiquetar a e como arco de retroceso
Tiempo de ejecucin:
TDFS(n,m) = O(n+m) con lista de adyacencia
TDFS(n,m) = O(n2) con matriz de adyacencia
TDFS(n,m) = O(n+m) con arcos decorados (asumiendo operaciones de mapeo en O(1))

Aplicaciones del DFS para Grafos no dirigidos en O(n+m)


Testear si un grafo G es conexo (todos los vrtices quedan visitados si y slo si el
grafo es conexo)
Calcular un rbol abarcador si G es conexo (formado por arcos tree)
Calcular las componentes conexas (por cada iteracin del DFSShell incremento un
contador indicando el nmero de componente conexa y con ese contador
etiqueto los vrtices de cada componente)
Encontrar un camino entre dos nodos.
Encontrar un ciclo.

En Anchura (Breadth-First Seach o BFS): Equivale al recorrido por niveles en rboles, ms


un testeo para no volver a recorrer un sub-grafo ya explorado. La bsqueda en anchura es
un algoritmo para recorrer o buscar elementos de un grafo. Se comienza eligiendo algn
nodo como elemento de la raz y se exploran los vecinos de este nodo. A continuacin,
para cada uno de los vecinos, se exploran sus respectivos vecinos adyacentes, y as hasta
que se recorra todo el grafo.
Algoritmo:
BFSShell( G : Grafo )
para cada vrtice v de G hacer
marcar v como no visitado
para cada vrtice v de G hacer
si v no est visitado entonces
BFS( G, v )
BFS( G : Grafo; v : Vrtice )
cola new Cola()
cola.enqueue( v )
mientras not cola.isEmpty() hacer
w cola.dequeue()
procesar a w
marcar a w como visitado
para cada vrtice x adyacente a w hacer
si x no est visitado entonces
cola.enqueue( x )

Tiempo de ejecucin: Sea un Grafo G = (V,A), sean n la cantidad de vrtices y m la cantidad


de arcos. Para simplificar el anlisis, supongamos que el grafo es conexo. Sea A i la cantidad de
adyacentes del vrtice i.

T(n,m) = c1 + ni=1 (c2 + Aij=1 c3)


= c1 + ni=1 (c2 + Ai*c3)
= c1 + ni=1 c 2 + ni=1 Ai*c3
= c1 + nc2 + mc3 = O(n+m)
TBFS(n,m) = O(n+m)
Aplicaciones del BFS
Idem al DFS y adems:

Hallar el camino ms corto (en calidad de arcos) entre dos vrtices (en O(n+m)).

Captulo 13 de [GT].
Algoritmos para encontrar caminos en Digrafos pesados con nmeros reales
-

DFS Pinchado: Permite encontrar un camino entre dos vrtices v y w.

Algoritmo (Hallar camino)


HallarCamino(G, origen, destino, camino) : boolean
origen.put(Estado, Visitado)
camino.addLast(origen)
si origen = destino entonces
retornar verdadero
sino
para cada adyacente v de origen en G hacer
si v.get(Estado) = NoVisitado entonces
encontr HallarCamino(G,v,destino,camino)
si encontr entonces
retornar verdadero
//Cuando no encontr, hago bactracking. Borro origen del camino
camino.remove(camino.last())
retornar falso
Tiempo de ejecucin: Tpinchado(n,m) = O (n+m)

Algoritmo (Hallar ciclo):


HallarCiclo(G, v, ciclo)
para cada adyacente w de v en G hacer
encontr HallarCamino(G,v,w,camino)
si encontr entonces
ciclo.addLast(v)
para cada vrtice x de camino hacer
ciclo.addLast(x)

DFS con bactracking, marca y desmarca: Permite encontrar un camino de costo mnimo
entre dos vrtices v y w. Al comienzo, el camino actual es una lista vaca. El costo del
camino es la suma de los pesos de los arcos del camino.

Algoritmo:
HallarCaminoMinimo(G, origen, destino, camino_actual, camino_minimo)
origen.put( Estado, Visitado )
camino_actual.addLast( origen )
si origen = destino entonces
Si costo( camino_actual ) < costo( camino_minimo ) entonces
camino_minimo camino_actual
Sino
para cada adyacente v de origen en G hacer
si v. get ( Estado ) = NoVisitado entonces
HallarCaminoMinimo( G, v, destino, camino_actual, camino_minimo )
camino.remove( camino.last() ) //Backtracking
origen.put( Estado, NoVisitado )
Tiempo de ejecucin: TcaminoMin(n,m) = O(n!)
-

Dijkstra: Permite hallar todos los camino de costo mnimo entre un vrtice v y todos los
otros vrtices. Supongamos un Digrafo G=(V,E) tal que cada arco tiene costo no negativo.
Hay un vrtice que se conoce como la fuente. El costo del camino es la suma de los pesos
de los arcos del camino. El algoritmo mantiene un conjunto S con los vrtices cuyo camino
con la distancia ms corta es conocida. S es inicialmente contiene slo la fuente. En cada
paso se agrega a S el vrtice v cuya distancia a la fuente es tan cercana cmo es posible. El
algoritmo termina cuando S contiene todos los vrtices. D(v) contiene la distancia a v
desde la fuente.

Algoritmo:
Dijkstra //Asumimos que la fuente es 1
S{1}
para i 2 a n hacer
D(i) peso del arco de 1 a i // si no hay arco
P(i) 1 //Para ir a i pasar por 1 (camino directo)
para i 1 a n-1 hacer
elegir vrtice w en V-S tal que D(w) es mnimo
agregar w a S
para cada vrtice v en V-S hacer
si D(w) + peso_arco(w,v) < D(v) entonces
D(v) D(w) + peso_arco(w,v)
P(v) w

TDijkstra(n) = O(n2) si G tiene n vrtices y est representado con matriz.


TDijkstra(n,m) = O(m*log(n)) (son m actualizaciones a una cola con prioridades adaptable de
n elementos), si G est representado con listas de adyacencias.
Recuperacin del camino en Dijkstra
Algoritmo
recuperar( P, destino )
cola new Cola()
cola.enqueue( 1 ) //encolo la fuente
recuperar_aux( P, destino, cola )
retornar cola
recuperar_aux( P, v, cola )
anterior P(v)
si anterior = 1 entonces
//el camino es directo (xq el anterior es la fuente)
//y terminamos
sino
recuperar_aux( P, anterior, cola )
cola.enqueue( anterior )

Floyd: Permite hallar el camino de costo mnimo entre cada par de vrtices v y w. Dado un
Digrafo pesado G=(V,A) donde cada arco tiene un peso no negativo. Queremos calcular los
caminos de costo mnimo de todos los vrtices a todos los vrtices. Supongamos que C(i,j)

de A. Usaremos una matriz A de nxn tal que inicialmente A(i,j)=C(i,j), o si no hay arco
entre i y j. En la iteracin k-sima veremos si actualizamos a A de acuerdo a:
Ak(i,j) = min(Ak-1(i,j), Ak-1(i,k) + Ak-1(k,j)).

k
Ak-1(k,j)

Ak-1(i,k)

i
Ak-1(i,j)
Algoritmo

Floyd
Para i1..n hacer
para j 1..n hacer
si hay arco (i,j) entonces A(i,j) C(i,j)
sino A(i,j)
P(i,j) 0 //por defecto el camino es directo
para i 1 .. n hacer
A(i,i) 0
para k 1..n hacer
para i 1..n hacer
para j 1..n hacer
si a(i,k) + a(k,j) < a(i,j) entonces
a(i,j) a(i,k) + a(k,j)
p(i,j) k
Tiempo de ejecucin: O(n3).
Recuperacin del camino en Floyd
Algoritmo
//Recupera el camino de i a j y lo almacena en cola
RecuperarCamino( P, cola, i, j )
k P(i,j)
si k 0 entonces
RecuperarCamino( P, cola, i, k )
cola.enqueue( k )
RecuperarCamino( P, cola, k, j )

Procesamiento de Texto

Tries: un trie es un rbol que se usa para implementar pattern matching en forma eficiente. La
aplicacin fundamental es la recuperacin. Un trie se usa para implementar un conjunto S de
String o un mapeo M de String en un tipo E. Un trie es un rbol que factoriza prefijos comunes
entre las cadenas del conjunto S o claves de M. Los caminos de la raz a las hojas representan
las palabras de S o las claves de M.

Definicin de Trie: Sea S un conjunto de string sobre un alfabeto . Un trie para S es un rbol
ordenado T tal que:

Cada nodo de T, excepto la raz, est etiquetado con un carcter de .


El orden de los hijos de un nodo interno de T est determinado por el orden cannico de
.
T tiene s nodos externos, cada uno asociado con un string de S, tal que la concatenacin
de los rtulos de los nodos del camino de la raz a una hoja v produce el string de S
asociado a v.

Propiedades de un Trie: Un trie almacenando una coleccin S de s strings de longitud total n sobre
un alfabeto de tamao d cumple:

Cada nodo interno de T tiene a lo sumo d hijos.


T tiene s nodos externos.
La altura de T es igual a la longitud del string ms largo de S.
El nmero de nodos de T es O(n).

Orden de tiempo de un Trie: Sea un conjunto S implementado con nodo trie T sobre un alfabeto .
Sea s la cardinalidad de S, d la cardinal de , y m el largo de un string a procesar:

Tinsert(s,d,m) = O(m)
Tlookup(s,d,m) = O(m)
Tdelete(s,d,m) = O(dm)

Aplicaciones de un Trie: Word matching: Dado un documento determinar todas las apariciones de
una palabra determinada. La solucin es construir un trie donde por cada palabra se almacena la
lista de posiciones (una lista de enteros) de las apariciones de la palabra.
Captulo 12 de [GT]

ndices invertidos: La estructura de datos fundamental de un motor de bsqueda es el ndice


invertido o archivo invertido. El ndice invertido es un mapeo donde por cada trmino t se

almacena la lista L de documentos web donde aparece t. El mapeo se puede implementar con
un trie. La lista L contiene las URLs de los documentos y la copia encontrada por el buscador
(la lista se almacena en disco). En general no se almacenan las stop words (artculos,
preposiciones, etc). Los trminos se pueden stemmizar (quedarse slo con la raz). La lista L
puede ser una cola con prioridad donde los documentos se rankean por importancia.
Compresin de datos
La compresin de datos consiste en la reduccin del volumen de informacin tratable
(procesar, transmitir o grabar). En principio, con la compresin se pretende transportar la
misma informacin, pero empleando la menor cantidad de espacio.

Compresin sin prdida de informacin: Los datos antes y despus de comprimirlos son
exactos en la compresin sin prdida. En el caso de la compresin sin prdida una mayor
compresin solo implica ms tiempo de proceso. Se utiliza principalmente en la
compresin de texto.
Compresin con prdida de informacin: Puede eliminar datos para reducir an ms el
tamao, con lo que se suele reducir la calidad. Hay que tener en cuenta que una vez
realizada la compresin, no se puede obtener la seal original, aunque s una
aproximacin cuya semejanza con la original depender del tipo de compresin. Se utiliza
principalmente en la compresin de imgenes, videos y sonidos.

Huffman: En lugar de usar un nmero fijo de bits para codificar cada carcter de un string X,
los caracteres que ms se usan se codifican con menos bits y los que menos se usan se
codifican con ms bits. Por cada carcter es necesario conocer su frecuencia de aparicin. Es
decir, por cada carcter c tendremos f(c) que es la cantidad de apariciones de c en la cadena X
a comprimir. La concatenacin de los bits de la compresin de los caracteres de la cadena
forman el string comprimido.
Cdigo prefijo: Para evitar ambigedades, no va a haber ningn cdigo que sea prefijo de otro.
Huffman (Idea)
Construye un rbol binario T que representa la codificacin para una cadena X. Cada nodo,
excepto la raz, representa un bit del cdigo. El hijo izquierdo representa un 0 y el derecho un
1. Cada hoja representa un carcter c. La codificacin de un carcter c se define como la
secuencia de bits determinada por el camino de la raz a la hoja que contiene a c en el rbol T.
Cada hoja tiene una frecuencia f(v) correspondiente a la frecuencia de carcter c almacenado
en v. Cada nodo interno tiene una f(v) que corresponde a la suma de la frecuencias de los
caracteres en dicho subrbol.

Algoritmo
Huffman (X)
Entrada: Un string X de longitude n sobre alfabeto de tamao d.
Salida: rbol para codificar X.
Computar la frecuencia f(c) para cada carcter c de X
Crear una cola con prioridad C
para cada carcter c en X hacer
crear un rbol binario hoja T con rtulo c
insertar T en Q con prioridad f(c)
mientras Q.size() > 1 hacer
f1 Q.min().key();
T1 Q.removeMin();
f2 Q.min().key();
T2 Q.removeMin();
Crear un Nuevo rbol binario T con hijo izquierdo T 1 e hijo derecho T2
Insertar T en Q con prioridad f1+f2
retornar el rbol Q.removeMin()

Arboles Balanceados

AVL: Es un rbol binario de bsqueda con una restriccin para mantener una altura del rbol
proporcional al logaritmo de la cantidad de nodos del rbol. El tiempo de bsqueda, insercin
y borrado en un rbol binario de bsqueda es lineal en la altura del rbol. Entonces, si n es la
cantidad de elementos de un rbol T, tendramos as que T(n) = O(log2(n)).
Propiedad del balance de la altura
Para cada nodo interno v de T, las alturas de los hijos difieren a lo sumo en 1. Cualquier ABB
que satisface esta propiedad se dice rbol AVL.

Como un AVL es un rbol binario de bsqueda, la operacin de bsqueda no sufre


alteraciones. Las nicas operaciones a modificar son la de insercin y eliminacin, las cuales
deben verificar que se cumpla la propiedad de balance al finalizar la operacin. Luego de cada
modificacin en un nodo, rebalancearn los hijos de dicho nodo en O(1) por medio de las
llamadas rotaciones. Las modificaciones se hacen desde la hoja donde se insert el nodo
hacia la raz siguiendo el camino de las llamadas recursivas.
Rotaciones
Rotacin izq-izq (Simple izquierda)

Rotacin izq-der (doble izquierda)

Rotacin der-der (simple derecha)

Rotacin der-izq (doble derecha)

Eliminacin en un AVL
Es idntica a la de un ABB pero en este caso, cada vez que se sale de la recursin es necesario
verificar de qu lado se elimin un nodo para realizar el rebalanceo.

rbol 2-3: Un rbol 2-3 es un rbol tal que cada nodo interno (no hoja) tiene dos o tres hijos, y
todas las hojas estn al mismo nivel. La definicin recursiva es:
T es un rbol 2-3 de altura h si
T es vaco (es decir de altura -1)
T es de la forma
Donde n es un nodo y Ti y Td son rboles 2-3, cada uno de altura h-1.
Ti se dice subrbol izquierdo y Td subrbol derecho.

T es de la forma
Donde n es un nodo y Ti, Tm y Td son rboles 2-3, cada uno de
altura h-1. Ti se dice subrbol izquierdo, T m se dice
subrbol medio y Td subrbol derecho.

Propiedad: Si un rbol 2-3 no contiene ningn nodo con 3 hijos entonces su forma
corresponde a un rbol binario lleno.
rbol 2-3 de bsqueda
Un rbol 2-3 es un rbol 2-3 de bsqueda si T es un rbol 2-3 tal que:

T es vaco (es decir de altura -1)


T es de la forma
n contiene una clave k, y k es mayor que las clases de Ti, k es
menor que las claves de Td, Ti y Td son rboles 2-3 de bsqueda.

T es de la forma
n contiene dos claves k1 y k2, y k1 es mayor que las claves de
Ti, k1 es menor que las claves de Tm, k2 es mayor que las claves
de Tm, k2 es menor que las claves de Td. Ti, Tm y Td son rboles
2-3 de bsqueda.
Reglas de Bsqueda
o Si n tiene dos hijos, entonces contiene una entrada
o Si n tiene tres hijos, entonces contiene dos entrada
o Si n es una hoja, entonces contiene una o dos entrada
Algoritmo

Recuperar( T, clave ) --> valor


R raz de T
sI clave est en R entonces
retornar valor igual a valor asociado a la entrada
sino
si R es una hoja entonces retornar nulo // Falla
sino
si R tiene una entrada entonces
k la clave de R
si clave < k entonces
retornar Recuperar( Ti(T), clave )
sino
retornar Recuperar( Td(T) clave )
sino
si R tiene dos entradas entonces
k1 y k2 las claves de R
si clave < k1 entonces
retornar Recuperar( Ti(T), clave )
sino
si clave < k2 entonces
retornar Recuperar( Tm(T), clave )
sino
retornar Recuperar( Td(T), clave )

Insertar en un rbol 2-3 de bsqueda


Para insertar un valor X en un rbol 2-3, primero hay que ubicar la hoja L en la cual X
terminar primero hay que ubicar la hoja L en la cual X terminar. Si L contiene ahora dos
valores, terminamos. Si L contiene tres valores, hay que partirla en dos hojas L1 y L2. L1 se

queda con el valor ms pequeo, L2 con el ms grande, y el del medio se manda al padre P de
L. Los nodos L1 y L2 se convierten en los hijos de P.
Si P tiene slo 3 hijos (y 2 valores), terminamos. En cambio, si P tiene 4 hijos (y 3 valores), hay
que partir a P igual que como hicimos una hoja slo que hay que ocuparse de sus 4 hijos.
Partimos a P en P1 y P2, a P1 le damos la clave ms pequea de los dos hijos de la izquierda y a
P2 le damos la clave ms grande y los dos hijos de la derecha.
Luego de esto, la entrada que sobra se manda al padre de P en forma recursiva. El proceso
termina cuando la entrada sobrante termina en un nodo con dos entradas o el rbol crece 1
en altura (al crear una nueva raz).

rboles 2-3-4: Un rbol 2-3-4 tiene hojas con 1,2 o 3 claves, y sus nodos internos contienen:
1 clave y 2 hijos
2 claves y 3 hijos
3 claves y 4 hijos
Todas las hojas tienen la misma profundad.
Insercin en un rbol 2-3-4: Es igual que en un rbol 2-3 excepto que cuando hay overflow (4
claves en un nodo), se parte el nodo y van 2 claves al nodo izquierdo y 1 clave al nodo de la
derecha, la tercera clave va al padre y as sucesivamente.

Captulo 10 de [GT]

rboles Red-Black: Un rbol Red-Black es un tipo especial de rbol binario de bsqueda en el


que cada nodo tiene un atributo de color cuyo valor es rojo o negro. Adems de los requisitos
impuestos a los rboles binarios de bsqueda convencionales, se deben satisfaces las
siguientes reales para tener un rbol Red-Black vlido:
Todo nodo es o bien rojo o bien negro.
La raz es negra.
Todas las hojas (Null) son negras.
Todo nodo rojo debe tener dos hijos negros.
Cada camino desde un nodo dado a sus hojas descendientes contiene el mismo nmero
de nodos negros.
El camino ms largo desde la raz hasta una hoja no es ms largo que dos veces el camino ms
corto desde la raz a una hoja.

Ordenamiento
Dado un arreglo a de n componentes enteras a[0], a[1], , a[n-1] se desea obtener una
permutacin de a tal que a[0] a[1] a[n-2] a[n-1].

Multipasada: O(n2)
o

Seleccin (selection sort): Haremos n-1 pasadas sobre el arreglo a. En la pasada isima, encontraremos el i-simo menos elemento del arreglo y lo
intercambiaremos con a[i].

Burbuja (bubble sort) o intercambio (Exchange sort): En cada pasada el burbuja


mira dos elementos adyacentes y los intercambia si estn fuera de orden. En cada
pasada, el mayor elemento del arreglo queda al final del sub-arreglo que se est
ordenando. Son necesarias n-1 pasadas (ya que el primer elemento queda
ordenado gratis).

Insercin (insertion sort): Es equivalente a la forma de ordenar un mazo de cartas.


Se comienza con un mazo vaco y uno desordenado. Cada carta se trata de insertar
en la posicin correcta. Entonces, en un momento dado, una parte del mazo est
ordenada y se trata de insertar la siguiente carta de la porcin desordenada del
mazo en la posicin correcta. Terminamos cuando la porcin desordenada est
vaca.

Merge sort: O(n*log2(n)):


o Caso recursivo: Partir el arreglo en dos, ordenar recursivamente cada mitad y
luego hacer la mezcla de cada mitad ordenada en un gran arreglo ordenado.
o Caso base: El arreglo tiene 0 o 1 componente entonces est ordenado.

Heap sort: O(n*log2(n))


Algoritmo
Heap Sort (a,n)
cola new ColaConPrioridad()
para I 0..n-1 hacer
cola.insert(a[i])
para I 0..n-1 hacer
a[i] cola. removeMin()

Quick sort: Quick Sort en promedio corta el arreglo por la mitad, como no hace el Merge,
en promedio es ms eficiente que el Merge sort con una complejidad de O(n*log2(n)). Sin
embargo, el peor caso se da cuando se quiere ordenar un arreglo ordenado, se invoca
recursivamente con una parte que mide 1 y la otra n-1, dando una complejidad de O(n2).
Algoritmo
Quick Sort
si la lista es no vaca entonces
1. Dividir la lista en dos de tal manera que los tems en la
primera mitad vengan antes que los tems en la segunda
mitad.
2. Ordenar con Quick Sort la primera mitad.
3. Ordenar con Quick Sort la segunda mitad.

Serializacin
La serializacin implica salvar el estado actual de un objeto en un stream y luego poder
recuperar el objeto equivalente de tal stream.
Archivos de accesos directo
Los archivos de acceso directo (Random Access File) permiten:

Leer los registros de un archivo en cualquier orden.


Modificar un registro cualquiera sin necesidad de reescribir todo el archivo.
Agregar un registro nuevo al final del archivo.

Tendremos una operacin ms que se llama seek que recibe el nmero de byte al que hay que
mover el puntero de archivo para realizar la prxima operacin de lectura o escritura. Para utilizar
seek es necesario conocer el tamao del registro del archivo subyacente.
Archivos Indizados (o Indexados)
Los archivos indexados tuenen un orden virtual determinado por el ordenamiento de una clave.
-

Implementacin de archivos indexados


o Por cada tabla, hay al menos dos archivos:
Un archivo de datos donde cada registro tiene tamao fijo.
Un archivo de ndice; un mapeo de clave en nmero de registro (contiene
adems la cantidad de registros del archivos de datos).
Cada clave extra de bsqueda requiere otro ndice (pero no otro archivo
de datos, como por ejemplo, buscar/ordenar alumnos por legajos, DNI,
nombre, etc).
Implementaciones para el ndice
o Arreglo ordenado
Bsqueda en orden logartmico
Las actualizaciones implican reordenar el arreglo en orden n*log(n).
o rbol binario de bsqueda
Puede denegar en orden lineal para buscar y actualizar pero se espera
orden logartmico.
o AVL, 2-3
Buscar y actualizar en orden logartmico.
o rbol B y B+
Para grandes volmenes de datos las opciones anteriores no son viables.
El rbol b generaliza la idea del rbol 2-3 con un gran nmero M de claves
en cada nodo.
El rbol B+ almacena entradas (clave, valor) slo en las hojas, los nodos
internos almacenan solo claves que sirven para guiar la bsqueda.

rbol B
El rbol B generaliza la idea del rbol 2-3 con un nmero M de claves en cada nodo. El tiempo de
bsqueda y actualizacin es proporcional al log M(cantidad de claves). Se puede desperdiciar
espacio en os nodos.

rbol B+
El rbol B+ almacena entradas (clave, valor) slo en las hojas, los nodos internos almacenan solo
claves que sirven para guiar la bsqueda.

Sntesis
Estructura de Datos
Arreglo

Arreglo Ordenado
Pila
Cola
-

Ventajas
Insercin rpida.
Acceso rpido si el ndice es
conocido.
Bsqueda ms rpida con
respecto a los arreglos no
ordenados.
Rpido acceso al elemento
tope.
Rpida insercin.
Rpido acceso al elemento
frente.
Rpida insercin.

Desventajas
Bsqueda y eliminacin lenta.
Tamao fijo.

Insercin y eliminacin lenta.


Tamao fijo.

Acceso lento a los dems


elementos de la estructura.

Acceso lento a los dems


elementos de la estructura.

Lista Enlazada

rbol Binario
rbol Red-Black
rbol

rbol 2-3-4

Tabla Hash

Rpida eliminacin e
insercin.
Rpida bsqueda, insercin
y eliminacin (si el rbol
esta balanceado).
Rpida bsqueda.
Rpida insercin y
eliminacin.
Rpida bsqueda, insercin
y eliminacin.
El rbol se mantiene
siempre balanceado.
Muy rpido acceso si la
clave es conocida.
Rpida insercin.

Bsqueda lenta.

Algoritmo de eliminacin
complejo.

Implementacin compleja.

Su implementacin es
compleja.

Eliminacin lenta.
Acceso lento si la clave es
desconocida.
Utilizacin de memoria
ineficiente.
Acceso lento a los dems
elementos.

Heap

Grafo

Rpida insercin y
eliminacin.
Acceso directo al mayor
elemento.
Muchas situaciones de la
vida real son resueltos con
grafos.

Algunos algoritmos son lentos


y muy complejos.

You might also like