transparencias de algorítmica

Upload: perpetuo-mogudo

Post on 04-Apr-2018

254 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/31/2019 Transparencias de Algortmica

    1/250

    Algortmica

    Conrado MartnezU. Politcnica Catalunya

    Septiembre 2012

  • 7/31/2019 Transparencias de Algortmica

    2/250

    1 Repaso de Conceptos Algortmicos

    2 Algoritmos Voraces

    3 Programacin Dinmica

    4 Flujos sobre Redes y Programacin Lineal

    5 Algoritmos Probabilsticos

    6 Estructuras de Datos Avanzadas

  • 7/31/2019 Transparencias de Algortmica

    3/250

    1 Repaso de Conceptos AlgortmicosAnlisis de Algoritmos

    Divide y vencersTablas de HashColas de prioridad

    2 Algoritmos Voraces

    3 Programacin Dinmica

    4 Flujos sobre Redes y Programacin Lineal

    5 Algoritmos Probabilsticos

    6 Estructuras de Datos Avanzadas

  • 7/31/2019 Transparencias de Algortmica

    4/250

    Eficiencia de un algoritmo = consumo de recursos decmputo: tiempo de ejecucin y espacio de memoriaAnlisis de algoritmos Propiedades sobre la eficienciade algoritmos

    Comparar soluciones algortmicas alternativasPredecir los recursos que usar un algoritmo o EDMejorar los algoritmos o EDs existentes y guiar el diseode nuevos algoritmos

  • 7/31/2019 Transparencias de Algortmica

    5/250

    En general, dado un algoritmo cuyo conjunto de entradas essu eficiencia o coste(en tiempo, en espacio, en nmero de

    operaciones de E/S, etc.) es una funcin de en N (o Q o R,segn el caso):

    N

    Ahora bien, caracterizar la funcin puede ser muycomplicado y adems proporciona informacin inmanejable,

    difcilmente utilizable en la prctica.

  • 7/31/2019 Transparencias de Algortmica

    6/250

    Sea el conjunto de entradas de tamao y N lafuncin restringida a .

    Coste en caso mejor:mejor

    Coste en caso peor:

    peor

    Coste promedio:

    avg

  • 7/31/2019 Transparencias de Algortmica

    7/250

    1 Para todo y para cualquier

    mejor peor

    2 Para todo

    mejor avg peor

  • 7/31/2019 Transparencias de Algortmica

    8/250

    Estudiaremos generalmente slo el coste en caso peor:1 Proporciona garantas sobre la eficiencia del algoritmo, el

    coste nunca exceder el coste en caso peor2 Es ms fcil de calcular que el coste promedio

  • 7/31/2019 Transparencias de Algortmica

    9/250

    Una caracterstica esencial del coste (en caso peor, en casomejor, promedio) es su tasa de crecimiento

    Ejemplo1 Funciones lineales:

    2 Funciones cuadrticas:

    Se dice que las funciones lineales y las cuadrticas tienentasas de crecimiento distintas. Tambin se dice que son de

    rdenes de magnitud distintos.

  • 7/31/2019 Transparencias de Algortmica

    10/250

    1 2 2 4 8 42 4 8 16 64 16

    3 8 24 64 512 2564 16 64 256 4096 2621445 32 160 1024 32768

    6 64 384 4096 262144

  • 7/31/2019 Transparencias de Algortmica

    11/250

    Los factores constantes y los trminos de orden inferior son

    irrelevantes desde el punto de vista de la tasa de crecimiento:p.e. tiene la misma tasa de creciemiento que

    notacin asinttica

    Definicin

    Dada una funcin R R la clase (O-grande de )es

    R R

    En palabras, una funcin est en si existe una constante

    tal que para toda a partir de un cierto punto ( ).

  • 7/31/2019 Transparencias de Algortmica

    12/250

    Aunque es un conjunto de funciones por tradicin seescribe a veces en vez de . Sin embargo,

    no tiene sentido.Propiedades bsicas de la notacin :

    1

    Si entonces2 Es reflexiva: para toda funcin R R ,3 Es transitiva: si y entonces4 Para toda constante ,

  • 7/31/2019 Transparencias de Algortmica

    13/250

    Los factores constantes no son relevantes en la notacinasinttica y los omitiremos sistemticamente: p.e. hablaremosde y no de ; no expresaremos la base delogaritmos ( , ya que podemos pasar de una base a

    otra multiplicando por el factor apropiado:

  • 7/31/2019 Transparencias de Algortmica

    14/250

  • 7/31/2019 Transparencias de Algortmica

    15/250

    Se dice que es la clase de las funciones que crecen noms rpido que . Anlogamente, es la clase de lasfunciones que crecen no ms despacio que .Finalmente,

    es la clase de la funciones con la misma tasa de crecimientoque .La notacin es reflexiva y transitiva, como las otras. Esadems simtrica: si y slo si . Si

    donde entonces .

  • 7/31/2019 Transparencias de Algortmica

    16/250

    Propiedades adicionales de las notaciones asintticas (lasinclusiones son estrictas):

    1 Para cualesquiera constantes , si es una funcincreciente entonces .

    2 Para cualesquiera constantes y , si es creciente,.3 Para cualquier constante , si es creciente,

    .

  • 7/31/2019 Transparencias de Algortmica

    17/250

    Los operadores convencionales (sumas, restas, divisiones,etc.) sobre clases de funciones definidas mediante unanotacin asinttica se extienden de la siguiente manera:

    donde y son conjuntos de funciones. Expresiones de laforma donde es una funcin se entender como

    .Este convenio nos permite escribir de manera cmoda

    expresiones como , , .

  • 7/31/2019 Transparencias de Algortmica

    18/250

    Regla de las sumas:

    Regla de los productos:

    Reglas similares se cumplen para las notaciones y .

    A li i d l it it ti

  • 7/31/2019 Transparencias de Algortmica

    19/250

    Anlisis de algoritmos iterativos

    1 El coste de una operacin elemental es .2 Si el coste de un fragmento es y el de es

    entonces el coste de es .3 Si el coste de es , el de es y el coste de evaluar

    es entonces el coste en caso peor de

    if then

    else

    end if

    es .

  • 7/31/2019 Transparencias de Algortmica

    20/250

    Anlisis de algoritmos recursivos

  • 7/31/2019 Transparencias de Algortmica

    21/250

    Anlisis de algoritmos recursivos

    El coste (en caso peor, medio, . . . ) de un algoritmo recursivo

    satisface, dada la naturaleza del algoritmo, una ecuacinrecurrente: esto es, depender del valor de paratamaos menores. Frecuentemente, la recurrencia adopta unade las dos siguientes formas:

    La primera corresponde a algoritmos que tiene una parte norecursiva con coste y hacen llamadas recursivas con

    subproblemas de tamao , donde es una constante.La segunda corresponde a algoritmos que tienen una parte norecursiva con coste y hacen llamadas recursivas consubproblemas de tamao (aproximadamente) , donde .

  • 7/31/2019 Transparencias de Algortmica

    22/250

    TeoremaSea el coste (en caso peor, en caso medio, ...) de un

    algoritmo recursivo que satisface la recurrencia

    si

    si ,

    donde es una constante, , es una funcin

    arbitraria y para una cierta constante .

    Entoncessi

    sisi

  • 7/31/2019 Transparencias de Algortmica

    23/250

    TeoremaSea el coste (en caso peor, en caso medio, . . . ) de un

    algoritmo recursivo que satisface la recurrencia

    si

    si ,

    donde es una constante, , es una funcinarbitraria y para una cierta constante .

    Sea . Entonces

    si

    si

    si

  • 7/31/2019 Transparencias de Algortmica

    24/250

    1 Repaso de Conceptos AlgortmicosAnlisis de AlgoritmosDivide y vencersTablas de HashColas de prioridad

    2 Algoritmos Voraces

    3 Programacin Dinmica

    4 Flujos sobre Redes y Programacin Lineal

    5 Algoritmos Probabilsticos

    6 Estructuras de Datos Avanzadas

    Introduccin

  • 7/31/2019 Transparencias de Algortmica

    25/250

    Introduccin

    El principio bsico de divide y vencers (en ingls, divide andconquer; en cataln, dividir per conquerir) es muy simple:

    1 Si el ejemplar (instancia) del problema a resolver essuficientemente simple, se encuentra la solucin mediante

    algn mtodo directo.2 En caso contrario, se divideo fragmenta el ejemplar dado

    en subejemplares y se resuelve, independientey recursivamente, el problema para cada uno de ellos.

    3 Las soluciones obtenidas se combinanparaobtener la solucin al ejemplar original.

  • 7/31/2019 Transparencias de Algortmica

    26/250

    El esquema de divide y vencers expresado enpseudocdigo tiene el siguiente aspecto:

    procedure DIVIDE_Y_VENCERAS( )if es simple then

    return SOLUCION_DIRECTA( )else

    DIVIDE

    for to doDIVIDE_Y_VENCERAS

    end forreturn COMBINA

    end if

    end procedure

    Ocasionalmente, si , se habla del esquema dereduccin.

  • 7/31/2019 Transparencias de Algortmica

    27/250

    El esquema de divide y vencers se caracterizaadicionalmente por las siguientes propiedades:

    No se resuelve ms de una vez un mismo subproblema

    El tamao de los subejemplares es, en promedio, una

    fraccin del tamao del ejemplar original, es decir, si esde tamao , el tamao esperado de un subejemplarcualquiera es donde . Con frecuencia, estacondicin se cumplir siempre, no slo en promedio.

    Coste de los algoritmos divide y vencers

  • 7/31/2019 Transparencias de Algortmica

    28/250

    Coste de los algoritmos divide y vencers

    El anlisis de un algoritmo divide y vencers requiere, al igualque ocurre con otros algoritmos recursivos, la resolucin de

    recurrencias. En su caso ms simple las recurrencias son de laforma

    si ,

    si .Este tipo de recurrencia corresponde al coste de unalgoritmo donde conocemos la solucin directa siempre que ,el tamao de , sea menor o igual a , y en caso contrario, sedescompone el ejemplar en subejemplares cuyo tamao esaproximadamente , haciendose llamadas recursivas,siendo el coste conjunto de las funciones de dividir y decombinar. Si bien es habitual que , existen muchassituaciones en las que esto no sucede.

  • 7/31/2019 Transparencias de Algortmica

    29/250

    TeoremaSi entonces la solucin de la recurrencia

    si ,

    si ,

    donde y son constantes, satisface

    si ,

    si

    si ,

    siendo .

  • 7/31/2019 Transparencias de Algortmica

    30/250

  • 7/31/2019 Transparencias de Algortmica

    31/250

    Puesto que es una constante y tenemos que el segundotrmino es ya que

    Ahora tenemos tres casos diferentes a considerar: segn quesea menor, igual o mayor que . Alternativamente, ya que

    , segn que sea mayor, igual o menor que . Si(equivalentemente, ) entonces la suma que

    aparece en el primer trmino es una serie geomtrica acotada

    por una constante, es decir, el primer trmino es . Comoasumimos que , es el primer trmino el que domina y

    .

  • 7/31/2019 Transparencias de Algortmica

    32/250

    Si , tendremos que y la suma vale ; ya que

    , conclumos que. Finalmente, sientonces y el valor de la suma es

    Por tanto, es el segundo trmino el que en este caso domina y

    .

    Bsqueda dicotmica

  • 7/31/2019 Transparencias de Algortmica

    33/250

    q

    Problema: Dado un vector de elementos, en orden

    creciente, y un elemento , determinar el valor , , talque (convendremos que y).

    Si el vector fuese vaco la respuesta es sencilla, pues noest en el vector. Pero para poder obtener una solucin

    recursiva efectiva, debemos realizar la siguientegeneralizacin: dado un segmento o subvector ,

    , ordenado crecientemente, y tal que, determinar el valor , , tal que

    . Este es un ejemplo clsico de inmersin deparmetros.Ahora s, si , el segmento en cuestin no contieneelementos y .

  • 7/31/2019 Transparencias de Algortmica

    34/250

  • 7/31/2019 Transparencias de Algortmica

    35/250

  • 7/31/2019 Transparencias de Algortmica

    36/250

    Algoritmo de Karatsuba y Ofmann

  • 7/31/2019 Transparencias de Algortmica

    37/250

    El algoritmo tradicional de multiplicacin tiene coste paramultiplicar dos enteros de bits, ya la suma de dos enteros de

    bits tiene coste .

    2 3 1 x 6 5 9 = 9 x 2 3 1 + 5 x 2 3 1 x 1 0+ 6 x 2 3 1 x 1 0 0

    = 2079 + 11550 + 138600

    = 152229

  • 7/31/2019 Transparencias de Algortmica

    38/250

    Tambi es de coste cuadrtico el algoritmo de multiplicacin ala rusa:

    while doInv:

    if es par thendivelse

    end ifend while

    Supongamos que e son dos nmeros positivos de

  • 7/31/2019 Transparencias de Algortmica

    39/250

    bits (si no es una potencia de 2 e no tienen ambos lamisma longitud, podemos aadir 0s por la izquierda para queas sea).

    Una idea que no funciona:

  • 7/31/2019 Transparencias de Algortmica

    40/250

    Efectuada la descomposicin y , se

    calculan 4 productos ( , , y ) y se combinanlas soluciones mediante sumas y desplazamientos (shifts). Elcoste de estas operaciones es . Por lo tanto, el coste de lamultiplicacin mediante este algoritmo divide y vencers vienedado por la recurrencia

    cuya solucin es . En este caso , y, y .

  • 7/31/2019 Transparencias de Algortmica

    41/250

    El algoritmo de Karatsuba y Ofmann (1962) realiza lamultiplicacin dividiendo los dos nmeros como antes pero serealizan las siguientes 3 multiplicaciones (recursivamente)

    Y el resultado se calcula a partir de las tres solucionesobtenidas

    El algoritmo requiere realizar 6 adiciones (una de ellas es de

  • 7/31/2019 Transparencias de Algortmica

    42/250

    El algoritmo requiere realizar 6 adiciones (una de ellas es dehecho una resta) frente a las 3 adiciones que se empleaban enel algoritmo anterior. El coste mejora pues el coste de las

    funciones de divisin y de combinacin del algoritmo deKaratsuba y Ofmann sigue siendo lineal y disminuye el nmerode llamadas recursivas.

    La constante oculta en la notacin asinttica es grande y laventaja de este algoritmo frente a los algoritmos bsicos no semanifiesta hasta que es relativamente grande (del orden de200 a 250 bits por multiplicando).

    procedure MULT( , , , , , )

  • 7/31/2019 Transparencias de Algortmica

    43/250

    Require: , ,Ensure: Devuelve el producto de por

    if thenUsar un mtodo simple para calcular el resultado

    elsediv div

    MULT

    MULTDECALA_IZQUIERDA

    Aadir un bit a si es necesarioMULT

    DECALA_IZQUIERDA divreturn

    end ifend procedure

  • 7/31/2019 Transparencias de Algortmica

    44/250

  • 7/31/2019 Transparencias de Algortmica

    45/250

    Supondremos que nuestra entrada es una lista enlazadaconteniendo una secuencia de elementos . Cadaelemento se almacena en un nodo con dos campos: infocontiene el elemento y next es un apuntador al siguiente nodode la lista (indicaremos que un nodo no tiene sucesor con el

    valor especial next = null). La propia lista es, de hecho, unapuntador a su primer nodo. La notacin apuntador campoindica el campo referido del objeto apuntado como en C y C++.Es equivalente a la expresin p .campode Pascal y Modula-2.

    procedure SPLIT( , , )R i

  • 7/31/2019 Transparencias de Algortmica

    46/250

    Require:Ensure:

    while do

    end whilenull

    end procedureprocedure MERGESORT( , )if then

    divSPLITMERGESORT

    MERGESORTfusiona las listas y

    MERGEend if

    end procedure

    Para fusionar razonamos de la siguiente forma: Si esvaca la lista resultante es la otra lista, es decir, la que

  • 7/31/2019 Transparencias de Algortmica

    47/250

    eventualmente es no vaca. Si ambas son no vacascomparamos sus respectivos primeros elementos: el menor delos dos ser el primer elemento de la lista fusionada resultantey a continuacin vendr la lista resultado de fusionar la sublistaque sucede a ese primer elemento con la otra lista.

    procedure MERGE( , )if null then return

    end ifif null then returnend ifif then

    MERGE

    returnelse

    MERGEreturn

    end ifend procedure

  • 7/31/2019 Transparencias de Algortmica

    48/250

    Cada elemento de y es visitado exactamente una vez,

  • 7/31/2019 Transparencias de Algortmica

    49/250

    y ,por lo que el coste de la operacin MERGE es proporcional a lasuma de los tamaos de las listas y ; es decir, su coste es

    . La funcin definida es recursiva final y podemos obtenercon poco esfuerzo una versin iterativa algo ms eficiente.Observese que si el primer elemento de la lista es igual alprimer elemento de se pone en primer lugar al que provienede , por lo que MERGESORT es un algoritmo estable.

    El coste de MERGESORT viene descrito por la recurrencia

    cuya solucin es , aplicando el segundocaso del Teorema 1.

    Algoritmo de Strassen

  • 7/31/2019 Transparencias de Algortmica

    50/250

    El algoritmo convencional de multiplicacin de matrices tienecoste para multiplicar dos matrices .

    for to dofor to do

    for to do

    end forend for

    end for

  • 7/31/2019 Transparencias de Algortmica

    51/250

    Para abordar una solucin con el esquema divide y vencersse descomponen las matrices en bloques:

    donde , etc.

  • 7/31/2019 Transparencias de Algortmica

    52/250

    Cada bloque de requiere dos multiplicaciones de bloques detamao y dos sumas cuyo coste es . El costedel algoritmo divide y vencers as planteado tendra coste

    es decir, .Para conseguir una solucin ms eficiente debemos reducir elnmero de llamadas recursivas.

    Strassen (1969) propuso una forma de hacer justamente esto.En el libro de Brassard & Bratley se detalla una posible manera

  • 7/31/2019 Transparencias de Algortmica

    53/250

    En el libro de Brassard & Bratley se detalla una posible manerade hallar la serie de frmulas que producen el resultadodeseado. Un factor que complica las cosas es que la

    multiplicacin de matrices no es conmutativa, a diferencia de loque sucede con la multiplicacin de enteros.Se obtienen las siguientes 7 matrices , mediante 7productos y 14 adiciones/sustracciones

    Mediante 10 adiciones/sustracciones ms podemos obtener

  • 7/31/2019 Transparencias de Algortmica

    54/250

    Mediante 10 adiciones/sustracciones ms, podemos obtenerlos bloques de la matriz resultante :

    Puesto que las operaciones aditivas tienen coste , elcoste del algoritmo de Strassen viene dado por la recurrencia

    cuya solucin es .

  • 7/31/2019 Transparencias de Algortmica

    55/250

    El algoritmo de Strassen tuvo un enorme impacto terico yaque fue el primer algoritmo de multiplicacin de matrices cuya

    complejidad era ; lo cual tena tambin implicaciones en eldesarrollo de algoritmos ms eficientes para el clculo dematrices inversas, de determinantes, etc. Adems era uno delos primeros casos en que las tcnicas algortmicas superabanlo que hasta el momento pareca una barrera infranqueable.En aos posteriores se han obtenido algoritmos todava mseficientes. El ms eficiente conocido es el de Coppersmith yWinograd (1986) cuyo coste es .El algoritmo de Strassen no es competitivo en la prctica,

    excepto si es muy grande ( ), ya que las constantes ytrminos de orden inferior del coste son muy grandes.

    QuickSortQUICKSORT (Hoare, 1962) es un algoritmo de ordenacin que

  • 7/31/2019 Transparencias de Algortmica

    56/250

    usa el principio de divide y vencers, pero a diferencia de losejemplos anteriores, no garantiza que cada subejemplar tendr

    un tamao que es fraccin del tamao original.La base de quicksortes el procedimiento de PARTICIN: dadoun elemento denominado pivote, debe reorganizarse elsegmento como ilustra la figura.

    El procedimiento de particin sita a un elemento, el pivote, ensu lugar apropiado. Luego no queda ms que ordenar los

  • 7/31/2019 Transparencias de Algortmica

    57/250

    segmentos que quedan a su izquierda y a su derecha. Mientrasque en MERGESORT la divisin es simple y el trabajo se realiza

    durante la fase de combinacin, en QUICKSORT sucede locontrario.Para ordenar el segmento el algoritmo queda as

    procedure QUICKSORT( , , )

    Ensure: Ordena el subvectorif then

    usar un algoritmo de ordenacin simpleelse

    PARTICIN

    QUICKSORTQUICKSORT

    end ifend procedure

  • 7/31/2019 Transparencias de Algortmica

    58/250

    En vez de usar un algoritmo de ordenacin simple (p.e.

    ordenacin por insercin) con cada segmento de o menoselementos, puede ordenarse mediante el algoritmo deinsercin al final:

    QUICKSORT SIZEINSERTSORT SIZE

    Puesto que el vector est quasi-ordenado tras aplicar|quicksort|, el ltimo paso se hace en tiempo , donde

    SIZE .Se estima que la eleccin ptima para el umbral o corte de

    recursin oscila entre 20 y 25.

  • 7/31/2019 Transparencias de Algortmica

    59/250

    Existen muchas formas posibles de realizar la particin. En

    Bentley & McIlroy (1993) se discute un procedimiento departicin muy eficiente, incluso si hay elementos repetidos.Aqu examinamos un algoritmo bsico, pero razonablementeeficaz.Se mantienen dos ndices y de tal modo que

    contiene elementos menores o iguales que el pivote , ycontiene elementos mayores o iguales. Los ndices

    barren el segmento (de izquierda a derecha, y de derecha aizquierda, respectivamente), hasta que y o secruzan ( ).

    procedure PARTICIN( , , , )

  • 7/31/2019 Transparencias de Algortmica

    60/250

    p ( , , , )Require:Ensure:

    ; ;while dowhile do

    end while

    while do

    end whileif then

    end if

    end while;

    end procedure

    El coste de QUICKSORT en caso peor es y por lo tantopoco atractivo en trminos prcticos. Esto ocurre si en todos ola gran mayora de los casos uno de los subsegementos

  • 7/31/2019 Transparencias de Algortmica

    61/250

    la gran mayora de los casos uno de los subsegementoscontiene muy pocos elementos y el otro casi todos, p.e. assucede si el vector est ordenado creciente odecrecientemente. El coste de la particin es y entoncestenemos

    Sin embargo, en promedio, el pivote quedar ms o menoscentrado hacia la mitad del segmento como sera deseablejustificando que quicksortsea considerado un algoritmo dedivide y vencers.

  • 7/31/2019 Transparencias de Algortmica

    62/250

  • 7/31/2019 Transparencias de Algortmica

    63/250

    Definicin

  • 7/31/2019 Transparencias de Algortmica

    64/250

    Dado un conjunto de pesos , es una funcin de formapara el conjunto de pesos si

    1

    2 existe una constante tal que

    Un mtodo simple y que funciona usualmente para calcularfunciones de forma consiste en sustituir por en ,multiplicar por y tomar el lmite para .

    L t i l l d h f i

  • 7/31/2019 Transparencias de Algortmica

    65/250

    Las extensiones a los nmeros reales de muchas funcionesdiscretas son inmediatas, p.e. .

    Para los nmeros binomiales se puede emplear laaproximacin

    La extensin de los factoriales a los reales viene dada por lafuncin gamma de Euler y la de los nmeros armnicoses la funcin .Por ejemplo, en quicksort los pesos son todos iguales:

    . La funcin de forma correspondiente es

    .

    Teorema (Roura, 1997)Sea descrita por la recurrencia

  • 7/31/2019 Transparencias de Algortmica

    66/250

    sea una funcin de forma correspondiente a los pesos

    , y , para y constantes.

    Sea y .

    Entonces

    si ,

    si y ,

    si ,

    donde es la nica solucin real no negativa de la

    ecuacin

    Consideremos . Ya hemos visto que los pesos sony . Por tanto , y .

    Puede comprobarse fcilmente que se dan todas las

  • 7/31/2019 Transparencias de Algortmica

    67/250

    Puede comprobarse fcilmente que se dan todas lascondiciones necesarias para la aplicacin del CMT.

    Calculamos

    por lo que tendremos que aplicar el caso 2 del CMT y calcular

    Por lo tanto,

    QuickSelectEl problema de la seleccin consiste en hallar el -simo de

  • 7/31/2019 Transparencias de Algortmica

    68/250

    entre elementos dados. En concreto, dado un vector conelementos y un rango , , un algoritmo de seleccin

    debe hallar el -simo elemento en orden ascendente. Sientonces hay que encontrar el mnimo, si entonces hayque hallar el mximo, si entonces debemos hallar lamediana, etc.

    Es fcil resolver el problema con coste ordenandopreviamente el vector y con coste , recorriendo el vectory manteniendo los elementos menores de entre los yaexaminados. Con las estructuras de datos apropiadas puederebajarse el coste a , lo cual no supone una mejora

    sobre la primera alternativa si .QUICKSELECT (Hoare, 1962), tambin llamado F IND yone-sidedQUICKSORT, es una variante del algoritmoQUICKSORT para la seleccin del -simo de entreelementos.

  • 7/31/2019 Transparencias de Algortmica

    69/250

    Supongamos que efectuamos una particin de un subvector

    , conteniendo los elementos -simo a -simo de , ytal que , respecto a un pivote . Una vez finalizada laparticin, supongamos que el pivote acaba en la posicin .Por tanto, en estn los elementos -simo a

    -simo de y en estn los elementos

    -simo a -simo. Si hemos acabado ya quehemos encontrado el elemento solicitado. Si entoncesprocedemos recursivamente en el subvector de la izquierda

    y si entonces encontraremos el elementobuscado en el subvector .

  • 7/31/2019 Transparencias de Algortmica

    70/250

    Puesto que QUICKSELECT es recursiva final es muy simple

  • 7/31/2019 Transparencias de Algortmica

    71/250

    obtener una versin iterativa eficiente que no necesita espacioauxiliar.En caso peor, el coste de QUICKSELECT es . Sinembargo, su coste promedio es donde la constante deproporcionalidad depende del cociente . Knuth (1971) hademostrado que , el nmero medio de comparaciones

    necesarias para seleccionar el -simo de entre es:

    El valor mximo se alcanza para ; entonces.

  • 7/31/2019 Transparencias de Algortmica

    72/250

    Consideremos ahora el anlisis del coste promedio

    suponiendo que adopta cualquier valor entre 1 y con igualprobabilidad.

    E nm. de comp. el pivote es el -simo

    puesto que el pivote es el -simo con igual probabilidad paratoda .

    La probabilidad de que es y entonces ya habremosacabado. La probabilidad de continuar a la izquierda es

    h b d h i

  • 7/31/2019 Transparencias de Algortmica

    73/250

    y entonces se habrn de hacer comparaciones.Anlogamente, con probabilidad se continuar en elsubvector a la derecha y se harn comparaciones.

    Aplicando el CMT con la funcin de forma

    obtenemos y .

  • 7/31/2019 Transparencias de Algortmica

    74/250

    La nica diferencia entre el algoritmo de seleccin de Hoare yel de Rivest y Floyd reside en la manera en que elegimos los

  • 7/31/2019 Transparencias de Algortmica

    75/250

    el de Rivest y Floyd reside en la manera en que elegimos lospivotes. El algoritmo de Rivest y Floyd obtiene un pivote de

    calidad empleando el propio algoritmo, recursivamente, paraseleccionar los pivotes!De hecho, el algoritmo calcula una pseudomediana y elige stacomo pivote. Se subdivide el subvector en bloques deelementos (excepto posiblemente el ltimo bloque), con

    constante e impar, y para cada uno de ellos se obtiene sumediana. El coste de esta fase es y como resultado seobtiene un vector con elementos. Sobre dicho vector seaplica el algoritmo de seleccin para hallar la mediana. Como

    el pivote seleccionado es la pseudomediana de loselementos originales, ello garantiza que al menoselementos son mayores que el pivote.

  • 7/31/2019 Transparencias de Algortmica

    76/250

    Por lo tanto, el coste en caso peor satisface

    Utilizando la versin discreta del CMT, si

    Rivest y Floyd usaron el valor en su formulacin originalde este algoritmo.

    1 Repaso de Conceptos AlgortmicosAnlisis de Algoritmos

  • 7/31/2019 Transparencias de Algortmica

    77/250

    gDivide y vencers

    Tablas de HashColas de prioridad

    2 Algoritmos Voraces

    3 Programacin Dinmica

    4 Flujos sobre Redes y Programacin Lineal

    5 Algoritmos Probabilsticos

    6 Estructuras de Datos Avanzadas

    Tablas de dispersin (hash)

  • 7/31/2019 Transparencias de Algortmica

    78/250

    Una tabla de dispersin(ing: hash table) permite almacenar unconjunto de elementos (o pares clave-valor) mediante unafuncin de dispersin que va del conjunto de claves alconjunto de ndices o posiciones de la tabla (p.e. ).

    Idealmente la funcin de dispersin hara corresponder acada uno de los elementos (de hecho a sus claves) quequeremos almacenar una posicin distinta. Obviamente, estono ser posible en general y a claves distintas lescorresponder la misma posicin de la tabla.

  • 7/31/2019 Transparencias de Algortmica

    79/250

    Pero si la funcin de dispersin dispersa eficazmente lasclaves, el esquema seguir siendo til, ya que la probabilidadde que el diccionario a representar mediante la tabla de hashcontenga muchas claves con igual valor de ser pequea.Dadas dos claves e distintas, se dice que e son

    sinnimos, o que colisionan, si .El problema bsico de la implementacin de un diccionariomediante una tabla de hash consistir en la definicin de unaestrategia de resolucin de colisiones.

  • 7/31/2019 Transparencias de Algortmica

    80/250

    Funciones de hash

  • 7/31/2019 Transparencias de Algortmica

    81/250

    Una buena funcin de hash debe tener las siguientespropiedades:1 Debe ser fcil de calcular2 Debe dispersar de manera razonablemente uniforme el

    espacio de las claves, es decir, si dividimos el conjunto de

    todas las claves en grupos de sinnimos, todos los gruposdeben contener aproximadamente el mismo nmero declaves.

    3 Debe enviar a posiciones distantes a claves que son

    similares.

    La construccin de buenas funciones de hash no es fcil yrequiere conocimientos muy slidos de varias ramas de las

  • 7/31/2019 Transparencias de Algortmica

    82/250

    matemticas. Est fuertemente relacionada con la

    construccin de generadores de nmeros pseudoaleatorios.Como regla general da buenos resultados calcular un nmeroentero positivo a partir de la representacin binaria de la clave(p.e. sumando los bytes que la componen) y tomar mdulo ,el tamao de la tabla. Se recomienda que sea un nmero

    primo.La clase Hash define el operador () de manera que si hes un objeto de la clase Hash y x es un objeto de la claseT, podemos aplicar h(x). Esto nos devolver un nmeroentero. La operacin privada hash de la clase Diccionariocalcular el mdulo mediante h(x) % _M de manera queobtengamos un ndice vlido de la tabla, entre 0 y _ M - 1.

    // especializacin del template para T = string

    template class Hash {

    public:

    int operator()(const string& x) const throw() {

  • 7/31/2019 Transparencias de Algortmica

    83/250

    p g

    int s = 0 ;

    for (int i = 0; i < x.length(); ++i)s = s * 37 + x[i];

    return s;

    };

    // especializacin del template para T = int

    template class Hash {

    static long const MULT = 31415926;

    public:

    int operator()(const int& x) const throw() {

    long y = ( ( x * x * MULT) > 4;

    return y;

    }

    };

    Otras funciones de hash ms sofisticadas emplean sumas

    ponderadas o transformaciones no lineales (p.e. elevan alcuadrado el nmero representado por los bytes centrales dela clave).

    Resolucin de colisiones

  • 7/31/2019 Transparencias de Algortmica

    84/250

    Existen dos grandes familias de estrategias de resolucin decolisiones. Por razones histricas, que no lgicas, se utilizanlos trminos dispersin abierta (ing: open hashing) ydireccionamiento abierto (ing: open addressing).

    Estudiaremos dos ejemplos representativos: tablas abiertascon sinnimos encadenados (ing: separate chaining) y sondeolineal (ing: linear probing).

    Sinnimos encadenados

    En las tablas con sinnimos encadenados cada entrada de latabla da acceso a una lista enlazada de sinnimos

  • 7/31/2019 Transparencias de Algortmica

    85/250

    tabla da acceso a una lista enlazada de sinnimos.

    template

    class Diccionario {

    ...

    private:

    struct nodo {

    Clave _k;

    Valor _v;

    nodo* _sig;

    // constructora de la clase nodonodo(const Clave& k, const Valor& v,

    nodo* sig = NULL);

    };

    nodo** _Thash; // tabla de punteros a nodo

    int _M; // tamao de la tabla

    int _n; // numero de elementos

    double _alfa_max; // factor de carga

    nodo*

    busca_sep_chain(const Clave& k) const throw();

    void inserta_sep_chain(const Clave& k,

    const Valor& v) throw(error);

    void elimina_sep_chain(const Clave& k) throw();

    };

    M = 13

    h (x) = x mod M

    X = { 0, 4, 6, 10, 12, 13, 17, 19, 23, 25, 30}

  • 7/31/2019 Transparencias de Algortmica

    86/250

    0

    6

    10

    12

    13

    19

    23

    25

    41730

    0

    2

    5

    7

    1

    3

    4

    6

    8

    9

    10

    11

    12

    Para la insercin, se accede a la lista correspondientemediante la funcin de hash y se recorre para determinar si ya

  • 7/31/2019 Transparencias de Algortmica

    87/250

    mediante la funcin de hash, y se recorre para determinar si ya

    exista o no un elemento con la clave dada. En el primer caso,se modifica la informacin asociada; en el segundo se aadeun nuevo nodo a la lista con el nuevo elemento.Puesto que estas listas de sinnimos contienen por lo generalpocos elementos lo ms efectivo es efectuar las inserciones

    por el inicio (no hace falta usar fantasmas, cierre circular, etc.).Existen variantes en que las listas de sinnimos estnordenadas o se sustituyen por rboles de bsqueda, pero nocomportan una ventaja real en trminos prcticos (el costeasinttico terico es mejor, pero el criterio no es efectivo ya que

    el nmero de elementos involucrado es pequeo).

  • 7/31/2019 Transparencias de Algortmica

    88/250

    La bsqueda es tambin simple: se accede a la lista apropiadamediante la funcin de hash y se realiza un recorridosecuencial de la lista hasta que se encuentra un nodo con la

    clave dada o la lista se ha examinado sin xito.

    template

    void Diccionario::inserta(const Clave& k,

    const Valor& v) throw(error) {

    if (_n / _M > _alfa_max)

    // l t bl t d i d ll i

  • 7/31/2019 Transparencias de Algortmica

    89/250

    // la tabla est demasiado llena ... enviar un error

    // o redimensionar

    inserta_sep_chain(k, v);

    }

    template

    void Diccionario::inserta_sep_chain(

    const Clave& k, const Valor& v) throw(error) {

    int i = hash(k);

    nodo* p = _Thash[i];

    // buscamos en la lista de sinnimos

    while (p != NULL && p -> _k != k)

    p = p -> _sig;

    // lo insertamos al principio

    // si no estaba

    if (p == NULL) {

    _Thash[i] = new nodo(k, v, _Thash[i]);

    ++_n;

    }

    else

    p - > _ v = v ;

    }

    template

    void Diccionario::busca(const Clave& k,

    bool& esta, Valor& v) const throw(error) {

  • 7/31/2019 Transparencias de Algortmica

    90/250

    nodo* p = buscar_sep_chain(k);

    if (p == NULL)

    esta = false;else {

    esta = true;

    v = p - > _ v ;

    }

    }

    template

    Diccionario::nodo*Diccionario::busca_sep_chain(const

    Clave& k) const throw() {

    int i = hash(k);

    nodo* p = _Thash[i];

    // buscamos en su lista de sinnimos

    while (p != NULL && p -> _k != k)

    p = p -> _sig;

    return p;

    }

    template

    void Diccionario::elimina(const

    Clave& k) throw() {

    eliminar_sep_chain(k);

    }

  • 7/31/2019 Transparencias de Algortmica

    91/250

    template void Diccionario::eliminar_sep_chain

    (const Clave& k) throw() {

    int i = hash(k);

    nodo* p = _Thash[i];

    nodo* ant = NULL; // apuntara al anterior de p

    // buscamos en su lista de sinnimos

    while (p != NULL && p -> _k != k) {ant = p;

    p = p -> _sig;

    }

    // si p != NULL, lo quitamos de la

    // lista teniendo en cuenta que puede

    // ser el primero

    if (p != NULL) {

    --_n;

    if (ant != NULL)

    ant -> _sig = p -> _sig;

    else

    _Thash[i] = p -> _sig;

    delete p;

    }

    }

  • 7/31/2019 Transparencias de Algortmica

    92/250

    Sea el nmero de elementos almacenados en la tabla conencadenamiento de sinnimos. En promedio, cada lista tendr

    elementos y el coste de bsquedas (con y sin xito),de inserciones y borrados ser proporcional a . Si es unvalor razonablemente pequeo entonces podemos considerar

    que el coste promedio de todas las operaciones sobre la tablade hash es , ya que es constante.

  • 7/31/2019 Transparencias de Algortmica

    93/250

    Al valor se le denomina factor de carga (ing: load factor). Otravariantes de hash abierto almacenan los sinnimos en unazona particular de la propia tabla, la llamada zona deexcedentes (ing: cellar). Las posiciones de esta zona no son

    direccionables, es decir, la funcin de hash nunca toma susvalores.

    Direccionamiento abierto

    En las estrategias de direccionamiento abierto los sinnimos

  • 7/31/2019 Transparencias de Algortmica

    94/250

    En las estrategias de direccionamiento abierto los sinnimos

    se almacenan en la tabla de hash, en la zona dedireccionamiento. Bsicamente, tanto en bsquedas como eninserciones se realiza una secuencia de sondeos quecomienza en la posicin y a partir de ah contina en

    hasta que encontramos una posicin ocupada por un

    elemento cuya clave es (bsqueda con xito), una posicinlibre (bsqueda sin xito, insercin) o hemos explorado la tablaen su totalidad. Las distintas estrategias varan segn lasecuencia de sondeos que realizan. La ms sencilla de todases el sondeo lineal: , realizndose losincrementos mdulo .

    Sondeo lineal

    template

  • 7/31/2019 Transparencias de Algortmica

    95/250

    p yp

    class Diccionario {

    ...

    private:

    enum Estado {libre, borrado, ocupado};

    struct nodo {

    Clave _k;

    Valor _v;

    Estado _estado;

    // constructora de la clase nodo

    nodo(const Clave& k, const Valor& v, Estado e = libre);

    };

    nodo* _Thash; // tabla de nodos

    int _M; // tamao de la tabla

    int _n; // numero de elementos

    double _alfa_max; // factor de carga

    int busca_linear_probing(const Clave& k) const throw();

    void inserta_linear_probing(const Clave& k,

    const Valor& v) throw(error);void elimina_linear_probing(const Clave& k) throw();

    };

    0 0 ocupado 0 0 ocupado0 0

    M = 13

    h (x) = x mod M

    X = { 0, 4, 6, 10, 12, 13, 17, 19, 23, 25, 30}

    (incremento 1)

  • 7/31/2019 Transparencias de Algortmica

    96/250

    2

    5

    7

    1

    3

    4

    6

    8

    9

    10

    11

    12 ocupado12

    10

    6

    4

    libre

    17

    19

    ocupado

    ocupado

    ocupado

    ocupado

    ocupado

    ocupado

    ocupado

    libre

    libre

    libre

    23

    13

    2

    5

    7

    1

    3

    4

    6

    8

    9

    10

    11

    12 ocupado12

    10

    6

    4

    libre

    17

    19

    ocupado

    ocupado

    ocupado

    ocupado

    ocupado

    ocupado

    ocupado

    libre

    23

    13

    25

    30

    ocupado

    ocupado

    2

    5

    7

    1

    3

    4

    6

    8

    9

    10

    11

    12 12

    10

    4

    6

    + {0, 4, 6, 10, 12} + {13, 17, 19, 23} + {25, 30}

    // Solo se invoca si hay al menos un sitio// no ocupado en la tabla: _n < _M

    template

    void

    Diccionario::inserta_linear_probing(

    const Clave& k, const Valor& v) throw(error) {

  • 7/31/2019 Transparencias de Algortmica

    97/250

    int i = hash(k);

    int vistos = 0; // aseguramos una sola pasada// prilibre es la primera posicin borrada

    // que encontremos, vale -1 si no

    // vemos ninguna posicin borrada

    int prilibre = -1;

    while (_Thash[i]._estado != libre

    && _Thash[i]._k != k && vistos < _M) {

    // nos guardamos la primera posicin borrada

    if (_Thash[i]._estado == borrado && prilibre == -1)prilibre == i;

    ++vistos;

    i = (i + 1) % _M;

    }

    // k no est; si sabemos una posicin

    // borrada utilizable, usarla

    if (_Thash[i]._estado == libre $\mid\mid$ _Thash[i]._k != _k) {

    ++_n;if (prilibre != -1) i = prilibre;

    }

    _Thash[i]._k = k; _Thash[i]._v = v;

    _Thash[i]._estado = ocupado;

    }

    template

    int Diccionario::busca(

    const Clave& k,

    bool& esta, Valor& v) const throw(error) {

    int i = busca_linear_probing(k);

  • 7/31/2019 Transparencias de Algortmica

    98/250

    if (_Thash[i]._estado == ocupado &&

    _Thash[i]._k == k) {esta = true;

    v = _Thash[i]. _v;

    }

    else

    esta = false;

    }

    template int Diccionario::busca_linear_probing(

    const Clave& k) const throw() {

    int i = hash(k);

    int vistos = 0; // aseguramos una pasada,

    // no ms

    // buscamos en su lista de sinnimos

    while (_Thash[i]._estado != libre && _Thash[i]._k != k&& vistos < _M) {

    ++vistos;

    i = (i + 1) % _M;

    }

    return i;

    }

    El borrado en tablas de direccionamiento abierto es algo mscomplicado. No basta con marcar la posicin correspondientecomo libre ya que una bsqueda posterior podra no hallar el

  • 7/31/2019 Transparencias de Algortmica

    99/250

    como libre ya que una bsqueda posterior podra no hallar el

    elemento buscado aunque ste se encontrase en la tabla. Ensu lugar debe marcarse la posicin que contena al elementocomo borrada.A efectos de las bsquedas es como si dicha posicinestuviera ocupada. Una posicin borrada puede utilizarsepara colocar nuevos elementos. Para ello, durante la iteracinque busca a la nueva clave podemos anotar la primera (o laltima) de las posiciones borradas vistas y cuando la iteracinfinalice podemos emplear esa posicin en lugar de la posicin

    libre donde finaliza la iteracin previa a la insercinpropiamente dicha.

    0

    1

    0

    13

    0

    1

    0

    13

    0

    1 13

    36

    M = 13

    h (x) = x mod M (incremento 1)

  • 7/31/2019 Transparencias de Algortmica

    100/250

    19, 25 {0, }

    19

    23

    2

    5

    7

    3

    4

    6

    8

    9

    10

    12

    10

    6

    4

    12

    11

    30

    25

    17

    23

    2

    5

    7

    3

    4

    6

    8

    9

    10

    12

    10

    6

    4

    12

    11

    30

    25

    17

    20

    23

    2

    5

    7

    3

    4

    6

    8

    9

    10

    12

    10

    6

    4

    12

    11

    30

    25

    17

    20

    = borrado

    + {20} + {36}

    = libre= ocupado

  • 7/31/2019 Transparencias de Algortmica

    101/250

    template

    void Diccionario::elimina_linear_probing(

    const Clave& k) throw() {

    int i = busca_linear_probing(k);

    if (_Thash[i]._estado == ocupado &&

    _Thash[i]._k == k)

    Thash[i]._estado = borrado;}

    C d l b d d d bl l di i

  • 7/31/2019 Transparencias de Algortmica

    102/250

    Con todo, los borrados degradan notablemente el rendimientogeneral, ya que las posiciones borradas cuentan a efectos dela bsqueda tanto como las realmente ocupadas.El sondeo lineal ofrece algunas ventajas ya que los sinnimostienden a encontrarse en posiciones consecutivas, lo que

    resulta ventajoso en implementaciones sobre memoria externa.Generalmente se usara junto a alguna tcnica de bucketing:cada posicin de la tabla es capaz de albergar elementos.

    Por otra parte tiene algunas serias desventajas y surendimiento es especialmente sensible al factor de carga

    S

  • 7/31/2019 Transparencias de Algortmica

    103/250

    . Si es prximo a (tabla llena o casi llena) elrendimiento ser muy pobre. Si el coste de lasbsquedas con xito (y modificaciones) ser proporcional a

    y el de bsquedas sin xito e inserciones ser proporcional a

    Un fenmeno indeseable que se acenta cuando es prximo

  • 7/31/2019 Transparencias de Algortmica

    104/250

    Un fenmeno indeseable que se acenta cuando es prximo

    a 1 es el apiamiento(ing: clustering). Muchos elementos nopueden ocupar su posicin preferida al estar ocupada porotro elemento que no tiene porqu ser un sinnimo (invasor).Grupos de sinnimos ms o menos dispersos acabanfundindose en grandes clusters y cuando buscamos unacierta clave tenemos que examinar no slo sus sinnimos sinoun buen nmero de claves que no tienen relacin alguna con laclave buscada.

    Redimensionamiento

  • 7/31/2019 Transparencias de Algortmica

    105/250

    Muchos lenguajes de programacin permiten crear tablasfijando su tamao en tiempo de ejecucin. Entonces es posibleutilizar la llamada tcnica de redimensionamiento(ing:resizing). Si el factor de carga es muy alto, superando un cierto

    valores umbral, se reclama a la memoria dinmica una tablacuyo tamao es aproximadamente el doble del tamao de latabla en curso y se reinserta toda la informacin de la tabla encurso sobre la nueva tabla.

    Para ello se recorre secuencialmente la tabla en curso y cadauno de los elementos presentes se inserta por el procedimientohabitual en la nueva tabla, usando una funcin de hash distinta,

  • 7/31/2019 Transparencias de Algortmica

    106/250

    obviamente. La operacin de redimensionamiento requieretiempo proporcional al tamao de la tabla en curso (y por tanto); pero hay que hacerla slo muy de vez en cuando. El

    redimensionamiento permite que el diccionario crezca sinlmites prefijados, garantizando un buen rendimiento de todas

    las operaciones y sin desperdiciar demasiada memoria. Lamisma tcnica puede aplicarse a la inversa, para evitar que elfactor de carga sea excesivamente bajo (desperdicio dememoria).Puede demostrarse que, aunque una operacin individual

    podra llegar tener coste , una secuencia deoperaciones de actualizacin tendr coste total .

    1 Repaso de Conceptos AlgortmicosAnlisis de AlgoritmosDivide y vencersTablas de Hash

  • 7/31/2019 Transparencias de Algortmica

    107/250

    Tablas de HashColas de prioridad

    2 Algoritmos Voraces

    3 Programacin Dinmica

    4 Flujos sobre Redes y Programacin Lineal

    5 Algoritmos Probabilsticos

    6 Estructuras de Datos Avanzadas

  • 7/31/2019 Transparencias de Algortmica

    108/250

    Una cola de prioridad (cat: cua de prioritat; ing: priority queue)es una coleccin de elementos donde cada elemento tieneasociado un valor susceptible de ordenacin denominadoprioridad.Una cola de prioridad se caracteriza por admitir inserciones de

    nuevos elementos y la consulta y eliminacin del elemento demnima (o mxima) prioridad.

    template

    class ColaPrioridad {

    public:

    ...

    // A d l l t i id d l l d

  • 7/31/2019 Transparencias de Algortmica

    109/250

    // Aade el elemento x con prioridad p a la cola de

    // prioridad.void inserta(cons Elem& x, const Prio& p) throw(error)

    // Devuelve un elemento de mnima prioridad en la cola de

    // prioridad. Se lanza un error si la cola est vaca.

    Elem min() const throw(error);

    // Devuelve la mnima prioridad presente en la cola de

    // prioridad. Se lanza un error si la cola est vaca.

    Prio prio_min() const throw(error);

    // Elimina un elemento de mnima prioridad de la cola de

    // prioridad. Se lanza un error si la cola est vaca.

    void elim_min() throw(error);

    // Devuelve cierto si y slo si la cola est vaca.

    bool vacia() const throw();

    };

    // Tenemos dos arrays Peso y Simb con los pesos atmicos

  • 7/31/2019 Transparencias de Algortmica

    110/250

    // y smbolos de n elementos qumicos,

    // p.e., Simb[i] = "C" y Peso[i] = 12.2.

    // Utilizamos una cola de prioridad para ordenar la

    // informacin de menor a mayor smbolo en orden alfabtico

    ColaPrioridad P;

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

    P.inserta(Peso[i], Simb[i]);

    int i = 0 ;

    while(! P.vacia()) {

    Peso[i] = P.min();

    Simb[i] = P.prio_min();++i;

    P.elim_min();

    }

  • 7/31/2019 Transparencias de Algortmica

    111/250

    Se puede usar una cola de prioridad para hallar el -simoelemento de un vector no ordenado. Se colocan los primeroselementos del vector en una max-cola de prioridad y acontinuacin se recorre el resto del vector, actualizando la colade prioridad cada vez que el elemento es menor que el mayor

    de los elementos de la cola, eliminando al mximo e insertandoel elemento en curso.

  • 7/31/2019 Transparencias de Algortmica

    112/250

    Muchas de las tcnicas empleadas para la implementacinde diccionarios puede usarse para implementar colas deprioridad (no las tablas de hash ni los tries)

    P.e., con rboles binarios de bsqueda equilibrados se

    puede conseguir coste para inserciones yeliminaciones

    DefinicinUn montculo(ing: heap) es un rbol binario tal que

  • 7/31/2019 Transparencias de Algortmica

    113/250

    1 todos las hojas (subrboles son vacos) se sitan en losdos ltimos niveles del rbol.

    2 en el antepenltimo nivel existe a lo sumo un nodo internocon un slo hijo, que ser su hijo izquierdo, y todos los

    nodos a su derecha en el mismo nivel son nodos internossin hijos.3 el elemento (su prioridad) almacenado en un nodo

    cualquiera es mayor (menor) o igual que los elementosalmacenados en sus hijos izquierdo y derecho.

  • 7/31/2019 Transparencias de Algortmica

    114/250

    Se dice que un montculo es un rbol binario quasi-completodebido a las propiedades 1-2. La propiedad 3 se denominaorden de montculo, y se habla de max-heaps o min-heapssegn que los elementos sean que sus hijos.

  • 7/31/2019 Transparencias de Algortmica

    115/250

    Proposicin

  • 7/31/2019 Transparencias de Algortmica

    116/250

    1 El elemento mximo de un max-heap se encuentra en la

    raz.

    2 Un heap de elementos tiene altura

    La consulta del mximo es sencilla y eficiente pues bastaexaminar la raz.

  • 7/31/2019 Transparencias de Algortmica

    117/250

  • 7/31/2019 Transparencias de Algortmica

    118/250

    Cmo aadir un nuevo elemento?

  • 7/31/2019 Transparencias de Algortmica

    119/250

    1 Colocar el nuevo elemento como ltimo elemento delmontculo, justo a la derecha del ltimo o como primero deun nuevo nivel

    2 Reestablecer el orden de montculo flotando el elementorecin aadido

    En el mtodo flotar el nodo dado se compara con su nodopadre y se realiza el intercambio si ste es mayor que el padre,iterando este paso mientras sea necesario

    Puesto que la altura del heapes el coste de

  • 7/31/2019 Transparencias de Algortmica

    120/250

    inserciones y eliminaciones ser .Se puede implementar un heapmediante memoria dinmica,con apuntadores al hijo izquierdo y derecho y tambin al padreen cada nodoPero es mucho ms fcil y eficiente implementar los heaps

    mediante un vector. No se desperdicia demasiado espacio yaque el heapes quasi-completo; en caso necesario puedeusarse el redimensionado

  • 7/31/2019 Transparencias de Algortmica

    121/250

    Las reglas anteriores implican que los elementos del heap seubican en posiciones consecutivas del vector, colocando la razen la primera posicin y recorriendo el rbol por niveles, de

  • 7/31/2019 Transparencias de Algortmica

    122/250

    izquierda a derecha.template

    class ColaPrioridad {

    public:

    ...

    private:

    // la componente 0 no se usa; el constructor de la clase

    // inserta un elemento ficticiovector h;

    int nelems;

    void flotar(int j) throw();

    void hundir(int j) throw();

    };

    template

    bool ColaPrioridad::vacia() const throw() {

    return nelems == 0;

  • 7/31/2019 Transparencias de Algortmica

    123/250

    }

    template

    Elem ColaPrioridad::min() const throw(error) {

    if (nelems == 0) throw error(ColaVacia);

    return h[1].first;

    }

    template

    Prio ColaPrioridad::prio_min() const throw(error) {

    if (nelems == 0) throw error(ColaVacia);

    return h[1].second;

    }

    template

    void ColaPrioridad::inserta(cons Elem& x,

    i ) th ( ) {

  • 7/31/2019 Transparencias de Algortmica

    124/250

    cons Prio& p) throw(error) {++nelems;

    h.push_back(make_pair(x, p));

    flotar(nelems);

    }

    template

    void ColaPrioridad::elim_min() const throw(error) {

    if (nelems == 0) throw error(ColaVacia);

    swap(h[1], h[nelems]);

    --nelems;

    hundir(1);

    }

    // Versin recursiva.

    // Hunde el elemento en la posicin j del heap

    // hasta reestablecer el orden del heap; por

    // hiptesis los subrboles del nodo j son heaps.

    // Coste: O(log(n/j))

    template

  • 7/31/2019 Transparencias de Algortmica

    125/250

    template void ColaPrioridad::hundir(int j) throw() {

    // si j no tiene hijo izquierdo, hemos terminado

    if (2 * j > nelems) return;

    int minhijo = 2 * j;

    if (minhijo < nelems &&

    h[minhijo].second > h[minhijo + 1].second)

    ++minhijo;

    // minhijo apunta al hijo de minima prioridad de j

    // si la prioridad de j es mayor que la de su menor hijo

    // intercambiar y seguir hundiendo

    if (h[j].second > h[minhijo].second) {

    swap(h[j], h[minhijo]);

    hundir(minhijo);

    }

    }

    // Versin iterativa.

    // Hunde el elemento en la posicin j del heap

    // hasta reestablecer el orden del heap; por

    // hiptesis los subrboles del nodo j son heaps.

    // Coste: O(log(n/j))

  • 7/31/2019 Transparencias de Algortmica

    126/250

    // Coste: O(log(n/j))template

    void ColaPrioridad::hundir(int j) throw() {

    bool fin = false;

    while (2 * j h[minhijo + 1].second)

    ++minhijo;if (h[j].second > h[minhijo].second) {

    swap(h[j], h[minhijo]);

    j = minhijo;

    } else {

    fin = true;

    }

    }

    }

    // Flota al nodo j hasta reestablecer el orden del heap;

    // todos los nodos excepto el j satisfacen la propiedad

    // de heap

    // Coste: O(log j)

  • 7/31/2019 Transparencias de Algortmica

    127/250

    // Coste: O(log j)

    template

    void ColaPrioridad::flotar(int j) throw() {

    // si j es la raz, hemos terminado

    if (j == 1) return;

    int padre = j / 2;

    // si el padre tiene mayor prioridad

    // que j, intercambiar y seguir flotandoif (h[j].second < h[padre].second) {

    swap(h[j], h[padre]);

    flotar(padre);

    }

    }

    Heapsort

    Heapsort (Williams, 1964) ordena un vector de elementos

    d heap l l d l

  • 7/31/2019 Transparencias de Algortmica

    128/250

    construyendo un heapcon los elementos y extrayndolos,uno a uno del heapa continuacin. El propio vector quealmacena a los elementos se emplea para construir el heap,de modo que heapsort acta in-situy slo requiere un espacio

    auxiliar de memoria constante. El coste de este algoritmo es(incluso en caso mejor) si todos los elementos sondiferentes.En la prctica su coste es superior al de quicksort, ya que elfactor constante multiplicativo del trmino es mayor.

    // Ordena el vector v[1..n]

    // (v[0] no se usa)

    // de Elems de menor a mayor

    t l t t l

  • 7/31/2019 Transparencias de Algortmica

    129/250

    template

    void heapsort(Elem v[], int n) {

    crea_max_heap(v, n);

    for (int i = n ; i > 0 ; - - i ) {

    // saca el mayor elemento del heap

    swap(v[1], v[i]);

    // hunde el elemento de indice 1// para reestablecer un max-heap en

    // el subvector v[1..i-1]

    hundir(v, i-1, 1);

    }

    }

  • 7/31/2019 Transparencias de Algortmica

    130/250

  • 7/31/2019 Transparencias de Algortmica

    131/250

  • 7/31/2019 Transparencias de Algortmica

    132/250

  • 7/31/2019 Transparencias de Algortmica

    133/250

  • 7/31/2019 Transparencias de Algortmica

    134/250

    Sea el coste en caso peor de heapsort y el costede crear el heap inicial. El coste en caso peor dehundir es y por lo tanto

  • 7/31/2019 Transparencias de Algortmica

    135/250

    Un anlisis simple de indica que yaque hay llamadas a hundir, cada una de las cuales

    tiene costePor tanto , de hecho encaso peor

    Podemos refinar el anlisis de :

  • 7/31/2019 Transparencias de Algortmica

    136/250

    Puesto que , podemos afirmar que .

    Demostracin alternativa: Sea la altura delheap En el nivel hay como mucho

  • 7/31/2019 Transparencias de Algortmica

    137/250

    heap. En el nivel hay como mucho

    nodos y cada uno de ellos habr de hundirse en caso peorhasta el nivel ; eso tiene coste

    Por lo tanto,

  • 7/31/2019 Transparencias de Algortmica

    138/250

    ya que

    En general, si ,

    Aunque , el anlisis detallado de es

    importante: utilizando un min-heappodemos hallar losmenores elementos en orden creciente de un vector (y en

  • 7/31/2019 Transparencias de Algortmica

    139/250

    importante: utilizando un p podemos hallar losmenores elementos en orden creciente de un vector (y enparticular el -simo) con coste:

    y si entonces .

  • 7/31/2019 Transparencias de Algortmica

    140/250

    1 Repaso de Conceptos Algortmicos

    2 Algoritmos VoracesCaminos Mnimos: Algoritmo de Dijkstra

    rboles de Expansin Mnimos: Algoritmos de Kruskal y

  • 7/31/2019 Transparencias de Algortmica

    141/250

    rboles de Expansin Mnimos: Algoritmos de Kruskal yde PrimParticiones

    3 Programacin Dinmica

    4 Flujos sobre Redes y Programacin Lineal

    5 Algoritmos Probabilsticos

    6 Estructuras de Datos Avanzadas

    Algoritmo de DijkstraDado un grafo dirigido etiquetado, el algoritmo deDijkstra (1959) nos permite hallar los caminos mnimos desdeun vrtice dado a todos los restantes vrtices del grafo.

    Si el grafo contuviera ciclos de peso negativo la nocin de

  • 7/31/2019 Transparencias de Algortmica

    142/250

    Si el grafo contuviera ciclos de peso negativo la nocin decamino mnimo no estara bien definida para todo par devrtices, pero el algoritmo de Dijkstra puede fallar en presenciade arcos con peso negativo, incluso si no hay ciclos de peso

    negativo. Supondremos por lo tanto que todos los pesosR son positivos.Sea el conjunto de caminos entre dos vrtices y de

    . Dado un camino su peso es la sumade los pesos de los arcos que lo forman:

    Sea y un caminode cuyo peso es mnimo. Si entonces

  • 7/31/2019 Transparencias de Algortmica

    143/250

    y ptomamos , por convenio. Consideraremos enprimer lugar la versin del algoritmo de Dijkstra que calcula lospesos de los caminos mnimos desde un vrtice a todos los

    restantes, y ms tarde la versin que calcula adicionalmentelos caminos propiamente dichos.

    es un grafo dirigido con pesos positivos

    DIJKSTRA

  • 7/31/2019 Transparencias de Algortmica

    144/250

    Para todo ,

    es un grafo dirigido con pesos positivos

    DIJKSTRA

    Para todo ,Para todo ,

    El algoritmo de Dijkstra acta en una serie de etapas. En todomomento el conjunto de vrtices se divide en dos partes: los

    vrtices vistosy los vrtices no vistoso candidatos. Al inicio ded i i i i

  • 7/31/2019 Transparencias de Algortmica

    145/250

    ycada etapa, si es un vrtice visto entonces ; si

    es un candidato entonces es el peso del camino mnimoentre y que pasa exclusivamente por vrtices intermediosvistos. Este es el invariante del algoritmo de Dijkstra.En cada etapa un vrtice pasa de ser candidato a ser visto. Ycuando todos los vrtices son vistos entonces tenemoscompletamente resuelto el problema.

    Qu vrtice candidato debe seleccionarse en cada etapapara pasar a ser visto? Intuitivamente, aqul cuya seamnima de entre todos los candidatos. Sea dicho vrtice.Entonces no slo es el peso del camino mnimo entre y

    que slo pasa por vistos (segn el invariante), sino el peso

    del camino mnimo. En efecto, si el camino mnimo pasase porl t ti i t t d l d di h

  • 7/31/2019 Transparencias de Algortmica

    146/250

    p palgn otro vrtice no visto , tendramos que el peso de dichocamino es , pero como y

    es mnimo llegamos a una contradiccin.

    Ahora debemos pensar cmo mantener el resto del invariante.Para los vrtices vistos ya tiene el valor adecuado (includo

    , el vrtice que pasa de candidatos a vistos, como acabamosde ver). Pero si es un candidato, tal vez haya de cambiar

    ya que tenemos un vrtice adicional visto, el vrtice . Unsencillo razonamiento demuestra que si el camino mnimo

  • 7/31/2019 Transparencias de Algortmica

    147/250

    sencillo razonamiento demuestra que si el camino mnimoentre y que pasa por vrtices vistos incluye a entonceses el inmediato antecesor de en dicho camino.

    De ah se sigue que el valor de slo puede cambiar para losvrtices sucesores de . Esto ocurrir si y slo si

    Si fuera sucesor de pero ya estuviera visto la condicin

  • 7/31/2019 Transparencias de Algortmica

    148/250

    Si fuera sucesor de pero ya estuviera visto la condicinanterior no puede ser cierta.

    procedure DIJKSTRA( , , )es el resultado; para todo

    es un subconjunto de vrtices defor do

    end for

  • 7/31/2019 Transparencias de Algortmica

    149/250

    while doel vrtice de con mnima

    for SUCESORES doPESO

    if then

    end if

    end forend while

    end procedure

    CANDIDATOS

  • 7/31/2019 Transparencias de Algortmica

    150/250

    Para conseguir que el algoritmo compute los caminos mnimospropiamente dichos, empezamos observando que si el caminomnimo entre y pasa por entonces la parte de ese camino

    que nos lleva de a ha de ser necesariamente el caminomnimo entre y . Por lo tanto, bastar con computar un rbol

  • 7/31/2019 Transparencias de Algortmica

    151/250

    mnimo entre y . Por lo tanto, bastar con computar un rbolde caminos mnimosque implcitamente se representamediante una tabla tal que:

    si ,si es el ltimo arco de ,

    si ,

    donde indica que no est definido.

    Claramente, los nicos cambios que sern necesarios son:1 inicializar2 incluir la actualizacin de en el bucle interno

    . . .for SUCESORES do

    PESOif th

  • 7/31/2019 Transparencias de Algortmica

    152/250

    if then

    end if

    end for. . .

    Si queremos el camino completo de a podemos deshacer elrecorrido a la inversa:

    hasta que lleguemos a .

    Sea el nmero de vrtices de y el nmero de arcos. Siel grafo se implementa mediante matriz de adyacencias, elcoste del algoritmo de Dijkstra es ya que se haceni i d l b l i i l d d d d ll

  • 7/31/2019 Transparencias de Algortmica

    153/250

    iteraciones del bucle principal y dentro de cada una de ellas seincurrira en un coste como mnimo para recorrer lossucesores del vrtice seleccionado. Descartaremos esta

    posibilidad, y supondremos que el grafo se implementamediante listas de adyacencia que nos darn mejoresresultados tanto en tiempo como en espacio.

  • 7/31/2019 Transparencias de Algortmica

    154/250

    Si es un conjunto arbitrario, podemos conseguir el mismo

    rendimiento utilizando tablas de hash para implementar y. Y el problema sigue siendo la ineficiencia en la seleccindel vrtice con mnima.Para mejorar la eficiencia podemos convertir en una colade prioridad cuyos elementos son vrtices y donde la prioridad

    de cada vrtice es su correspondiente valor dees una cola de prioridad de mnimos cuyos

  • 7/31/2019 Transparencias de Algortmica

    155/250

    es una cola de prioridad de mnimos, cuyoselementos son vrtices de y la prioridad de unelemento es

    . . . para todo ;for do

    INSERTAend for

    while ES_VACIA doMIN ELIM_MIN

    for SUCESORES do. . .

    El problema es que dentro del bucle que recorre los sucesoresde se puede modificar el valor de (la prioridad) de vrticescandidatos. Por ello deberemos dotar a la cola de prioridad deuna operacin adicional que, dado un elemento, nos permita

    decrementar su prioridad (los valores de se modificansiempre a la baja).

  • 7/31/2019 Transparencias de Algortmica

    156/250

    p j ). . .for SUCESORES do

    PESOif then

    DECR_PRIOend if

    end for. . .

    Si los costes de las operaciones sobre la cola de prioridad sonentonces el coste del bucle principal es

    # sucesores de

    # sucesores de

  • 7/31/2019 Transparencias de Algortmica

    157/250

    Por otra parte, el coste de las inicializaciones previas es

    .Por lo tanto el coste que nos queda es . Puededemostrarse que, de hecho, el coste en caso peor delalgoritmo de Dijkstra es . Pero en muchoscasos el coste es menor, porque no hay que usar decr_priopara todos los sucesores del vrtice seleccionado y/o porque elcoste de las operaciones sobre la cola de prioridad esfrecuentemente menor que .

    Al crear sabemos cuntos vrtices tiene el grafo ypodemos crear dinmicamente una estructura de datos paraese tamao. Adicionalmente podemos evitar la redundancia dela tabla , ya que para cada elemento de tenemos su

    prioridad, que es su valor de . Necesitamos por lo tanto unaclase con la funcionalidad combinada tpica de las colas de

  • 7/31/2019 Transparencias de Algortmica

    158/250

    pprioridad y de los diccionarios:template

    class ColaPrioDijkstra {

    public:

    ColaPrioDijkstra(int n = 0 ) ;void inserta(const Elem& e, const Prio& prio);

    Elem min() const;

    void elim_min();

    Prio prio(const Elem& e) const;

    bool contiene(const Elem& e) const;

    void decr_prio(const Elem& e, const Prio& nuevaprio);

    bool es_vacia() const;

    ...

    };

    typedef vector grafo;

    typedef list::const_iterator arco;

    ...

    void Dijkstra(const grafo& G, int s, ... ) {

    ColaPrioDijkstra cand(G.size());

    for (int v = 0; v < G.size(); ++v)

    cand.inserta(v, INFINITY);

    cand.decr_prio(s, 0);

  • 7/31/2019 Transparencias de Algortmica

    159/250

    while(not cand.es_vacia()) {

    int u = cand.min(); double du = cand.prio(u);

    cand.elim_min();

    for (arco e = G[u].begin(); e != G[u].end(); ++e) {

    // e apunta al par

    // e -> first() == v

    // e -> second() == peso(u,v)

    int v = e -> first();

    if (cand.contiene(v)) {

    double d = du + e -> second();

    if (d < cand.prio(v))

    cand.decr_prio(v, d);

    }

    }

    }

    }

    Pueden conseguirse costes logartmicos o inferiores en todaslas operaciones sobre la cola de prioridad utilizando un heapimplementado en vector.

    Adems necesitaremos una tabla de hash que nos permitatraducir vrtices a ndices. Y una tabla de ndices y otra de

  • 7/31/2019 Transparencias de Algortmica

    160/250

    posiciones en el heap.template

    class ColaPrioDijkstra {

    ...

    private:vector prio;

    vector elems;

    int nelems; // == elems.size()

    vector index;

    vector pos;

    hash_map identif;

    Los vectores y , junto al contadorrepresentan al heap. Si entonces y

  • 7/31/2019 Transparencias de Algortmica

    161/250

    , es decir, nos da la posicin en el heapdelelemento e el identificador del elemento en la posicin

    del heap, siendo .

    La constructora de la clase crea las tablas , , ycon componentes y el map.Cada vez que se inserta un nuevo elemento se le asigna elndice , se inserta en , se coloca en el heap

    en la posicin , y se le hace flotar. La operacinflotar se encarga de mantener actualizadas las tablas e

  • 7/31/2019 Transparencias de Algortmica

    162/250

    g. Para elim_min, se intercambia el ltimo nodo del heap

    con la raz// intercambiamos el ultimo elemento del heap con la raz

    swap(prio[1],prio[nelems]);

    swap(elems[1], elems[nelems]);

    // actualizamos pos e index

    swap(pos[index[1]], pos[index[nelems]]);

    swap(index[1],index[nelems]);

    y a continuacin se hunde la raz, cuidando de mantener

    tambin actualizadas las tablas e .

    La operacin decr_prio requiere averiguar el identificadordel elemento cuya prioridad se va a decrementar usando latabla de hash, usar la tabla para obtener la posicin delnodo que le corresponde en el heap, y una vez modificada la

  • 7/31/2019 Transparencias de Algortmica

    163/250

    nodo que le corresponde en el heap, y una vez modificada laprioridad, flotar el nodo.Es fcil comprobar que las operaciones de la clase,

    exceptuando la constructora, tienen coste (es_vacia,min, prio, contiene) o (inserta, elim_min,decr_prio).

    1 Repaso de Conceptos Algortmicos

    2 Algoritmos VoracesCaminos Mnimos: Algoritmo de Dijkstra

    rboles de Expansin Mnimos: Algoritmos de Kruskal yde Prim

  • 7/31/2019 Transparencias de Algortmica

    164/250

    Particiones

    3 Programacin Dinmica

    4 Flujos sobre Redes y Programacin Lineal

    5 Algoritmos Probabilsticos

    6 Estructuras de Datos Avanzadas

    rboles de Expansin Mnimos

    Dado un grafo no dirigido y conexo con pesos o

    costes en las aristas R, un rbol de expansin mnimo(MST: minimum spanning tree) es un subgrafo de

  • 7/31/2019 Transparencias de Algortmica

    165/250

    tal que tiene el mismo conjunto de vrtices ( ), esun rbol (es decir, es conexo y acclico) y su coste

    es mnimo entre todos los posibles rboles de expansin de .

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    166/250

    2

    3

    4

    6

    108

    9

    9

    5 3

    7289

  • 7/31/2019 Transparencias de Algortmica

    167/250

    2

    3

    4

    6

    108

    9

    9

    Existen multitud de algoritmos para calcular un MST de ungrafo. No obstante todos ellos siguen un esquema voraz:

    ; Candidataswhile do

  • 7/31/2019 Transparencias de Algortmica

    168/250

    while doSeleccionar una arista Candidatasque

    no crea un ciclo en

    Candidatas Candidatasend while

    Diremos que un conjunto de aristas es prometedorsi y slo si:

  • 7/31/2019 Transparencias de Algortmica

    169/250

    1 no contiene ciclos2 es un subconjunto de las aristas de un MST del grafo

    Un corte del grafo es una particin de su conjunto de

    vrtices en dos subconjuntos y no vacos y disjuntos:

  • 7/31/2019 Transparencias de Algortmica

    170/250

    Una arista respeta un corte si sus dos extremos estn

    ambos en o ambos en , en caso contrario se dice quecruza el corte.

    Teorema

    Sea un conjunto prometedor de aristas que respetan uncierto corte del grafo . Sea la arista de

    mnimo peso que cruza el corte Entonces

  • 7/31/2019 Transparencias de Algortmica

    171/250

    mnimo peso que cruza el corte . Entonces

    es prometedor

    El teorema anterior nos da la receta para disear algoritmos

    de clculo de un MST: una vez que hayamos definido cul es elcorte que corresponde a cada iteracin, la seleccin de laarista consistir en localizar la arista de mnimo peso que

  • 7/31/2019 Transparencias de Algortmica

    172/250

    arista consistir en localizar la arista de mnimo peso quecruza el corte. Por definicin, como respeta el corte y locruza, no puede crear un ciclo en .

    Ms an: la correccin de los algoritmos que se fundamentanen esta idea queda automticamente establecida.

    Demostracin:Sea el conjunto de aristas de un MST tal que .

    Puesto que respeta el corte, al menos una arista de las quecruzan el corte tendr que pertenecer a , en caso contrario

  • 7/31/2019 Transparencias de Algortmica

    173/250

    no sera conexo. Supongamos que una de dichas aristas es. Si es la arista de mnimo peso que cruza el corte, como

    es prometedor, hemos demostrado el teorema. Peroque ocurre si no es la arista de mnimo peso que cruza elcorte?

    Demostracin (cont.):El coste del MST incluir el coste de las aristas de , elcoste y el coste de otras aristas. Si agregsemos a laarista de mnimo peso que cruza el corte, crearamos un

    ciclo, porque es un rbol. Sea la arista de que cruza elcorte forma parte de dicho ciclo. De manera que

  • 7/31/2019 Transparencias de Algortmica

    174/250

    tambin es un rbol de expansin. Y su coste es menor o igualque el de puesto que slo cambiamos el coste de por elde , que es el mnimo. Como es MST, llegamos a unacontradiccin a menos que y tengan el mismo coste, y portanto y tendran el mismo coste. El teorema queda

    demostrado, ya que es un subconjunto de las aristasde , que es un MST.

    C C

    e

    T

  • 7/31/2019 Transparencias de Algortmica

    175/250

    e

    podemos sustituir e por e para obtener un nuevo MST

    Algoritmo de Prim

    En el algoritmo de Prim, se mantiene un conjunto de vrtices

    Vistos , y en cada etapa del algoritmo se selecciona laarista de mnimo peso que une a un vrtice de Vistoscon unvrtice no visto (i e en Vistos)

  • 7/31/2019 Transparencias de Algortmica

    176/250

    vrtice no visto (i.e., en Vistos).Dicha arista no puede crear un ciclo y se aade al conjunto .Asimismo el vrtice pasa a ser de Vistos.La correccin del algoritmo es inmediata; el conjunto respetael corte Vistos Vistos y seleccionamos la arista demnimo peso que cruza el corte para agregarla a .

    procedure PRIM( ); Vistos

    Candidatasfor ADYACENTES do

    Candidatas Candidatasend for

    while doSeleccionar la arista

    de Candidatas de mnimo peso

  • 7/31/2019 Transparencias de Algortmica

    177/250

    de Candidatasde mnimo peso

    Sea el vrtice en Vistos:

    Vistos Vistosfor ADYACENTES do

    if VistosthenCandidatas Candidatas

    end ifend for

    end whilereturn

    end procedure

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    178/250

    3

    4

    6

    108

    9

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    179/250

    3

    4

    6

    108

    9

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    180/250

    3

    4

    6

    108

    9

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    181/250

    3

    4

    6

    108

    9

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    182/250

    3

    4

    6

    108

    9

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    183/250

    3

    4

    6

    108

    9

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    184/250

    3

    4

    6

    108

    9

    El coste del algoritmo de Prim depender de cmoimplementemos la seleccin de la arista candidata. El bucle

    principal hace iteraciones, pues en cada iteracinaadimos una arista al rbol , o equivalentemente, en cadaiteracin vemosun vrtice nuevo y terminaremos cuando todos

    i

  • 7/31/2019 Transparencias de Algortmica

    185/250

    estn vistos.En el interior del bucle principal se hacen dos tareas

    costosas: seleccionar la arista de mnimo peso en Candidatasy aadir ciertas aristas adyacentes al vrtice recin visto alconjunto de Candidatas.

    El coste de la segunda tarea es proporcional al grado delvrtice y en total aportar al coste

    grado grado

  • 7/31/2019 Transparencias de Algortmica

    186/250

    Pero si usamos una implementacin ingenua para el conjunto

    de Candidatas, el coste de seleccionar una arista es y elcoste total del algoritmo de Prim es .

    Para conseguir mejorar sensiblemente el coste del algoritmo elconjunto de Candidatasdebe implementarse como unmin-heap, siendo la prioridad de cada arista su coste.Entonces la seleccin (y eliminacin) de la arista de coste

    mnimo en cada iteracin pasa a ser .Por otro lado, el coste de ir aadiendo aristas a Candidatas lotenemos que recalcular:

  • 7/31/2019 Transparencias de Algortmica

    187/250

    tenemos que recalcular:

    grado grado

    En total:

    Algoritmo de Kruskal

    En el algoritmo de Kruskal se mantiene en todo momento un

    conjunto de aristas que es un bosque (un conjunto derboles). En cada paso se toma una arista de mnimo pesoentre todas las posibles; si dicha arista cierra un ciclo sedescarta si no cierra un ciclo se agrega a

  • 7/31/2019 Transparencias de Algortmica

    188/250

    descarta, si no cierra un ciclo, se agrega a .Cuando la arista escogida no cierra un ciclo, se

    define como corte el que forman los vrtices en la mismacomponente conexa de (mediante aristas de ) por un lado, ylos restantes vrtices del grafo por otro. Claramente respetael corte y es la arista de mnimo peso que respeta ese corte.

    procedure KRUSKAL( )Ordenar por peso creciente

    while doSIGUIENTE

    if no cierra un ciclo en then

  • 7/31/2019 Transparencias de Algortmica

    189/250

    end if

    end whilereturn

    end procedure

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    190/250

    3

    4

    6

    108

    4

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    191/250

    3

    4

    6

    108

    4

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    192/250

    3

    4

    6

    108

    4

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    193/250

    3

    4

    6

    108

    4

  • 7/31/2019 Transparencias de Algortmica

    194/250

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    195/250

    3

    4

    6

    108

    4

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    196/250

    3

    4

    6

    108

    4

  • 7/31/2019 Transparencias de Algortmica

    197/250

    5

    2

    3

    7

    2

    89

  • 7/31/2019 Transparencias de Algortmica

    198/250

    3

    4

    6

    108

    4

    Para determinar si una cierta arista cierra un ciclo en demanera eficiente usaremos una estructura de datos astutadenominada PARTICION (tambin se les conoce como MFSETSy UNION-FIND).Inicialmente creamos una PARTICION en la que cada vrticedel grafo constituye un bloque por s solo. Cada vez queagreguemos una arista al conjunto , los bloques a

  • 7/31/2019 Transparencias de Algortmica

    199/250

    los que pertenecen y se fusionan en un solo bloque

    (merge, union).Cada bloque de vrtices es pues una componente conexa de; si existe un camino entre los vrtices y usando las

    aristas de , y pertenecern a un mismo bloque de laPARTICIN.

    El test que determina si un nueva arista cierra un cicloentonces consiste simplemente en ver si los vrtices ypertenecen a un mismo bloque de la PARTICIN o no. Si ya

    estn conectado, la nueva arista cerrar un ciclo; en casocontrario, la nueva arista no cierra un ciclo y los vrtices pasana estar conectados.H bit l t l l PARTICIN i i

  • 7/31/2019 Transparencias de Algortmica

    200/250

    Habitualmente la clase PARTICIN proporciona una operacinFIND que dado un elemento nos devuelve el representantedel bloque en el que est . Dos elementos estarn en elmismo bloque si y slo si los representantes de sus bloquesson idnticos.

    procedure KRUSKAL( )Ordenar por peso creciente

    Se crea una particin inicial, cada vrtice en un bloquedistinto

    MAKE_UNIONFIND

    while doSIGUIENTE

  • 7/31/2019 Transparencias de Algortmica

    201/250

    if FIND FIND then

    UNIONend if

    end whilereturn

    end procedure

    Para calcular el coste del algoritmo de Kruskal tenemos por un

    lado el coste de la ordenacin de las aristas, siendo . La creacin de

    la particin inicial tiene coste , siendo . Por otrolado, el bucle siguiente hace al menos iteraciones (tantascomo aristas tiene el MST hallado) pero puede llegar a haceriteraciones en caso peor. El coste del cuerpo del bucle vendrdominado por el coste de las llamadas a las operaciones F INDy UNION. Si el bucle principal realiza iteraciones,

  • 7/31/2019 Transparencias de Algortmica

    202/250

    , se harn llamadas a FIND. Por otro lado,

    se hacen siempre exactamente llamadas a UNION.Es muy fcil obtener implementaciones del UNION-FIND quegaranticen que el coste de F IND y UNION es , lo quenos llevara a un coste

    para el algoritmo.

    Se puede mejorar el rendimiento notablemente (aunque no en

    caso peor) de la siguiente forma:1 En vez de ordenar las aristas por peso, se crea unmin-heap con coste

    2 Se usa una versin de UNION-FIND que garantiza queFINDs + UNIONs tienen coste

    . La funcin , llamada funcininversa de Ackermann crece de manera extremadamentelenta, a los efectos prcticos, por muy grandes que sean

  • 7/31/2019 Transparencias de Algortmica

    203/250

    y , .

    3 El bucle principal seguir teniendo coste peroen la mayora de casos ser ms cercano aporque no se suelen hacer mucho ms del mnimo de

    iteraciones.

    El coste del algoritmo vendr dominado por el coste de extraeraristas durante las iteraciones del bucle principal y en casopeor es ; en promedio ser cercano a , locual es muy ventajoso, sobre todo si .

    1 Repaso de Conceptos Algortmicos

    2 Algoritmos VoracesCaminos Mnimos: Algoritmo de Dijkstrarboles de Expansin Mnimos: Algoritmos de Kruskal yde PrimParticiones

  • 7/31/2019 Transparencias de Algortmica

    204/250

    3 Programacin Dinmica

    4 Flujos sobre Redes y Programacin Lineal

    5 Algoritmos Probabilsticos

    6 Estructuras de Datos Avanzadas

    Particiones

    Una particin de un conjunto no vaco es una coleccin desubconjuntos no vacos tal que

    1 Si entonces .

  • 7/31/2019 Transparencias de Algortmica

    205/250

    2 .

    Se suele denominar bloquede la particin a cada uno de loss. Las particiones y las relaciones de equivalencia estn

    estrechamente ligadas. Recordemos que es una relacin deequivalencia en si y slo si

    1 es reflexiva: para todo , .2 es transitiva: si y , entonces , para

  • 7/31/2019 Transparencias de Algortmica

    206/250

    y , , pcualesquiera , y en .

    3 es simtrica: si y slo si , para cualesquieray en .

    Dada una particin de , sta induce una relacin deequivalencia definida por

    e pertenecen a un mismo bloque

    Y a la inversa, dada una relacin de equivalencia en , stainduce una particin donde

  • 7/31/2019 Transparencias de Algortmica

    207/250

    induce una particin , donde

    Al subconjunto de elementos equivalentes a se le denominaclase de equivalenciade . Cada uno de los bloques de la

    particin inducida por una relacin es por lo tanto una clasede equivalencia. Ntese que si entonces . Unelemento cualquiera de la clase se denomina representantede la clase.

  • 7/31/2019 Transparencias de Algortmica

    208/250

    En muchos algoritmos, especialmente en algoritmos sobre

    grafos, es importante poder representar particiones de unconjunto finito de manera eficiente.

    Vamos a suponer que el conjunto soportesobre el que sedefine la particin es ; sin excesiva dificultad,empleando alguna de las tcnicas vistas en temas precedentes

    podemos representar de manera eficiente una biyeccin entreun conjunto finito de cardinalidad y el conjunto ycon ello una particin sobre el conjunto soporte en casonecesario.

  • 7/31/2019 Transparencias de Algortmica

    209/250

    Adicionalmente, supondremos que el conjunto soporte es

    esttico, es decir, ni se aaden ni se eliminan elementos. Noobstante, con poca dificultad extra podemos obtenerrepresentaciones eficientes para particiones de conjuntosdinmicos.

    Generalmente el tipo de operaciones que una claseParticion debe soportar son las siguientes: 1) dados doselementos y , determinar si pertenecen al mismo bloque o

    no; 2) dados dos elementos y fusionar los bloques a los quepertenecen (si procede) en un slo bloque, devolviendo laparticin resultante.Frecuentemente el primer tipo de operacin se realiza

  • 7/31/2019 Transparencias de Algortmica

    210/250

    p p pmediante una operacin FIND que dado un elemento ,

    devuelve un representante de la clase a la que pertenece . Sidos elementos y tienen el mismo representante, entonceshan de estar en el mismo bloque.

    El segundo tipo de operacin se llama MERGE o UNION. De ahque las particiones se les llame a menudo estructurasunion-find o mfsets (abreviacin de merge-find sets).La operacin MAKE crea una particin de consistenteen bloques cada uno de los cuales contiene un elemento

  • 7/31/2019 Transparencias de Algortmica

    211/250

    en bloques cada uno de los cuales contiene un elemento.

    En muchas aplicaciones antes de hacer cualquier UNION se

    habr determinado previamente si los elementos y cuyosbloques habran de unirse, estn o no en el mismo bloque;para ello se habr preguntado si FIND FIND o no.Por esta razn es habitual que en una clase Particion laoperacin UNION slo acte sobre elementos que son

  • 7/31/2019 Transparencias de Algortmica

    212/250

    operacin UNION slo acte sobre elementos que son

    representantes de sus respectivas clases.

    procedure ( ). . .

    FINDFIND

    if thenUNION

  • 7/31/2019 Transparencias de Algortmica

    213/250

    . . .

    end ifend procedure

    Puesto que la operacin MAKE recibe como parmetro elnmero de elementos del conjunto soporte, podremos utilizarimplementaciones en vector, reclamando un vector con elnmero apropiado de componentes a la memoria dinmica si

    nuestro lenguaje de programacin lo soporta. Tambin serposible utilizar este tipo de implementacin si el valor de estacotado y dicha cota no es irrazonablemente grande. Encualquier caso podremos modificar sin demasiado esfuerzo las

  • 7/31/2019 Transparencias de Algortmica

    214/250

    q pimplementaciones que se vern a continuacin para que seancompletamente dinmicas y funcionen correctamente enaquellos casos en que no se puedan crear vectores cuyotamao se fija en tiempo de ejecucin o si el conjunto soporteha de soportar inserciones y borrados.

    Quick-find consiste representar la particin mediante un vectory almacenar en la componente de el representante de la

    clase a la que pertenece . De este modo la operacin FINDtiene coste constante, ya q