Professional Documents
Culture Documents
Ca p t u lo 6
Algor it m os d e Or d en a m ien t o
6 . 1 Con cep t o d e Or d en a m ien t o
DEFI NI CI N.
En t r a d a : Una secuencia de n nmeros <a1, a2 , , an >, usualmente en la
forma de un arreglo de n elementos.
S a l i d a : Una permutacin <a1, a2 , , an > de la secuencia de entrada tal
que a1 = a2 = = an.
CONSI DERACI ONES. Cada nmero es normalmente una clave que forma
parte de un registro; cada registro contiene adems datos satlites que se
mueven junto con la clave; si cada registro incluye muchos datos satlites,
entonces movemos punt eros a los registros (y no los registros).
Un mtodo de ordenacin se denomina e s t a b le si el orden relativo de los
elementos no se altera por el proceso de ordenamiento. (Importante cuanto
se ordena por varias claves).
Hay dos categoras importantes y disjuntas de algoritmos de ordenacin:
Or d en a ci n i n t er n a : La cantidad de registros es suficientemente
pequea y el proceso puede llevarse a cabo en memoria.
Or d en a ci n ex t er n a : Hay demasiados registros para permitir
ordenacin interna; deben almacenarse en disco.
Por ahora nos ocuparemos slo de ordenacin interna.
Los algoritmos de ordenacin interna se clasifican de acuerdo con la
cantidad de trabajo necesaria para ordenar una secuencia de n elementos:
Cuntas com p a r a cion es de elementos y cuntos m ovi m i e n t os de
elementos de un lugar a otro son necesarios?
Empezaremos por los mtodos tradicionales (insercin y seleccin) . Son
fciles de entender, pero ineficientes, especialmente para juegos de datos
grandes. Luego prestaremos ms atencin a los ms eficientes: heapsort y
quicksort .
Pgina 64
6 . 2 Or d en a m ien t o p or I n s er cin
Este es uno de los mtodos ms sencillos. Consta de tomar uno por uno los
elementos de un arreglo y recorrerlo hacia su posicin con respecto a los
anteriormente ordenados. As empieza con el segundo elemento y lo ordena
con respecto al primero. Luego sigue con el tercero y lo coloca en su posicin
ordenada con respecto a los dos anteriores, as sucesivamente hasta recorrer
todas las posiciones del arreglo.
Este es el algoritmo:
Sea n el nmero de elementos en el arreglo A.
I NSERTION-SORT(A) :
{Para cada valor de j, inserta A[j] en la posicin que le corresponde en la
secuencia ordenada A[1 .. j 1]}
for j 2 t o n d o
k A[j]
i j 1
wh i l e i > 0 A[i] > k d o
A[i + 1] A[i]
i i 1
A[i + 1] k
An li s i s del a lgor it mo:
Nmero de comparaciones: n(n-1)/ 2 lo que implica un T(n) = O(n
2
). La
ordenacin por insercin utiliza aproximadamente n
2
/ 4 comparaciones y
n
2
/ 8 intercambios en el caso medio y dos veces ms en el peor de los casos.
La ordenacin por insercin es lineal para los archivos casi ordenados.
6 . 3 Or d en a m ien t o p or Seleccin
El mtodo de ordenamiento por seleccin consiste en encontrar el menor de
todos los elementos del arreglo e intercambiarlo con el que est en la primer a
posicin. Luego el segundo ms pequeo, y as sucesivamente hasta ordenar
todo el arreglo.
SELECTION-SORT(A) :
{Para cada valor de j, selecciona el menor elemento de la secuencia no
ordenada A[j .. n] y lo intercambia con A[j]}
for j 1 t o n 1 d o
k j
for i j + 1 t o n d o
i f A[i] < A[k ] t h e n k i
in t e r ca m b ie A[j] A[k]
Pgina 65
Anlisis del algoritmo:
La ordenacin por seleccin utiliza aproximadamente n
2
/ 2 comparaciones y
n intercambios, por lo cual T(n) = O(n
2
).
6.4 Or d e n a m ien t o d e la Bu r bu ja ( Bu bb les or t )
El algoritmo bubblesort , tambin conocido como ordenamiento burbuja,
funciona de la siguiente manera: Se recorre el arreglo intercambiando los
elementos adyacentes que estn desordenados. Se recorre el arreglo tantas
veces hasta que ya no haya cambios que realizar. Prcticamente lo que hace es
tomar el elemento mayor y lo va recorriendo de posicin en posicin hasta
ponerlo en su lugar.
Procedimiento Bu b b leS or t
for (i = n; i >= 1; i-- )
f or (j = 2; j <= i; j++)
{ i f (A[j-1] > A[j]) t h en intercambie(A, j- 1, j);
}
An lis is d el a lgor it m o:
La ordenacin de burbuja tanto en el caso medio como en el peor de los casos
utiliza aproximadamente n
2
/ 2 comparaciones y n
2
/ 2 intercambios, por lo cual
T(n) = O(n
2
).
6.5 Or d en a m ien t o R p id o ( Qu ick sor t )
Vimos que en un algoritmo de ordenamiento por intercambio, son
necesarios intercambios de elementos en sublistas hasta que no son posibles
ms. En el burbujeo, son comparados tems correlativos en cada paso de la
lista. Por lo tanto para ubicar un tem en su correcta posicin, pueden ser
necesarios varios intercambios.
Veremos el sort de intercambio desarrollado por C.A.R. Hoare conocido
como Qu ick sor t . Es ms eficiente que el burbujeo (bubblesort ) porque los
intercambios involucran elementos que estn ms apartados, entonces
menos intercambios son requeridos para poner un elemento en su posicin
correcta.
La idea bsica del algoritmo es elegir un elemento llamado p i vo t e, y
ejecutar una secuencia de intercambios tal que todos los elementos
menores que el pivot e queden a la izquierda y todos los mayores a la
derecha.
Pgina 66
Lo nico que requiere este proceso es que todos los elementos a la izquierda
sean menores que el pivot e y que todos los de la derecha sean mayores luego
de cada paso, no importando el or d en entre ellos, siendo precisamente esta
flexibilidad la que hace eficiente al proceso.
Hacemos dos bsquedas, una desde la izquierda y otra desde la derecha,
comparando el pivot e con los elementos que vamos recorriendo, buscando
los menores o iguales y los mayores respectivamente.
DESCRI PCI N. Basado en el paradigma dividir -y-conquistar, estos son los
tres pasos para ordenar un subarreglo A[p r]:
Di vi d i r . El arreglo A[p r] es particionado en dos subarreglos no vacos
A[p q] y A[q+1 r]cada dato de A[p q] es menor que cada dato
de A[q+1 r]; el ndice q se calcula como parte de este proceso de
particin.
Con q u i s t a r . Los subarreglos A[p q] y A[q+1 r] son ordenados
mediante sendas llamadas recursivas a QUICKSORT.
Co m b i n a r . Ya que los subarreglos son ordenados in sit u, no es necesario
hacer ningn trabajo extra para combinarlos; todo el arreglo A[p r]
est ahora ordenado.
QUICKSORT (A, p, r) :
if p < r t h en
q PARTITION(A, p, r)
QUICKSORT(A, p, q)
QUICKSORT(A, q+1, r)
PARTITION (A, p, r) :
x A[p]; i p1; j r+1
w h i le
r ep ea t j j1 u n t il A[j] = x
r ep ea t i i+1 u n t il A[i] = x
i f i < j t h e n
intercambie A[i] A[j]
els e ret u rn j
Para ordenar un arreglo completo A, la llamada inicial es QUICKSORT(A, 1, n).
PARTITION reordena el subarreglo A[p r] in situ, poniendo datos menores
que el p i v o t e x = A[p] en la parte baja del arreglo y datos mayores que x en
la parte alta.
An li s i s d el a lgor it m o:
Depende de si la particin es o no balanceada, lo que a su vez depende de
cmo se elige los pivotes:
Si la particin es balanceada, QUICKSORT corre asintticamente tan
rpido como ordenacin por mezcla.
Pgina 67
Si la particin es desbalanceada, QUICKSORT corre asintticamente tan
lento como la ordenacin por insercin.
El peor caso ocurre cuando PARTITION produce una regin con n1
elementos y otra con slo un elemento.
Si este desbalance se presenta en cada paso del algoritmo, entonces, como la
particin toma tiempo (n) y (1) = (1), tenemos la recurrencia:
(n) = (n 1) + (n) = (k)
k =1
n
= (n
2
).
Por ejemplo, este tiempo (n
2
) de ejecucin ocurre cuando el arreglo est
completamente ordenado, situacin en la cual INSERTIONSORT cor re en
tiempo (n).
Si la particin produce dos regiones de tamao n/ 2, entonces la recurrencia
es:
(n) = 2(n/ 2) + (n) = (n log n).
Tenemos un algoritmo mucho ms rpido cuando se da el mejor caso de
PARTITION.
El caso promedio de QUICKSORT es mucho ms parecido al mejor caso que al
peor caso; por ejemplo, si PARTITION siempre produce una divisin de
proporcionalidad 9 a 1:
o Tenemos la recurrencia (n) = (9n/ 10) + (n/ 10) + n.
o En el rbol de recursin, cada nivel tiene costo n (o a lo ms n ms
all de la profundidad log
10
n), y la recursin termina en la
profundidad log
10 / 9
n = (log n)
o el costo total para divisiones 9 a 1 es (nlog n), asintticamente lo
mismo que para divisiones justo en la mitad.
o Cualquier divisin de proporcionalidad constante, por ejemplo, 99 a
1, produce un rbol de recursin de profundidad ( log n), en que el
costo de cada nivel es (n), lo que se traduce en que el tiempo de
ejecucin es (nlog n).
En la prctica, en promedio, PARTITION produce una mezcla de divisiones
buenas y malas, que en el rbol de recursin estn distribuidas
aleatoriamente; si suponemos que aparecen alternadamente por niveles:
En la raz, el costo de la particin es n y los arreglos producidos tienen
tamaos n1 y 1.
Pgina 68
En el siguiente nivel, el arreglo de tamao n1 es particionado en dos
arreglos de tamao (n1)/ 2, y el costo de procesar un arreglo de
t amao 1 es 1.
Esta combinacin produce tres arreglos de tamaos 1, (n1)/ 2 y (n
1)/ 2 a un costo combinado de 2n1 = (n)
no peor que el caso de una sola particin que produce dos arreglos de
tamaos (n1)/ 2 + 1 y (n1)/ 2 a un costo de n = (n), y que es muy
aproximadamente balanceada.
Intuitivamente, el costo (n) de la divisin mala es absorbido por el costo
(n) de la divisin buena:
la divisin resultante es buena.
El tiempo de ejecucin de QUICKSORT, cuando los niveles producen
alternadamente divisiones buenas y malas, es como el tiempo de ejecucin
para divisiones buenas nicamente:
O(n log n), pero con una constante ms grande.
6.6 Or d en a m ien t o p or Mon t cu lo ( Hea p s or t )
DEFI NI CI ONES. Un heap (binario) es un arreglo que puede verse como un
rbol binario completo:
Cada nodo del rbol corresponde a un elemento del arreglo;
El rbol est lleno en todos los niveles excepto posiblemente el de ms
abajo, el cual est lleno desde la izquierda hasta un cierto punto.
Un arreglo A que representa a un heap tiene dos atributos:
[A] es el nmero de elementos en el arreglo;
[A] es el nmero de elementos en el heap almacenado en el arreglo
[A] = [A];
A[1 .. [A]] puede contener datos vlidos, pero ningn dato ms all de
A[ [A]] es un elemento del heap.
La raz del rbol es A[1]; y dado el ndice i de un nodo, los ndices de su padre,
hijo izquierdo, e hijo derecho se calculan como:
P(i) : r e t u r n i/ 2] L(i) : r e t u r n 2i R(i) : r e t u r n 2i + 1
Un heap satisface la propiedad de heap:
Para cualquier nodo i distinto de la raz, A[P(i)] = A[i];
El elemento ms grande en un heap est en la raz;
Pgina 69
Los subrboles que tienen raz en un cierto nodo contienen valores ms
pequeos que el valor contenido en tal nodo.
La altura de un heap de n elementos es (log n).
RESTAURACIN DE LA PROPI EDAD DE HEAP. Consideremos un arreglo A y un
ndice i en el arreglo, tal que:
Los rboles binarios con races en L( i) y R(i) son heaps;
A[i] puede ser ms pequeo que sus hijos, violando la propiedad de
heap.
HEAPIFY hace descender por el heap el valor en A[i], de modo que el
subrbol con raz en i se vuelva un heap; en cada paso:
determinamos el ms grande entre A[i], A[L(i)] y A[R(i)], y
almacenamos su ndice en k ;
si el ms grande no es A[i], entonces intercambiamos A[ i] con A[k ], de
modo que ahora el nodo i y sus hijos satisfacen la propiedad de heap;
pero ahora, el nodo k tiene el valor originalmente en A[i]el subrbol
con raz en k podra estar violando la propiedad de heap
siendo necesario llamar a HEAPIFY recursivamente.
HEAPIFY(A, i) :
l L(i); r R(i)
i f l = [A] A[l] > A[i] t h en k l els e k i
i f r = [A] A[r] > A[k] t h en k r
i f k ? i t h e n
intercambie A[i] A[k]
HEAPIFY(A, k)
El tiempo de ejecucin de HEAPIFY a partir de un nodo de altura h es O(h) =
O(log n), en que n es el nmero de nodos en el subrbol con raz en el nodo de
partida.
CONSTRUCCIN DE UN HEAP. Usamos HEAPIFY de abajo hacia arriba para
convertir un arreglo A[1 .. n] n = [A] en un heap:
Como los elementos en A[(n/ 2] + 1) .. n] son todos hojas del rbol, cada
uno es un heap de un elemento;
BUILD-HEAP pasa por los dems nodos del rbol y ejecuta HEAPIFY en
cada uno.
Pgina 70
El orden en el cual los nodos son procesados garantiza que los
subrboles con raz en los hijos del nodo i ya son heaps cuando HEAPIFY
es ejecutado en el nodo i.
BUILD-HEAP(A) :
[A] [A]
f or i [A]/ 2] d ow n t o 1 do HEAPIFY(A, i)
El tiempo que toma HEAPIFY al correr en un nodo vara con la altura del nodo,
y las alturas de la mayora de los nodos son pequeas.
En un heap de n elementos hay a lo ms n/ 2
h +1
nodos de altura h, de modo
que el costo total de BUI LD- HEAP es:
n
h+1
2
1
1
1
h0
logn
]
O(h) O n
h
2
h
h0
log n
]
_
,
O n ( )
ya que
h
h
2
h0
2
.
Un heap es un rbol binario con las siguientes caractersticas:
o Es completo. Cada nivel es completo excepto posiblemente el ltimo,
y en ese nivel los nodos estn en las posiciones ms a la izquierda.
o Los tems de cada nodo son mayores e iguales que los tems
almacenados en los hijos.
Para implementarlo podemos usar estructuras enlazadas o vectores
numerando los nodos por nivel y de derecha a izquierda.
Pgina 71
Es decir:
1
2 3
4 5 6 7
De este modo, es fcil buscar la direccin del padre o de los hijos de un nodo.
El padre de i es: i div 2. Los hijos de i son: 2 * i y 2 * i + 1.
Un algoritmo para convertir un rbol binario completo en un heap es bsico
para otras operaciones de heap. Por ejemplo un rbol en el que ambos
subrboles son heap pero el rbol en si no lo es.
2
9 4
1 5 3
La nica razn por la que no es un heap es porque la raz es menor que uno
(o dos como en este caso subrboles)
El primer paso es intercambiar la raz con el mayor de los dos hijos:
9
2 4
1 5 3
Esto garantiza que la nueva raz sea mayor que ambos hijos, y que uno de
estos siga siendo un heap (en este caso el derecho) y que el otro pueda ser o
no. Si es, el rbol entero lo es, sino simplemente repetimos el swapdown en
este subrbol.
S w ap d ow n
1. Done := false
2. c:= 2 ** r
3. W h i l e n o t Done a n d c < = n Do
a. i f c < n a n d Heap[c] < Heap[c+1] t h en c := c+1;
b. i f Heap[r] < Heap[c] t h en
i. Intercambiar Heap[r] y Heap[c]
ii. r := c
iii. c := 2 ** c
els e Done := true
Pgina 72
Hea p i f y
Recibe un rbol Binario Completo (ABC) almacenado en un arreglo
desde posicin 1 a posicin n. Convierte el rbol en un heap.
SwapDown (rbol cuya raz esta en r)
Veamos un ejemplo:
Sean los siguientes elementos: 35, 15, 77, 60, 22, 41
El arreglo contiene los tems como un ABC.
35
15 77
60 22 41
Usamos Heapify para convertirlo en Heap.
77
60 41
15 22 35
Esto pone al elemento ms grande en la raz, es decir la posicin 1 del vector.
Ahora usamos la estrategia de sort de seleccin y posicionamos
correctamente al elemento ms grande y pasamos a ordenar la sublista
compuesta por los otros 5 elementos
35
60 41
15 22 77 ------------------- 35,60,41,15,22,77
En trminos del rbol estamos cambiando, la raz por la hoja ms a la
derecha. Sacamos ese elemento del rbol. El rbol que queda no es un heap.
Como solo cambiamos la raz, los subrboles son heaps, entonces podemos
usar swapdown en lugar del Heapify que consume ms tiempo.
Pgina 73
60
35 41
15 22
Ahora usamos la misma tcnica de intercambiar la raz con la hoja ms a la
derecha que podamos.
22
35 41
15 60 --------------------------------------- 35,22,41,15,60,77
Volvemos a usar SwapDown para convertir en un Heap.
41
35 22
15
Y volvemos a hacer el intercambio hoja-raz.
15
35 22
41 ------------------------------------------- 35,15,22,41,60,77
15
35 22
Volvemos a usar SwapDown
35
15 22 Intercambiamos hoja- raz y podamos
22 ------------------------------------------ 22,15,35,41,60,77
Pgina 74
Finalmente, el rbol de dos elementos es convertido en un heap e
intercambiado la raz con la hoja y podado
15
22 ------------------------------------------ 15,22,35,41,60,77
El siguiente algoritmo resume el procedimiento descrito.
Consideramos a X como un rbol binario completo (ABC) y usamos h ea p i f y
para convertirlo en un heap.
For i = n dow n t o 2 d o
I ntercambiar X[1] y X[i], poniendo el mayor elemento de la sublista
X[1]...X[i] al final de esta.
Aplicar SwapDown para convert ir en heap el rbol binario
correspondiente a la sublista almacenada en las posiciones 1 a i - 1 de
X.
6 . 7 Ot r os Mt od os d e Or d en a m ien t o
Existen varios otros algoritmos de ordenamiento. A continuacin se
mencionarn brevemente algunos otros ms.
6.7.1 Or d e n a m i e n t o por I n cr em en t os Decr ecien t es
Denominado as por su desarrollador Donald Shell (1959). El ordenamiento
por incrementos decrecientes (o mtodo sh ellsor t ) es una generalizacin
del ordenamiento por insercin donde se gana rpidez al permitir
intercambios entre elementos que se encuentran muy alejados.
La idea es reorganizar la secuencia de datos para que cumpla con la
propiedad siguiente: si se toman todos los elementos separados a una
distancia h, se obtiene una secuencia ordenada.
Se dice que la secuencia h ordenada est constituida por h secuencias
ordenadas independendientes, pero entrelazadas entre s. Se utiliza una
serie decreciente h que termine en 1.
f or ( h = 1; h <= n/ 9; h = 3*h + 1 );
f or ( ; h > 0; h/ = 3 )
for ( i = h + 1; i <= n; i+= 1 )
{ v = A[i];
j = i;
Pgina 75
w h i le ( j > h && A[j- h] > v ) t h en
{ A[j] = A[j-1];
j - = h;
}
A[j] = v ;
}
An lis is d el a lgor it m o:
Esta sucesin de incrementos es fcil de utilizar y conduce a una ordenacin
eficaz. Hay otras muchas sucesiones que conducen a ordenaciones mejores.
Es difcil mejorar el programa anterior en ms de un 20%, incluso para n
grande. Existen sucesiones desfavorables como por ejemplo: 64, 32, 16, 8, 4,
2, 1, donde slo se comparan elementos en posiciones impares cuando h=1.
Na d i e ha sido capaz de analizar el algoritmo, por lo que es difcil evaluar
analticamente los diferentes incrementos y su comparacin con otros
mtodos, en consecuencia no se conoce su forma funcional del tiempo de
ejecucin.
Para la sucesin de incrementos anterior se tiene un T(n) = n( log n)
2
y n
1,25
.
La ordenacin de Shell nunca hace ms de n
3 /2
comparaciones (para los
incrementos 1,2,13, 40.....) .
6 . 7. 2 Or d en a m ien t o p or Me zcla s Su ces iva s ( m er g e s or t )
Se aplica la tcnica divide- y-vencers, dividiendo la secuencia de datos en dos
subsecuencias hasta que las subsecuencias tengan un nico elemento, luego
se ordenan mezclando dos subsecuencias ordenadas en una secuencia
ordenada, en forma sucesiva hasta obtener una secuencia nica ya ordenada.
Si n = 1 solo hay un elemento por ordenar, sino se hace una ordenacin de
mezcla de la primera mitad del arreglo con la segunda mitad. Las dos mitades
se ordenan de igual forma.
Ejemplo: Se tiene un arreglo de 8 elementos, se ordenan los 4 elementos de
cada arreglo y luego se mezclan. El arreglo de 4 elementos, se ordenan los 2
elementos de cada arreglo y luego se mezclan. El arreglo de 2 elementos,
como cada arreglo slo tiene n = 1 elemento, solo se mezclan.
Pgina 76
v o i d ordenarMezcla(TipoEle A[], int izq, int der)
{ i f ( izq < der )
{ centro = ( izq + der ) % 2;
ordenarMezcla( A, izq, centro );
ordenarMezcla( A, centro+1, der);
intercalar( A, izq, centro, der );
}
}
v o i d intercalar(TipoEle A[], int a, int c, int b )
{ k = 0;
i = a;
j = c + 1;
n = b - a;
w h i le ( i < c + 1 ) && ( j < b + 1 )
{ if ( A[i] < A[j] )
{ B[k] = A[i];
i = i + 1;
}
els e
{ B[k] = A[j];
j = j + 1;
}
k = k + 1;
};
w h i le ( i < c + 1 )
{ B[k] = A[i];
i++;
k++;
};
w h i le ( j < b + 1 )
Pgina 77
{ B[k] = A[j];
j++;
k++;
};
i = a;
f or ( k = 0; k < n; i++ )
{ A[i] = B[k];
i++;
};
};
An lis is d el a lgor i t m o:
La relacin de recurrencia del algoritmo es T(1) = 1, T(n) = 2 T(n/ 2) + n, cuya
solucin es T(n) = n log n.
Pgina 78
Ca p t u lo 7
Algor it m os d e B s qu ed a
7.1 I n t r od u ccin
En cualquier estructura de datos puede plantearse la necesidad de saber si
un cierto dato est almacenado en ella, y en su caso en que posicin se
encuentra. Es el problema de la bsqueda.
Existen diferentes mtodos de bsqueda, todos parten de un esquema
iterativo, en el cual se trata una parte o la totalidad de la estructura de datos
sobre la que se busca.
El tipo de estructura condiciona el proceso de bsqueda debido a los
diferentes modos de acceso a los datos.
7. 2 B s q u e d a Li n e a l
La bsqueda es el proceso de localizar un registro (elemento) con un valor de
llave particular. La bsqueda termina exitosamente cuando se localiza el
registro que contenga la llave buscada, o termina sin xito, cuando se
determina que no aparece ningn registro con esa llave.
Bsqueda lineal, tambin se le conoce como bsqueda secuencial.
Supongamos una coleccin de registros organizados como una lista lineal. El
algoritmo bsico de bsqueda lineal consiste en empezar al inicio de la lista e
ir a travs de cada registro hasta encontrar la llave indicada (k ), o hasta al
final de la lista. Posteriormente hay que comprobar si ha habido xito en la
bsqueda.
Es el mtodo ms sencillo en estructuras lineales. En estructuras ordenadas
el proceso se optimiza, ya que al llegar a un dato con nmero de orden
mayor que el buscado, no hace falta seguir.
La situacin ptima es que el registro buscado sea el primero en ser
examinado. El peor caso es cuando las llaves de todos los n registros son
comparados con k (lo que se busca). El caso promedio es n/ 2
comparaciones.
Este mtodo de bsqueda es muy lento, pero si los datos no estn en orden
es el nico mtodo que puede emplearse para hacer las bsquedas. Si los
valores de la llave no son nicos, para encontrar todos los registros con una
llave particular, se requiere buscar en toda la lista.
Pgina 79
Mejor a s en la eficien cia d e la b s q u ed a lin eal
1) Mu e s t r e o d e a cce s o
Este mtodo consiste en observar que tan frecuentemente se solicita
cada registro y ordenarlos de acuerdo a las probabilidades de acceso
detectadas.
2) Movim ie n t o h a cia e l fr e n t e
Este esquema consiste en que la lista de registros se reorganicen
dinmicamente. Con este mtodo, cada vez que bsqueda de una llave
sea exitosa, el registro correspondiente se mueve a la primera
posicin de la lista y se recorren una posicin hacia abajo los que
estaban antes que l.
3) Tr a n s p os i ci n
Este es otro esquema de reorganizacin dinmica que consiste en que,
cada vez que se lleve a cabo una bsqueda exitosa, el registro
correspondiente se intercambia con el anterior. Con este
procedimiento, entre ms accesos tenga el registro, ms rpidamente
avanzar hacia la primera posicin. Comparado con el mtodo de
movimiento al frente, el mtodo requiere ms tiempo de actividad
para reorganizar al conjunto de registros. Una ventaja de mtodo de
transposicin es que no permite que el requerimiento aislado de un
registro, cambie de posicin todo el conjunto de registros. De hecho,
un registro debe ganar poco a poco su derecho a alcanzar el inicio de
la lista.
4) Or d e n a m i e n t o
Una forma de reducir el nmero de comparaciones esperadas cuando
hay una significativa frecuencia de bsqueda sin xito es la de
ordenar los registros en base al valor de la llave. Esta tcnica es til
cuando la lista es una lista de excepciones, tales como una lista de
decisiones, en cuyo caso la mayora de las bsquedas no tendrn
xito. Con este mtodo una bsqueda sin xito termina cuando se
encuentra el primer valor de la llave mayor que el buscado, en lugar
de la final de la lista.
En ciertos casos se desea localizar un elemento concreto de un arreglo. En
una bsqueda lineal de un arreglo, se empieza con la primera casilla del
arreglo y se observa una casilla tras otra hasta que se encuentra el elemento
buscado o se ha visto todas las casillas. Como el resultado de la bsqueda es
un solo valor, ya sea la posicin del elemento buscado o cero, puede usarse
una funcin para efectuar la bsqueda.
Pgina 80
En la funcin BUSQ_LINEAL, ntese el uso de la variable booleana
encontrada.
Fu n ct i on BUSQ_LINEAL (nombres: tiponom; Tam: integer;
{Regresa el ndice de la celda que contiene el elemento buscado o
regresa 0 si no est en el arreglo}
V a r encontrado: boolean;
indice; integer:
Begin
encontrado := false;
indice : = 1:
Re a p e a t
I f nombres {ndice} = sebusca t h e n
be gin
encontrado : = true;
BUSQ_LINEAL := indice
en d
el s e
indice := indice + 1
Un t i l (encontrado) or {indice > tam);
I f not encontrado t h e n BUSQ_LINEAL: = 0
En d ;
7. 3 B s q u ed a Bin a r ia
Una bsqueda lineal funciona bastante bien para una lista pequea. Pero si
se desea buscar el nmero de telfono de J orge Perez en el directorio
telefnico de Santiago, no sera sensato empezar con el primer nombre y
continuar la bsqueda nombre por nombre. En un mtodo ms eficiente se
aprovechar el orden alfabtico de los nombres para ir inmediatamente a un
lugar en la segunda mitad del directorio.
La bsqueda binaria es semejante al mtodo usado automticamente al
buscar un nmero telefnico. En la bsqueda binaria se reduce
sucesivamente la operacin eliminando repetidas veces la mitad de la lista
restante. Es claro que para poder realizar una bsqueda binaria debe tenerse
una lista ordenada.
Se puede aplicar tanto a datos en listas lineales como en rboles binarios de
bsqueda. Los prerrequisitos principales para la bsqueda binaria son:
o La lista debe estar ordenada en un orden especifco de acuerdo
al valor de la llave.
o Debe conocerse el nmero de registros.
Pgina 81
Al go r i t m o
1. Se compara la llave buscada con la llave localizada al centro del
arreglo.
2. Si la llave analizada corresponde a la buscada fin de bsqueda si no.
3. Si la llave buscada es menor que la analizada repetir proceso en mitad
superior, sino en la mitad inferior.
4. El proceso de partir por la mitad el arreglo se repite hasta encontrar el
registro o hasta que el tamao de la lista restante sea cero , lo cual
implica que el valor de la llave buscada no est en la lista.
El esfuerzo mximo para este algoritmo es de log2 n. El mnimo de 1 y en
promedio log2 n.
7. 4 r boles d e B s qu ed a
Son tipos especiales de rboles que los hacen adecuados para almacenar y
recuperar informacin. Como en un rbol binario de bsqueda buscar
informacin requiere recorrer un solo camino desde la raz a una hoja. Como
en un rbol balanceado el ms largo camino de la raz a una hoja es O( log
n). A diferencia de un rbol binario cada nodo puede contener varios
elementos y tener varios hijos. Debido a esto y a que es balanceado, permite
acceder a grandes conjuntos de datos por caminos cortos.
7. 5 B s qu ed a p or Tr a n s for m a cin d e Cla ves ( Ha s h i n g)
Hasta ahora las tcnicas de localizacin de registros vistas, emplean un
proceso de bsqueda que implica cierto tiempo y esfuerzo. El siguiente
mtodo nos permite encontrar directamente el registro buscado.
La idea bsica de este mtodo consiste en aplicar una funcin que traduce un
conjunto de posibles valores llave en un rango de direcciones relativas. Un
problema potencial encontrado en este proceso, es que tal funcin no puede
ser uno a uno; las direcciones calculadas pueden no ser todas nicas, cuando
R(k1)= R(k2 ) . Pero: K1 diferente de K2 decimos q ue hay una co li s i n. A dos
llaves diferentes que les corresponda la misma direccin relativa se les llama
s in n imos .
A las tcnicas de clculo de direcciones tambin se les conoce como:
o Tcnicas de almacenamiento disperso
o Tcnicas aleatorias
o Mtodos de transformacin de llave- a-direccin
o Tcnicas de direccionamiento directo
o Mtodos de tabla Hash
o Mtodos de Hashing
Pgina 82
Pero el trmino ms usado es el de hashing. Al clculo que se realiza para
obtener una direccin a partir de una llave se le conoce como fu n cin
h a s h .
Ven t a ja s :
1. Se pueden usar los valores naturales de la llave, puesto que se
traducen internamente a direcciones fciles de localizar.
2. Se logra independencia lgica y fsica, debido a que los valores de las
llaves son independientes del espacio de direcciones.
3. No se requiere almacenamiento adicional para los ndices.
De s ve n t a ja s:
1. No pueden usarse registros de longitud variable.
2. El archivo no est ordenado.
3. No permite llaves repetidas.
4. Solo permite acceso por una sola llave.
Cost os :
Tiempo de procesamiento requerido para la aplicacin de la funcin
hash.
Tiempo de procesamiento y los accesos E/ S requeridos para
solucionar las colisiones.
La e fi ci e n ci a d e u n a fu n cin h a s h d ep en d e d e:
1. La distribucin de los valores de llave que realmente se usan.
2. El nmero de valores de llave que realmente estn en uso con
respecto al tamao del espacio de direcciones.
3. El nmero de registros que pueden almacenarse en una direccin
dada sin causar una colisin.
4. La tcnica usada para resolver el problema de las colisiones.
La s fu n cion es h a s h m s comu n es son :
o Residuo de la divisin
o Mtodo de la Multiplicacin
o Medio del cuadrado
o Pliegue
Ha s h i n g p or Res i d u o d e l a Di v i s i n
En este caso, h ( k ) = k mod m , en que m = nmero primo no muy cercano
a una potencia de 2si m = 2
p
, entonces h(k) es los p bits menos
significativos de k .
Pgina 83
La idea de este mtodo es la de dividir el valor de la llave entre un nmero
apropiado, y despus utilizar el residuo de la divisin como direccin
relativa para el registro (direccin = llave mod divisor).
Mientras que el valor calculado real de una direccin relativa, dados tanto
un valor de llave como el divisor, es directo; la eleccin del divisor apropiado
puede no ser tan simple. Existen varios factores que deben considerarse para
seleccionar el divisor:
1. El rango de valores que resultan de la operacin "llave mod divisor", va
desde cero hasta el divisor 1. Luego, el divisor determina el tamao del
espacio de direcciones relativas. Si se sabe que el archivo va a contener
por lo menos n registros, entonces tendremos que hacer que divisor > n,
suponiendo que solamente un registro puede ser almacenado en una
direccin relativa dada.
2. El divisor deber seleccionarse de tal forma que la probabilidad de
colisin sea minimizada. Cmo escoger este nmero? Mediante
investigaciones se ha demostrado que los divisores que son nmeros
pares tienden a comportase pobremente, especialmente con los
conjuntos de valores de llave que son predominantemente impares.
Algunas investigaciones sugieren que el divisor deber ser un nmero
primo. Sin embargo, otras sugieren que los divisores no primos trabajan
t an bin como los divisores primos, siempre y cuando los divisores no
primos no contengan ningn factor primo menor de 20. Lo ms comn
es elegir el nmero primo ms prximo al total de direcciones.
Independientemente de que tan bueno sea el divisor, cuando el espacio de
direcciones de un archivo est completamente lleno, la probabilidad de
colisin crece dramticamente. La saturacin de archivo de mide mediante
su fa ct or d e ca r ga , el cual se define como la relacin del nmero de
registros en el archivo contra el nmero de registros que el archivo podra
contener si estuviese completamente lleno.
Todas las funciones hash comienzan a trabajar pr obablemente cuando el
archivo est casi lleno. Por lo general, el mximo factor de carga que puede
tolerarse en un archivo para un rendimiento razonable es de entre el 70% y
80%.
Por ejemplo, si:
n = 2,000 strings de caracteres de 8 bits, en que cada string es
interpretado como un nmero entero k en base 256, y
estamos dispuestos a examinar un promedio de 3 elementos en una
bsqueda fallida,
Pgina 84
Entonces podemos:
asignar una tabla de mezcla de tamao m = 701 y
usar la funcin de mezcla k (k) = k mod 701 .
Ha s h i n g p or Mt od o d e la Mu lt i p li ca ci n
En este caso, h( k ) = m ( k A mod 1) ] ,
en que 0 < A < 1; el valor de m no es crtico y tpicamente se usa una
potencia de 2 para facilitar el clculo computacional de la funcin.
Por ejemplo, si k = 123456, m = 10,000, y A = ( 5 1)/ 2 0 .6180339887,
entonces h(k ) = 41.
Ha s h i n g p or M ed i o d el Cu a d r a d o
En esta tcnica, la llave es elevada al cuadrado, despus algunos dgitos
especficos se extraen de la mitad del resultado para constituir la direccin
relativa. Si se desea una direccin de n dgitos, entonces los dgitos se
truncan en ambos extremos de la llave elevada al cuadrado, tomando n
dgitos intermedios. Las mismas posiciones de n dgitos deben extraerse
para cada llave.
Eje m p lo:
Utilizando esta funcin hashing el tamao del archivo resultante es de 10
n
donde n es el numero de dgitos extrados de los valores de la llave elevada al
cuadrado.
Ha s h i n g p or Pl i eg u e
En esta tcnica el valor de la llave es particionada en varias partes, cada una
de las cuales (excepto la ltima) tiene el mismo nmero de dgitos que tiene
la direccin relativa objetivo. Estas particiones son despus plegadas una
sobre otra y sumadas. El resultado, es la direccin relativa. Igual que para el
mtodo del medio del cuadrado, el tamao del espacio de dir ecciones
relativas es una potencia de 10.
Com p a r a ci n en t r e la s Fu n ci on es Hash
Aunque alguna otra tcnica pueda desempearse mejor en situaciones
particulares, la tcnica del residuo de la divisin proporciona el mejor
desempeo. Ninguna funcin hash se desempea siempre mejor que las
Pgina 85
otras. El mtodo del medio del cuadrado puede aplicarse en archivos con
factores de cargas bastantes bajas para dar generalmente un buen
desempeo. El mtodo de pliegues puede ser la tcnica ms fcil de calcular ,
pero produce resultados bastante errticos, a menos que la longitud de la
llave sea aproximadamente igual a la longitud de la direccin.
Si la distribucin de los valores de llaves no es conocida, entonces el mtodo
del residuo de la divisin es preferible. Note que el hashing puede ser
aplicado a llaves no numricas. Las posiciones de ordenamiento de
secuencia de los caracteres en un valor de llave pueden ser utilizadas como
sus equivalentes "numricos". Alternativamente, el algoritmo hash acta
sobre las represe ntaciones binarias de los caracteres.
Todas las funciones hash presentadas tienen destinado un espacio de
tamao fijo. Aumentar el tamao del archivo relativo creado al usar una de
estas funciones, implica cambiar la funcin hash, para que se refiera a un
espacio mayor y volver a cargar el nuevo archivo.
M t od os p a r a Res olver el Pr ob le m a d e la s Colis ion es
Considere las llaves K1 y K2 que son sinnimas para la funcin hash R. Si K1
es almacenada primero en el archivo y su direccin es R(K1), entonces se
dice que K1 esta almacenado en su direccin de origen.
Existen dos m t od os b sicos para determinar dnde debe ser alojado K2:
Dir e ccion a m ie n t o a b ie r t o. Se encuentra entre direccin de origen
para K2 dentro del archivo.
Sep a r a cin d e d es bor d e ( r ea d e d e s b or d e ) . Se encuentra una
direccin para K2 fuera del rea principal del archivo, en un rea
especial de desborde, que es utilizada exclusivamente para almacenar
registro que no pueden ser asignados en su direccin de origen
Los m t od os m s con ocid os p a r a r es olver colis ion es s on :
Son d e o li n e a l
Es una tcnica de direccionamiento abierto. Este es un proceso de bsqueda
secuencial desde la direccin de origen para encontrar la siguiente localidad
vaca. Esta tcnica es tambin conocida como mtodo de desbordamiento
consecutivo.
Para almacenar un registro por hashing con sondeo lineal, la direccin no
debe caer fuera del lmite del archivo. En lugar de terminar cuando el lmite
del espacio de direccin se alcanza, se regresa al inicio del espacio y
sondeamos desde ah. Por lo que debe ser posible detectar si la direccin
Pgina 86
base ha sido encontrada de nuevo, lo cual indica que el archivo est lleno y
no hay espacio para la llave.
Para la bsqueda de un registro por hashing con sondeo lineal, los valores
de llave de los registros encontrados en la direccin de origen, y en las
direcciones alcanzadas con el sondeo lineal, deber compararse con el valor
de la llave buscada, para determinar si el registro objetivo ha sido localizado
o no.
El sondeo lineal puede usarse para cualquier tcnica de hashing. Si se
emplea sondeo lineal para almacenar registros, tambin deber emplearse
para recuperarlos.
Doble h a s h in g
En esta tcnica se aplica una segunda funcin hash para combinar la llave
original con el result ado del primer hash. El resultado del segundo hash
puede situarse dentro del mismo archivo o en un archivo de sobreflujo
independiente; de cualquier modo, ser necesario algn mtodo de solucin
si ocurren colisiones durante el segundo hash.
La ventaja del mtodo de separacin de desborde es que reduce la situacin
de una doble colisin, la cual puede ocurrir con el mtodo de
direccionamiento abierto, en el cual un registro que no est almacenado en
su direccin de origen desplazar a otro registro, el que despus buscar su
direccin de origen. Esto puede evitarse con direccionamiento abierto,
simplemente moviendo el registro extrao a otra localidad y almacenando al
nuevo registro en la direccin de origen ahora vaca.
Puede ser aplicado como cualquier direccionamiento abierto o tcnica de
separacin de desborde.
Para ambas mtodos para la solucin de colisiones existen tcnicas para
mejorar su desempeo como:
1. En ca d en a m ien t o d e s in n im os
Una buena manera de mejorar la eficiencia de un archivo que utiliza el
clculo de direcciones, sin directorio auxiliar para guiar la
recuperacin de registros, es el encadenamiento de sinnimos.
Mantener una lista ligada de registros, con la misma direccin de
origen, no reduce el nmero de colisiones, pero reduce los tiempos de
acceso para recuperar los registros que no se encuentran en su
localidad de origen. El encadenamiento de sinnimos puede emplearse
con cualquier tcnica de solucin de colisiones.
Cuando un registro debe ser recuperado del archivo, solo los sinnimos
de la llave objetivo son accesados.
Pgina 87
2. Dir eccion a m ien t o p or cu bet a s
Otro enfoque para resolver el problema de las colisiones es asignar
bloques de espacio (cubetas), que pueden acomodar ocurrencias
mltiples de registros, en lugar de asignar celdas individuales a
registros. Cuando una cubeta es desbordada, alguna nueva localizacin
deber ser encontrada para el registro. Los mtodos para el problema
de sobrecupo son bsicamente los mismos que los mtodos para
resolver colisiones.
Com p a r a cin en t r e Son d e o Lin ea l y Doble Ha s h i n g
De ambos mtodos resultan distribuciones diferentes de sinnimos en un
archivo relativo. Para aquellos casos en que el factor de carga es bajo (< 0.5),
el sondeo lineal tiende a agrupar los sinnimos, mientras que el doble
hashing tiende a dispersar los sinnimos ms ampliamente a travs del
espacio de direcciones.
El doble hashing tiende a comportarse casi tambin como el sondeo lineal
con factores de carga pequeos (< 0.5), pero acta un poco mejor para
factores de carga mayores. Con un factor de carga > 80 %, el sondeo lineal,
por lo general, resulta tener un comportamiento terrible, mientras que el
doble hashing es bastante tolerable para bsquedas exitosas, pero no as en
bsquedas no exitosas.
7. 6 B s q u e d a e n Te xt os
La bsqueda de patrones en un texto es un problema muy importante en la
prctica. Sus aplicaciones en computacin son variadas, como por ejemplo
la bsqueda de una palabra en un archivo de texto o problemas relacionados
con biologa computacional, en donde se requiere buscar patrones dentro de
una secuencia de ADN, la cual puede ser modelada como una secuencia de
caracteres (el problema es ms complejo que lo descrito, puesto que se
requiere buscar patrones en donde ocurren alteraciones con cierta
probabilidad, esto es, la bsqueda no es exacta).
En este captulo se considerar el problema de buscar la ocurrencia de un
patrn dentro de un texto. Se utilizarn las siguientes convenciones:
n denotar el largo del texto en donde se buscar el patrn, es decir, texto =
a1 a2 ... an . Donde m denotar el largo del patrn a buscar, es decir, patrn =
b1 b2 ... bm .
Pgina 88
Por ejemplo:
Texto = "analisis de algoritmos" n=22 y m=4
Patrn = "algo"
7. 6 . 1 Algor i t m o d e Fu e r za Br u t a
Se alinea la primera posicin del patrn con la primera posicin del
texto, y se comparan los caracteres uno a uno hasta que se acabe el
patrn, esto es, se encontr una ocurrencia del patrn en el texto, o
hasta que se encuentre una discrepancia.
Si se detiene la bsqueda por una discrepancia, se desliza el patrn en
una posicin hacia la derecha y se intenta calzar el patrn
nuevamente.
En el peor caso este algoritmo realiza O(m
.
n)comparaciones de
caracteres.
7. 6 . 2 Algor i m o Kn u t h- Mor r is - Pr a t t
Suponga que se est comparando el patrn y el texto en una posicin
dada, cuando se encuentra una discrepancia.
Pgina 89
Sea X la parte del patrn que calza con el texto, e Y la correspondiente
parte del texto, y suponga que el largo de X es j. El algoritmo de fuerza
bruta mueve el patrn una posicin hacia la derecha, sin embargo,
esto puede o no puede ser lo correcto en el sentido que los primeros j-
1 caracteres de X pueden o no pueden calzar los ltimos j- 1 caracteres
de Y.
La observacin clave que realiza el algoritmo Knuth- Morris- Pratt (en
adelante KMP) es que X es igual a Y, por lo que la pregunta planteada
en el prrafo anterior puede ser respondida mirando solamente el
patrn de bsqueda, lo cual permite precalcular la respuesta y
almacenarla en una tabla.
Por lo tanto, si deslizar el patrn en una posicin no funciona, se
puede intentar deslizarlo en 2, 3, ..., hasta j posiciones.
Se define la funcin de fracaso (f a i l u r e f u n ct i on) del patrn como:
f(j) = max( i < j b1 .. bi = bj=i+1 bj)
Intuitivamente, f(j) es el largo del mayor prefijo de X que adems es
sufijo de X. Note que j = 1 es un caso especial, puesto que si hay una
discrepancia en b1 el patrn se desliza en una posicin.
Si se detecta una discrepancia entre el patrn y el texto cuando se
trata de calzar bj+1, se desliza el patrn de manera que bf(j) se
encuentre donde bj se encontraba, y se intenta calzar nuevamente.
Pgina 90
Suponiendo que se tiene f(j) precalculado, la implementacin del
algoritmo KMP es la siguiente:
/ / n = largo del texto
/ / m = largo del patrn
/ / Los ndices comienzan desde 1
in t k =0;
in t j=0;
w h i le (k <n && j<m)
{
w h i le (j>0 && texto[k]!=patron[j])
{
j=f[j];
}
if (texto[k+1])==patron[ j+1]))
{
j++;
}
k++;
}
/ / j==m => calce, j el patrn no estaba en el texto
Pgina 91
Ejemplo:
El tiempo de ejecucin de este algoritmo no es difcil de analizar, pero
es necesario ser cuidadoso al hacerlo. Dado que se tienen dos ciclos
anidados, se puede acotar el tiempo de ejecucin por el nmero de
veces que se ejecuta el ciclo externo (menor o igual a n) por el nmero
de veces que se ejecuta el ciclo interno (menor o igual a m), por lo que
la cota es igual a O(mn), que es igual a lo que demora el algoritmo de
fuerza bruta!.
El anlisis descrito es pesimista. Note que el nmero total de veces
que el ciclo interior es ejecutado es menor o igual al nmero de veces
que se puede decrementar j, dado que f(j)<j. Pero j comienza desde
cero y es siempre mayor o igual que cero, por lo que dicho nmero es
menor o igual al nmero de veces que j es incrementado, el cual es
menor que n. Por lo tanto, el tiempo total de ejecucin es O(n). Por
otra parte, k nunca es decrementado, lo que implica que el algoritmo
nunca se devuelve en el texto.
Queda por resolver el problema de definir la funcin de fracaso, f(j).
Esto se puede realizar inductivamente. Para empezar, f(1)=0 por
definicin. Para calcular f(j+1) suponga que ya se tienen almacenados
los valores de f(1), f(2), ..., f(j). Se desea encontrar un i+1 tal que el
(i+1)- simo carcter del patrn sea igual al (j+1)- simo carcter del
patrn.
Para esto se debe cumplir que i=f(j). Si bi+1=bj+1, entonces f(j+1)=i+1.
En caso contrario, se reemplaza i por f(i) y se verifica nuevamente la
condicin.
Pgina 92
El algoritmo resultante es el siguiente (note que es similar al
algoritmo KMP):
/ / m es largo del patrn
/ / los ndices comienzan desde 1
in t [] f=new int[m];
f[1]=0;
in t j=1;
in t i;
w h i le (j<m)
{
i=f[ j];
w h i le (i>0 && patron[i+1]!=patron[j+1])
{
i=f[ i];
}
if (patron[i+1]==patron[ j+1])
{
f[j+1]=i+1;
}
els e
{
f[j+1]=0;
}
j++;
}
El tiempo de ejecucin para calcular la funcin de fracaso puede ser
acotado por los incrementos y decrementos de la variable i, que es
O(m).
Por lo tanto, el tiempo total de ejecucin del algoritmo, incluyendo el
preprocesamiento del patrn, es O(n+m).
7. 6 . 3 Algor it m o d e Boyer - Moor e
Hasta el momento, los algoritmos de bsqueda en texto siempre
comparan el patrn con el texto de izquierda a derecha. Sin embargo,
suponga que la comparacin ahora se realiza de derecha a izquierda:
si hay una discrepancia en el ltimo carcter del patrn y el carcter
del texto no aparece en todo el patrn, entonces ste se puede deslizar
m posiciones sin realizar niguna comparacin extra. En particular, no
fue necesario comparar los primeros m-1 caracteres del texto, lo cual
indica que podra realizarse una bsqueda en el texto con menos de n
comparaciones; sin embargo, si el carcter discrepante del texto se
encuentra dentro del patrn, ste podra desplazarse en un nmero
menor de espacios.
Pgina 93
El mtodo descrito es la base del algoritmo Boyer- Moore, del cual se
estudiarn dos variantes: Horspool y Sunday.
Bo y er- Moor e - Hor s p ool ( BMH)
El algoritmo BMH compara el patrn con el texto de derecha a
izquierda, y se detiene cuando se encuentra una discrepancia con el
t exto. Cuando esto sucede, se desliza el patrn de manera que la letra
del texto que estaba alineada con bm , denominada c, ahora se alinie
con algn bj, con j<m, si dicho calce es posible, o con b0 , un carcter
ficticio a la izquierda de b1, en caso contrario (este es el mejor caso del
algoritmo).
Para determinar el desplazamiento del patrn se define la funcin
siguiente como:
0 si c no pertenece a los primeros m- 1 caracteres del patrn (Por qu
no se considera el carcter bm?).
j si c pertenece al patrn, donde j<m corresponde al mayor ndice tal
que bj==c.
Esta funcin slo depende del patrn y se puede precalcular antes de
realizar la bsqueda.
El algoritmo de bsqueda es el siguiente:
/ / m es el largo del patrn
/ / los ndices comienzan desde 1
int k=m;
int j=m;
wh ile (k <=n && j>=1)
{
if (texto[ k-(m-j)]==patron[ j])
{
j--;
}
else
{
k=k+(m-siguiente(a[k]));
j=m;
}
}
/ / j==0 => calce!, j>=0 => no hubo calce.
Pgina 94
Ejemplo de uso del algoritmo BMH:
Se puede demostrar que el tiempo promedio que toma el algoritmo
BMH es:
donde c es el tamao del alfabeto (c<<n). Para un alfabeto
razonablemente grande, el algoritmo es .
En el peor caso, BMH tiene el mismo tiempo de ejecucin que el
algoritmo de fuerza bruta.
Bo y er- Moor e -Su n d a y (BMS)
El algoritmo BMH desliza el patrn basado en el smbolo del texto
que corresponde a la posicin del ltimo carcter del patrn. Este
siempre se desliza al menos una posicin si se encuentra una
discrepancia con el texto.
Es fcil ver que si se utiliza el carcter una posicin ms adelante en el
texto como entrada de la funcin siguiente el algoritmo tambin
funciona, pero en este caso es necesario considerar el patrn completo
al momento de calcular los valores de la funcin siguiente. Esta
variante del algoritmo es conocida como Boy er- Moore-Sunday
(BMS).
Pgina 95
Es posible generalizar el argumento, es decir, se pueden utilizar
caracteres ms adelante en el texto como entrada de la funcin
siguiente? La respuesta es no, dado que en ese caso puede ocurrir que
se salte un calce en el texto.
Pgina 96
Ca p t u lo 8
Teor a d e Gr a fos
Un grafo (o multigrafo) , es una estructura muy importante utilizada en
Informtica y tambin en ciertos ramos de Matemticas, como por ejemplo, en
Investigacin de Operaciones. Muchos problemas de difcil resolucin, pueden ser
expresados en forma de grafo y consecuentemente resuelto usando algoritmos de
bsqueda y manipulacin estndar.
Entre las mltiples aplicaciones que tienen estas estructuras podemos mencionar:
Modelar diversas situaciones reales, tales como: sistemas de aeropuertos,
flujo de trfico, etc.
Realizar planificaciones de actividades, tareas del computador, planificar
operaciones en lenguaje de mquinas para minimizar tiempo de ejecucin.
Simplemente, un gr a fo es una estructura de datos no lineal, que puede ser
considerado como un conjunto de v r t i ce s (o nodos, dependiendo de la
bibliografa) y a r cos que conectan esos vrtices.
Matemticamente tenemos G=(V, E) . Si u y v son elementos de V, entonces un
arco se puede representar por ( u,v ).
Los grafos tambin se pueden clasificar como:
Grafo No Dirigido
Grafo Dirigido (o Digrafo)
En el primer caso, los arcos no tienen una direccin y, por lo tant o, (u,v ) y (v,u)
representan el mismo arco. En un Gr a f o No Di r i gi d o, dos vrtices se dicen
adyacentes si existe un arco que une a esos dos vrtices.
En el segundo caso, los arcos tienen una direccin definida, y as (u,v) y (v,u)
entonces representan arcos diferentes. Un Gr a f o Di r i g i d o (o digrafo) puede
tambin ser fuertemente conectado si existe un camino desde cualquier vrtice
hacia otro cualquier vrtice.
Pgina 97
Ejemplos de grafos (dirigidos y no dirigidos):
G1 = (V1, E1)
V1 = {1, 2, 3, 4} E1 = {(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)}
G2 = (V2, E2)
V2 = {1, 2, 3, 4, 5, 6} E2 = {(1, 2), (1, 3), (2, 4), (2, 5), (3, 6)}
G3 = (V3, E3)
V3 = {1, 2, 3} E3 = {<1, 2>, <2, 1>, <2, 3>}
Grficamente estas tres estructuras de vrtices y arcos se pueden representar
de la siguiente manera:
8 .1 De fi n i ci on e s B s i ca s
Un grafo puede ser direccional o no direccional.
Un g r a f o d i r ecci on a l G es un par (V, E):
V es un conjunto finito de vrtices y
E es un conjunto de aristas que representa una relacin binaria sobre
V E V V.
En un g r a f o n o d i r ecci on a l G = (V, E), el conjunto de aristas E consiste
en pares no ordenados de vrtices.
Pgina 98
Una a r is t a es un conjunto {u, v }, en que u, v V y u v , y que
representamos como (u, v ).
Si (u, v) es una a r i s t a en un grafo:
dirigido, entonces (u, v ) es i n ci d en t e desde o sale del vrtice u y es
incidente a o entra al vrtice v ;
no dirigido, entonces (u, v ) es in cid en t e sobre u y v .
v es a d y acen t e a u; si el grafo es no dirigido, entonces la relacin de
adyacencia es simtrica.
Un ca m i n o ( o r u t a ) es una secuencia de vrtices v 1,...,v n tal que (v i,v i+1)
pertenece a E. La lo n gi t u d de un camino es la cantidad de arcos que ste
contiene.
Un ca m in o de longitud k desde un vrtice u a un vrtice u en un grafo G =
(V, E) es una secuencia v0 , v1, , vk de vrtices tal que:
u = v0 ,
u = vk y
(v i-1, vi) E para i = 1, 2, , k .
Si hay un ca m i n o p desde u a u, entonces u es a l ca n z a b l e desde u va p.
Un ca m in o s im p le es aquel donde todos sus vrtices son distintos. Slo el
primero y el lt imo pueden coincidir. Un ci cl o en un grafo dirigido es el
camino de longitud mayor o igual que 1 donde w1 = wn . Se llamar ci clo
s im p le si el camino es simple.
Si a={u,v } es una arista de G escribiremos slo a=uv , y diremos que a une
los vrtices u y v o que u y v son ext r em os de a . Una arista a=uu se llama
b u cl e. Una arista que aparece repetida en E se llama a r i s t a m l t i p l e.
Pgina 99
Un ci cl o es un camino simple y cerrado.
Un grafo es con ex o si desde cualquier vrtice existe un camino hasta
cualquier otro vrtice del grafo.
Un gr a fo es con exo si para cada par de vrtices u y v existe un camino de
u a v . Si G es un grafo no conexo (o disconexo), cada uno de sus subgrafos
conexos maximales se llama com p on e n t e con e xa de G.
Un digrafo D=(V,E) es fu e r t e m e n t e con e xo si para todo par de vrtices u
y v existe un camino dirigido que va de u a v .
Dado un digrafo D, podemos considerar el grafo G no dirigido que se obtiene
al sustituir cada arco (u,v) por la arista (u,v). Si este grafo es conexo, diremos
que el digrafo D es d b i lm e n t e con e xo.
Se dice que un grafo no dirigido es un r b ol si es conexo y acclico.
En algunos textos llaman grafo al que aqu se denomina grafo simple,
permitiendo la presencia de aristas mltiples en los multigrafos y de bucles
en los seudografos.
Pgina 100
Dos vrtices son a d ya cen t es si son extremos de una misma arista. Dos
aristas son a d ya ce n t e s si tienen un extremo comn. Un vrtice y una
arista son i n ci d e n t e s si el vrtice es extremo de la arista. Un vrtice es
a is la d o si no tiene otros vrtices adyacentes.
Un gr a fo com p let o es un grafo simple en el que todo par de vrtices est
unido por una arista. Se representa con Kn al grafo completo de n vrtices.
Un grafo G=(V,E) se llama b i p a r t i t o (o bipartido) si existe una particin
de V, V=X U Y, tal que cada arista de G une un vrtice de X con otro de Y.
(Se designa por Kr ,s al gr a fo b i p a r t i t o co m p le t o en que | X| = r e | Y| = s,
y hay una arista que conecta cada vrtice de X con cada vrtice de Y).
El nmero de vrtices de un grafo G es su or d en y el nmero de aristas su
t a m a o . Designaremos el orden con n y el tamao con q y utilizaremos la
notacin de grafo (n,q).
Dos grafos G=(V,E) y G=(V,E) son is om or fos si existe una biyeccin
f:V V que conserva la adyacencia. Es decir, u,v V, u y v son
adyacentes en G f( u) y f( v ) son adyacentes en G.
Un s u bgr a fo de G=(V,E) es ot ro grafo H=(V,E) tal que V V y E E. Si
V= V se dice que H es un subgrafo gen er a d or .
Se llama gr a d o de un vrtice v al nmero de aristas que lo tienen como
extremo, (cada bucle se cuenta, por tanto, dos veces). Se designa por d( v ) .
Un gr a fo r egu la r es un grafo simple cuyos vrtices tienen todos los
mismos grados.
A la sucesin de los grados de los vrtices de G se le denomina s u ces in
d e gr a d os del grafo G. Una sucesin de enteros no negativos se dice
sucesin gr fica si es la sucesin de grados de un grafo simple.
8 .2 Rep r e s e n t a cion e s d e Gr a fos
Existen dos formas de mantener un grafo G en la memoria de una
computadora, una se llama R ep r es en t a ci n s ecu en ci a l de G, la cual se
basa en la matriz de adyacencia.
La otra forma, es la llamada R ep r es en t a ci n en la z a d a de G y se basa en
listas enlazadas de vecinos. Independientemente de la forma en que se
mantenga un grafo G en la memoria de una computadora, el grafo G
normalmente se introduce en la computadora por su definicin formal: Un
conjunto de nodos y un conjunto de aristas.
Pgina 101
8 .2.1 Ma t r iz y Lis t a d e Ad ya ce n cia
Dado un grafo G = (V, E), podemos representar un grafo a travs de una
matriz de dimensin V x V, donde el contenido podr ser de nmeros
binarios (0;1) o de nmero enteros (-1;0;1).
Para ejemplificar, analicemos el grafo G:
La ca r d in a lid a d de vrtices del grafo G es 6, por tanto, para su
representacin, deberemos tener una matriz de adyacencias 6x6. Utilizando
valores binarios, podemos representarla de esta forma:
ma[i,j] =
Conforme observamos, la matriz de adyacencias est formada siguiendo la
siguiente regla: m a [ i , j] = 1, si i e s a d ya ce n t e a j, y 0 en ca s o
co n t r a r i o. Como estamos trabajando con un dgrafo, debemos establecer
cual es el origen y cual es el destino. En el ejemplo presentado, el origen est
definido por la letra indicadora de lnea. Por ejemplo, A est conectado con
B, ms no en sentido contr ario, por eso ma[A,B] es 1 y ma[B,A] es 0 .
Para resolver esto, podemos hacer una representacin alternativa: m a [i,j]
= -1 si i e s or igen de a dya ce n cia con j, 1 si i e s el d e s t i n o de
a dya ce n ci a con j, y e s 0 p a r a l os d em s vr t ices n o en vu e l t os e n l a
a dya ce n cia . Esto es sintetizado en la siguiente matriz:
Pgina 102
ma[i,j] =
Como ejemplo, observemos el elemento ma[A,B] , ma[A,C] e ma[A,D] que
poseen valor -1. Esto indica que A es origem de arcos para C , D y E. Tambin
observemos ma[F,D] y ma[F,E] , con valor 1, indicando que F r ecibe los
arcos de D y E.
A pesar de la metodologa empleada, se observa que para una aplicacin
dada que necesite de alteracin del grafo, sera inadecuada la representacin
a travs de estructuras fijas, exigiendo, entonces, est ructuras dinmicas.
Li s t a d e Ad ya ce n ci a s
Para que sea pos ible remodelar un grafo en t iempo de ejecucin , se torna
necesaria la utilizacin dinmica de su representacin. Por eso, la
representacin de adyacencias entre vrtices puede ser hecha a travs de
listas lineales.
Su constr uccin es realizada por un vector dinmico con listas encadenadas
formando un ndice de vrtices. De cada elemento de ndice parte una lista
encadenada descr ibiendo los vrtices adyacentes conectados.
Como ejemplo, para el grafo G presentado anteriormente, visualizaremos la
siguiente representacin:
Pgina 103
La lista encadenada es formada por nodos que contienen el dat o del vrtice
(let ra) y el puntero para el vrtice adyacente a lo indicado en el ndice (vector
descript or de vrtices). Eventualmente los nodos pueden exigir otros
campos, tales como marcas de visita al vrtice, datos adicionales para
procesamiento de la secuencia del grafo, etc.
Esta es la forma de representacin ms flexible para la representacin de
grafos. Obviamente que aplicaciones especficas permitir n el uso de otras
formas de representacin. Cabe aqu destacar que es posible la descripcin
de grafos a travs de sus aristas, lo que puede demandar una matriz para su
descripcin.
La suma de las longitudes de todas las listas es |E|, si G es direccional, y
2|E| si G es no direccional la cantidad de memoria necesaria es siempre
O(max(V, E)) = O(V + E).
La matriz de adyacencias de G = (V, E) supone que los vrtices estn
numerados 1, 2, , |V| arbitrariamente, y consiste en una matriz A = (a
ij
)
de |V||V|, tal que:
a
ij
1 si (i, j) E,
0 en otro caso.
'
Esta representacin requiere (V
2
) memoria, independientemente del
nmero de aristas en G.
La m a t r iz d e a d ya cen cia siempre es simtrica porque aij = aji . La list a
d e Ad ya ce n cia es una lista compuesta por vrtices y una sublista
conteniendo las aristas que salen de l.
En el caso de las lis t a s d e a d ya cen cia el espacio ocupado es O(V + E), muy
distinto del necesario en la matriz de adyacencia, que es de O(V
2
). La
representacin por listas de adyacencia, por tanto, ser ms adecuada para
grafos dispersos.
8.2.2 Ma t r iz y Lis t a d e I n cid en cia
Este tipo de matriz representa un grafo a partir de sus aristas. Como exige
muchas veces la utilizacin de una matriz mayor dado que el mtodo de la
matriz de adyacencias, no esta t an utilizada en cuant o a aquella. La matriz
alojada deber tener dimensiones V x E.
El principio de est a representacin est en la regla: m i [ i,j] = 1 s i el vr t ice
i in cid e con l a a r is t a j, y 0 en ca s o co n t r a r i o . Ejemplificando a partir
del grafo G anteriormente presentado, tendr emos una matriz:
Pgina 104
mi[i,j] =
8 .3 Recor r id os d e Gr a fos
En muchas aplicaciones es necesario visitar todos los vrtices del grafo a
partir de un nodo dado. Algunas aplicaciones son:
Encontrar ciclos
Encontrar componentes conexas
Encontrar rboles cobertores
Hay dos enfoques bsicos:
Recorrido (o bsqueda) en amplitud (b r ea d t h -f i r s t s ea r ch):
Se visita a todos los vecinos directos del nodo inicial, luego a los
vecinos de los vecinos, etc.
Recorrido (o bsqueda) en profundidad (d e p t h -f i r s t s ea r ch):
La idea es alejarse lo ms posible del nodo inicial (sin repetir nodos),
luego devolverse un paso e intentar lo mismo por otro camino.
8 .3.1 Recor r id os en Am p lit u d
La Bsqueda en Amplitud (BFS) es uno de los algoritmos ms simples para
recorrer un grafo y es el modelo de muchos algoritmos sobre grafos.
Dado un grafo G = (V, E) y un vrtice de partida s, BFS explora
sistemticamente las aristas de G para descubrir todos los vrtices
alcanzables desde s:
Calcula la distancia mnimo nmero de aristas de s a cada
vrtice alcanzable.
Produce un rbol con raz s que contiene todos los vrtices
alcanzables.
Para cualquier vrtice v alcanzable desde s , la ruta de s a v en el
rbol contiene el mnimo nmero de aristas es una ruta ms
cort a.
Funciona en grafos direccionales y no direccionales.
Pgina 105
BFS expande la frontera entre vrtices descubiertos y no descubiertos
uniformemente en toda la amplitud de la frontera.
Descubre todos los vrtices a distancia k antes de descubrir cualquier vrtice
a distancia k + 1.
BFS pinta cada vrtice BLANCO, PLOMO o NEGRO, segn su estado:
Todos los vrtices empiezan BLANCOs.
Un vrtice es descubierto la primera vez que es encontrado, y se pinta
PLOMO.
Cuando se ha descubierto todos los vrtices adyacentes a un vrtice
PLOMO, ste se pinta NEGRO.
Los vrtices PLOMOs pueden tener vrtices adyacentes BLANCOs
representan la frontera entre vrtices descubiertos y no descubiertos.
BFS construye un rbol de amplitud:
Inicialmente, el rbol slo contiene su raz el vrtice s.
Cuando se descubre un vrtice BLANCO v mientras se explora la lista
de adyacencias de un vrtice u, v y la arista (u, v ) se agregan al rbol,
y u se convierte en el predecesor o padre de v en el rbol.
En la siguiente versin de BFS:
El grafo se representa mediante listas de adyacencias.
Para cada vrtice u, se almacena: el color en color[u], el predecesor
en [u], y la distancia desde s en d[u].
El conjunto de vrtices PLOMOs se maneja en la cola Q.
El rbol de amplitud o grafo predecesor de G se define como
G
= (V
, E
), en que:
V
= {v V : [v ] NI L} {s}, y
E
= {( [v ], v ) E : v V
{s}};
Las aristas en E
):
E
= {( [v ], v ) : v V [v ] NI L}
las aristas en E