Articulo de referencia

Cola de prioridad

En informática , una cola de prioridad es un tipo de dato abstracto similar a una cola regular donde cada elemento tiene una prioridad asociada que determina su orden de servici...

En informática , una cola de prioridad es un tipo de dato abstracto similar a una cola regular donde cada elemento tiene una prioridad asociada que determina su orden de servicio. [ 1 ] La cola de prioridad sirve primero los elementos de mayor prioridad. [ 1 ] Los valores de prioridad deben ser instancias de un tipo de dato ordenado, y se puede dar mayor prioridad tanto al valor menor como al mayor con respecto a la relación de orden dada. Por ejemplo, en la biblioteca estándar de Java , la clase PriorityQueue considera que el elemento más bajo con respecto a su orden tiene la mayor prioridad. [ 2 ]

Si bien las colas de prioridad a menudo se implementan usando montículos , son conceptualmente distintas. Una cola de prioridad puede implementarse con un montículo o con otros métodos; al igual que una lista puede implementarse con una lista enlazada o con un arreglo .

Operaciones

Una cola de prioridad tiene las siguientes operaciones: [ 3 ] [ 4 ] [ 5 ]

Cola de máxima prioridad

  • insert(S, element, priority): [ 4 ] [ 5 ] agregar un elemento al conjunto Scon una prioridad asociada.
  • maximum(S): devuelve el elemento con la prioridad más alta .
    Esto también se conoce como " find_max".
  • extract_max(S): elimina el elemento del conjunto Scon la prioridad más alta y devuélvelo.
    Esto también se conoce como " delete", [ 4 ] o " extract". [ 5 ]
  • increase_key(S, element, k): aumenta la prioridad asociada a un elemento al nuevo valor k.

Cola de prioridad mínima

  • insert(S, element, priority): [ 4 ] [ 5 ] agregar un elemento al conjunto Scon una prioridad asociada.
  • minimum(S): devuelve el elemento con la prioridad más baja .
    Esto también se conoce como " find_min".
  • extract_min(S): elimina el elemento del conjunto Scon la prioridad más baja y devuélvelo.
    Esto también se conoce como " delete", [ 4 ] o " extract". [ 5 ]
  • decrease_key(S, element, k): disminuir la prioridad asociada a un elemento al nuevo valor k.

Las pilas y las colas pueden implementarse como tipos específicos de colas de prioridad, donde la prioridad está determinada por el orden en que se insertan los elementos. En una pila, la prioridad de cada elemento insertado aumenta monótonamente; por lo tanto, el último elemento insertado siempre es el primero en recuperarse. En una cola, la prioridad de cada elemento insertado disminuye monótonamente; por lo tanto, el primer elemento insertado siempre es el primero en recuperarse.

En algunas implementaciones, si dos elementos tienen la misma prioridad, se atienden en el mismo orden en que se añadieron a la cola. En otras implementaciones, el orden de los elementos con la misma prioridad no está definido.

Implementación

Implementaciones ingenuas

Se puede crear una cola de prioridad simple, aunque ineficiente, de varias maneras. Estas implementaciones sencillas permiten demostrar el comportamiento esperado de una cola de prioridad de forma más simple.

  • insertar elementos en un array no ordenado; encontrar y extraer el elemento con mayor prioridad.
    Rendimiento: " insert" actúa enO(1){\displaystyle O(1)}tiempo constante, donde " extract_max" se desempeña enO(norte){\displaystyle O(n)}tiempo lineal.
insertar (elemento, prioridad): nodo.elemento ← elemento nodo.prioridad ← prioridad lista.añadir(nodo) extraer_máximo (): más alto ← 0 para cada nodo en la lista: Si highest.priority < node.priority: más alto ← nodo lista.eliminar(más alto) devolver elemento más alto
  • insertar elementos en un array ordenado; extraer el primer elemento
    Rendimiento: " insert" actúa enO(norte){\displaystyle O(n)}tiempo lineal, donde " extract_max" se desempeña enO(1){\displaystyle O(1)}tiempo constante.
insertar (elemento, prioridad): nodo.elemento ← elemento nodo.prioridad ← prioridad para i en [0...N]: elemento ← lista.get_at_index(i) Si element.priority < node.priority: lista.insertar_en_índice(nodo, i + 1) devolver extraer_máximo (): más alto ← lista.get_at_index(0) lista.eliminar(más alto) devolver elemento más alto

Implementación habitual

Para mejorar el rendimiento, las colas de prioridad se basan normalmente en un montón , lo que daO(registronorte){\displaystyle O(\log n)}rendimiento para inserciones y extracciones, yO(norte){\displaystyle O(n)}construir el montón inicialmente a partir de un conjunto denorte{\displaystyle n}elementos. Las variantes de la estructura de datos de montón básica, como los montones de emparejamiento o los montones de Fibonacci, pueden proporcionar mejores límites para algunas operaciones. [ 6 ]

Alternativamente, cuando se utiliza un árbol de búsqueda binaria autoequilibrado , la inserción y la eliminación también tomanO(registronorte){\displaystyle O(\log n)}tiempo, aunque construir árboles a partir de secuencias de elementos existentes llevaO(norteregistronorte){\displaystyle O(n\log n)}tiempo; esto es típico cuando ya se tiene acceso a estas estructuras de datos, como con bibliotecas estándar o de terceros. Desde el punto de vista de la complejidad espacial, usar un árbol de búsqueda binaria autoequilibrado con lista enlazada requiere más almacenamiento, ya que necesita almacenar referencias adicionales a otros nodos.

Desde el punto de vista de la complejidad computacional, las colas de prioridad son congruentes con los algoritmos de ordenación. La sección sobre la equivalencia entre colas de prioridad y algoritmos de ordenación , que se presenta a continuación, describe cómo los algoritmos de ordenación eficientes pueden generar colas de prioridad eficientes.

Montones especializados

Existen varias estructuras de datos de montón especializadas que proporcionan operaciones adicionales o superan el rendimiento de las implementaciones basadas en montón para tipos específicos de claves, en concreto, claves enteras. Supongamos que el conjunto de claves posibles es{1,2,...,do}{\displaystyle \{1,2,...,C\}}.

  • Cuando solo se necesitan insert, find-miny y en caso de prioridades enteras, se puede construir una cola de cubetas como una matriz deextract-mindo{\displaystyle C}listas enlazadas más un punteroarriba{\displaystyle {\text{superior}}}, inicialmentedo{\displaystyle C}Insertar un elemento con clavek{\displaystyle k}agrega el elemento a lak{\displaystyle k}Lista y actualizacionesarribamin(arriba,k){\displaystyle {\text{top}}\gets {\text{min}}({\text{top}},k)}, ambos en tiempo constante. extract-minElimina y devuelve un elemento de la lista con índicearriba{\displaystyle {\text{superior}}}, luego incrementosarriba{\displaystyle {\text{superior}}}si es necesario hasta que vuelva a apuntar a una lista no vacía; esto tomaO(do){\displaystyle O(C)}tiempo en el peor de los casos. Estas colas son útiles para ordenar los vértices de un grafo por su grado. [ 7 ] : 374
  • Un árbol de van Emde Boas admite las operaciones minimum, maximum, insert, delete, search, extract-min, extract-max, predecessory ensuccessor]O(registroregistrodo){\displaystyle O(\log \log C)}tiempo, pero tiene un costo de espacio para colas pequeñas de aproximadamenteO(2metro/2){\displaystyle O(2^{m/2})}, dóndemetro{\displaystyle m}es el número de bits en el valor de prioridad. [ 8 ] El espacio se puede reducir significativamente con el hashing.
  • El árbol Fusion de Fredman y Willard implementa la minimumoperación enO(1){\displaystyle O(1)}tiempo y insertoperaciones extract-minenO(registronorte/registroregistrodo){\displaystyle O(\log n/\log \log C)}tiempo. Sin embargo, el autor afirma que: «Nuestros algoritmos tienen interés meramente teórico; los factores constantes que influyen en los tiempos de ejecución impiden su aplicación práctica». [ 9 ]

Para aplicaciones que realizan muchas operaciones de " mirar " por cada extract-minoperación " ", la complejidad temporal de las acciones de mirar se puede reducir aO(1){\displaystyle O(1)}En todas las implementaciones de árbol y montón, se almacena en caché el elemento de mayor prioridad después de cada inserción y eliminación. Para la inserción, esto añade como máximo un coste constante, ya que el elemento recién insertado se compara únicamente con el elemento mínimo previamente almacenado en caché. Para la eliminación, esto añade como máximo un coste adicional de "inspección", que suele ser menor que el coste de eliminación, por lo que la complejidad temporal general no se ve afectada significativamente.

Las colas de prioridad monótonas son colas especializadas optimizadas para el caso en que nunca se inserta un elemento con una prioridad inferior (en el caso de un montículo mínimo) a la de cualquier elemento extraído previamente. Esta restricción se cumple en diversas aplicaciones prácticas de las colas de prioridad.

Resumen de los tiempos de carrera

Aquí se muestran las complejidades temporales [ 10 ] de diversas estructuras de datos de montículo. La abreviatura am. indica que la complejidad dada está amortizada; de lo contrario, se trata de la complejidad en el peor de los casos. Para conocer el significado de " O ( f )" y " Θ ( f )", consulte la notación Big O. Los nombres de las operaciones presuponen un montículo mínimo.

  1. make-heap es la operación de construir un montón a partir de una secuencia de n elementos no ordenados. Se puede realizar entiempo Θ ( n ) siempre que meld se ejecute en tiempo O (log n ) (donde ambas complejidades se pueden amortizar). [ 11 ] [ 12 ] Otro algoritmo alcanza Θ ( n ) para montones binarios. [ 13 ] 
  2. 1 2 3 Paramontículos persistentes (que no admiten decrease-key ), una transformación genérica reduce el costo de meld al de insert , mientras que el nuevo costo de delete-min es la suma de los costos antiguos de delete-min y meld . [ 16 ] Aquí, hace que meld se ejecute en tiempo Θ (1) (amortizado, si el costo de insert es) mientras que delete-min todavía se ejecuta en O (log n ). Aplicado a montículos binomiales asimétricos, produce colas de Brodal-Okasaki, montículos persistentes con complejidades óptimas en el peor de los casos. [ 15 ] 
  3. Límite inferior deΩ(registroregistronorte),{\displaystyle \Omega (\log \log n),}[ 19 ] límite superior deO(22registroregistronorte).{\displaystyle O(2^{2{\sqrt {\log \log n}}}).}[ 20 ]
  4. Las colas de Brodal y los montículos de Fibonacci estrictos alcanzan complejidades óptimas en el peor de los casos para los montículos. Inicialmente se describieron como estructuras de datos imperativas. La cola de Brodal-Okasaki es una estructura de datos persistente que alcanza el mismo óptimo, excepto queno admite la decreción de clave .

Equivalencia entre colas de prioridad y algoritmos de ordenación

Utilizar una cola de prioridad para ordenar

La semántica de las colas de prioridad sugiere naturalmente un método de ordenación: insertar todos los elementos a ordenar en una cola de prioridad y eliminarlos secuencialmente; aparecerán ordenados. Este es, de hecho, el procedimiento utilizado por varios algoritmos de ordenación , una vez eliminada la capa de abstracción que proporciona la cola de prioridad. Este método de ordenación es equivalente a los siguientes algoritmos de ordenación:

Utilizar un algoritmo de ordenación para crear una cola de prioridad.

También se puede utilizar un algoritmo de ordenación para implementar una cola de prioridad. Específicamente, Thorup dice: [ 26 ]

Presentamos una reducción de espacio lineal determinista general de colas de prioridad a ordenación, lo que implica que si podemos ordenar hastanorte{\displaystyle n}llaves enS(norte){\displaystyle S(n)}tiempo por clave, luego hay una cola de prioridad que admite deletey insertenO(S(norte)){\displaystyle O(S(n))}tiempo y find-minen tiempo constante.

Es decir, si existe un algoritmo de ordenación que pueda ordenar enO(S){\displaystyle O(S)}tiempo por tecla, dondeS{\displaystyle S}es alguna función denorte{\displaystyle n}y tamaño de palabra , [ 27 ] entonces se puede utilizar el procedimiento dado para crear una cola de prioridad donde extraer el elemento de mayor prioridad esO(1){\displaystyle O(1)}tiempo, e insertar nuevos elementos (y eliminar elementos) esO(S){\displaystyle O(S)}tiempo. Por ejemplo, si uno tiene unO(norteregistronorte){\displaystyle O(n\log n)}algoritmo de ordenación, se puede crear una cola de prioridad conO(1){\displaystyle O(1)}tirando yO(registronorte){\displaystyle O(\log n)}inserción.

Bibliotecas

Una cola de prioridad suele considerarse una " estructura de datos contenedora ".

La Standard Template Library (STL) y el estándar C++ 1998 especifican `std::priority_queue` como una de las plantillas de clase adaptadoras de contenedores de la STL . Sin embargo, no especifica cómo se deben atender dos elementos con la misma prioridad, y de hecho, las implementaciones comunes no los devolverán según su orden en la cola. Implementa una cola de máxima prioridad y tiene tres parámetros: un objeto de comparación para ordenar, como un objeto de función (por defecto si no se especifica), el contenedor subyacente para almacenar las estructuras de datos (por defecto ), y dos iteradores al principio y al final de una secuencia. A diferencia de los contenedores STL reales, no permite la iteración de sus elementos (se adhiere estrictamente a su definición de tipo de datos abstracto). La STL también tiene funciones de utilidad para manipular otro contenedor de acceso aleatorio como un montón binario de máxima prioridad. Las bibliotecas Boost también tienen una implementación en el montón de la biblioteca.less<T>std::vector<T>

El módulo heapq de Python implementa un min-heap binario sobre una lista.

La biblioteca de JavaPriorityQueue contiene una clase ( java.util.PriorityQueue), que implementa una cola de prioridad mínima como un montón binario.

La biblioteca de .NET contiene una clase System.Collections.Generic.PriorityQueue , que implementa un min-heap cuaternario respaldado por una matriz.

La biblioteca de Scala contiene una clase scala.collection.mutable.PriorityQueue , que implementa una cola de prioridad máxima.

La biblioteca de Go contiene un módulo de contenedor/montón que implementa un montículo mínimo sobre cualquier estructura de datos compatible.

La biblioteca estándar de Rust contiene una estructura std::collections::BinaryHeap , que implementa una cola de prioridad con un montón binario.

La extensión de la biblioteca estándar de PHP contiene la clase SplPriorityQueue .

El framework Core Foundation de Apple contiene una estructura CFBinaryHeap , que implementa un min-heap.

Aplicaciones

Gestión del ancho de banda

La priorización de colas se puede utilizar para gestionar recursos limitados, como el ancho de banda en una línea de transmisión desde un enrutador de red . En caso de que el tráfico saliente se acumule en la cola debido a un ancho de banda insuficiente, todas las demás colas se pueden detener para enviar el tráfico de la cola de mayor prioridad al llegar. Esto garantiza que el tráfico prioritario (como el tráfico en tiempo real, por ejemplo, una transmisión RTP de una conexión VoIP ) se reenvíe con el menor retraso y la menor probabilidad de ser rechazado debido a que una cola alcance su capacidad máxima. El resto del tráfico se puede gestionar cuando la cola de mayor prioridad esté vacía. Otro enfoque utilizado consiste en enviar una cantidad desproporcionadamente mayor de tráfico desde las colas de mayor prioridad.

Muchos protocolos modernos para redes de área local también incluyen el concepto de colas de prioridad en la subcapa de control de acceso al medio (MAC) para garantizar que las aplicaciones de alta prioridad (como VoIP o IPTV ) experimenten una latencia menor que otras aplicaciones que pueden ser atendidas con un servicio de mejor esfuerzo . Algunos ejemplos incluyen IEEE 802.11e (una enmienda a IEEE 802.11 que proporciona calidad de servicio ) e ITU-T G.hn (un estándar para redes de área local de alta velocidad que utilizan el cableado doméstico existente ( líneas eléctricas , líneas telefónicas y cables coaxiales ).

Normalmente, se establece una limitación (policía) para restringir el ancho de banda que puede utilizar el tráfico de la cola de mayor prioridad, con el fin de evitar que los paquetes de alta prioridad saturen el resto del tráfico. Este límite rara vez se alcanza gracias a instancias de control de alto nivel, como Cisco Callmanager , que se puede programar para bloquear las llamadas que superen el límite de ancho de banda programado.

Simulación de eventos discretos

Otro uso de una cola de prioridad es gestionar los eventos en una simulación de eventos discretos . Los eventos se añaden a la cola utilizando su tiempo de simulación como criterio de prioridad. La ejecución de la simulación se lleva a cabo extrayendo repetidamente el elemento superior de la cola y ejecutando el evento correspondiente.

Véase también : Planificación (informática) , teoría de colas

El algoritmo de Dijkstra

Cuando el grafo se almacena en forma de lista de adyacencia o matriz, se puede utilizar una cola de prioridad para extraer el mínimo de manera eficiente al implementar el algoritmo de Dijkstra , aunque también se necesita la capacidad de modificar la prioridad de un vértice en particular en la cola de prioridad de manera eficiente.

Si, en cambio, un grafo se almacena como objetos de nodo y los pares prioridad-nodo se insertan en un montón, no es necesario modificar la prioridad de un vértice en particular si se realiza un seguimiento de los nodos visitados. Una vez visitado un nodo, si vuelve a aparecer en el montón (tras haber tenido un número de prioridad menor asociado anteriormente), se elimina y se ignora.

Codificación de Huffman

La codificación de Huffman requiere obtener repetidamente los dos árboles de menor frecuencia. Una cola de prioridad es un método para lograrlo .

Algoritmos de búsqueda primero el mejor

Los algoritmos de búsqueda primero en amplitud , como el algoritmo A* , encuentran el camino más corto entre dos vértices o nodos de un grafo ponderado , probando primero las rutas más prometedoras. Se utiliza una cola de prioridad (también conocida como límite inferior ) para gestionar las rutas no exploradas; aquella cuya estimación (un límite inferior en el caso de A*) de la longitud total del camino sea la más pequeña recibe la máxima prioridad. Si las limitaciones de memoria hacen que la búsqueda primero en amplitud sea impracticable, se pueden utilizar variantes como el algoritmo SMA* , con una cola de prioridad de doble extremo para permitir la eliminación de elementos de baja prioridad.

Algoritmo de triangulación ROAM

El algoritmo ROAM (Real-time Optimally Adapting Meshes ) calcula una triangulación dinámica del terreno. Su funcionamiento se basa en dividir los triángulos donde se requiere mayor detalle y fusionarlos donde se requiere menor detalle. El algoritmo asigna a cada triángulo del terreno una prioridad, generalmente relacionada con la reducción del error que se produciría al dividirlo. El algoritmo utiliza dos colas de prioridad: una para los triángulos que se pueden dividir y otra para los que se pueden fusionar. En cada paso, se divide el triángulo de la cola de división con la prioridad más alta, o se fusiona con sus vecinos el triángulo de la cola de fusión con la prioridad más baja.

Algoritmo de Prim para el árbol de expansión mínima

Al usar la cola de prioridad de montículo mínimo en el algoritmo de Prim para encontrar el árbol de expansión mínimo de un grafo conectado y no dirigido , se puede lograr un buen tiempo de ejecución. Esta cola de prioridad de montículo mínimo utiliza la estructura de datos de montículo mínimo que admite operaciones tales como , , , . [ 28 ] En esta implementación, el peso de las aristas se usa para decidir la prioridad de los vértices . Menor peso, mayor prioridad y mayor peso, menor prioridad. [ 29 ]insertminimumextract-mindecrease-key

Cola de prioridad paralela

La paralelización se puede utilizar para acelerar las colas de prioridad, pero requiere algunos cambios en la interfaz de la cola de prioridad. La razón de estos cambios es que una actualización secuencial generalmente solo tieneO(1){\textstyle O(1)}oO(registronorte){\textstyle O(\log n)}costo, y no hay ganancia práctica al paralelizar dicha operación. Un posible cambio es permitir el acceso concurrente de múltiples procesadores a la misma cola de prioridad. El segundo posible cambio es permitir operaciones por lotes que trabajan enk{\textstyle k}elementos, en lugar de solo un elemento. Por ejemplo, extractMineliminará el primero.k{\textstyle k}elementos con la máxima prioridad.

Acceso paralelo concurrente

Si la cola de prioridad permite el acceso concurrente, varios procesos pueden realizar operaciones simultáneamente en ella. Sin embargo, esto plantea dos problemas. En primer lugar, la definición de la semántica de las operaciones individuales deja de ser evidente. Por ejemplo, si dos procesos desean extraer el elemento con la prioridad más alta, ¿deberían obtener el mismo elemento o elementos diferentes? Esto restringe el paralelismo a nivel del programa que utiliza la cola de prioridad. Además, dado que varios procesos tienen acceso al mismo elemento, esto genera contención.

Se inserta el nodo 3 y se establece el puntero del nodo 2 al nodo 3. Inmediatamente después, se elimina el nodo 2 y se establece el puntero del nodo 1 al nodo 4. Ahora el nodo 3 ya no es accesible.

El acceso concurrente a una cola de prioridad se puede implementar en un modelo PRAM de lectura concurrente, escritura concurrente (CRCW). A continuación, la cola de prioridad se implementa como una lista de salto . [ 30 ] [ 31 ] Además, se utiliza una primitiva de sincronización atómica, CAS , para que la lista de salto no requiera bloqueo . Los nodos de la lista de salto constan de una clave única, una prioridad, un array de punteros , para cada nivel, a los nodos siguientes y una deletemarca. La deletemarca indica si el nodo está a punto de ser eliminado por un proceso. Esto garantiza que otros procesos puedan reaccionar a la eliminación de forma adecuada.

  • insert(e)Primero, se crea un nuevo nodo con una clave y una prioridad. Además, se le asigna un número de niveles, que determina el tamaño del array de punteros. A continuación, se realiza una búsqueda para encontrar la posición correcta donde insertar el nuevo nodo. La búsqueda comienza desde el primer nodo y desde el nivel más alto. Luego, se recorre la lista de saltos hasta el nivel más bajo hasta encontrar la posición correcta. Durante la búsqueda, para cada nivel, el último nodo recorrido se guarda como nodo padre del nuevo nodo en ese nivel. Además, el nodo al que apunta el puntero del nodo padre en ese nivel se guarda como nodo sucesor del nuevo nodo en ese nivel. Posteriormente, para cada nivel del nuevo nodo, los punteros del nodo padre se establecen al nuevo nodo. Finalmente, los punteros, para cada nivel, del nuevo nodo se establecen a los nodos sucesores correspondientes.
  • extract-minPrimero, se recorre la lista de nodos a omitir hasta encontrar un nodo cuya deletemarca no esté definida. Esta deletemarca se establece como verdadera para ese nodo. Finalmente, se actualizan los punteros de los nodos padres del nodo eliminado.

Si se permite el acceso concurrente a una cola de prioridad, pueden surgir conflictos entre dos procesos. Por ejemplo, se produce un conflicto si un proceso intenta insertar un nuevo nodo, pero al mismo tiempo otro proceso está a punto de eliminar el predecesor de ese nodo. [ 30 ] Existe el riesgo de que el nuevo nodo se añada a la lista de saltos, pero que ya no sea accesible. ( Ver imagen )

Operaciones con elementos K

En este entorno, las operaciones en una cola de prioridad se generalizan a un lote dek{\textstyle k}elementos. Por ejemplo, k_extract-minelimina elk{\textstyle k}toma los elementos más pequeños de la cola de prioridad y los devuelve.

En un entorno de memoria compartida , la cola de prioridad paralela se puede implementar fácilmente utilizando árboles de búsqueda binaria paralelos y algoritmos de árbol basados ​​en uniones . En particular, k_extract-mincorresponde a una división en el árbol de búsqueda binaria que tieneO(registronorte){\textstyle O(\log n)}costo y produce un árbol que contiene elk{\textstyle k}elementos más pequeños. k_insertse puede aplicar mediante una unión de la cola de prioridad original y el lote de inserciones. Si el lote ya está ordenado por la clave, k_inserttieneO(kregistro(1+nortek)){\textstyle O(k\log(1+{\frac {n}{k}}))}costo. De lo contrario, primero debemos clasificar el lote, por lo que el costo seráO(kregistro(1+nortek)+kregistrok)=O(kregistronorte){\textstyle O(k\log(1+{\frac {n}{k}})+k\log k)=O(k\log n)}Otras operaciones para colas de prioridad se pueden aplicar de manera similar. Por ejemplo, k_decrease-keyse puede realizar aplicando primero differencey luego union, que primero elimina los elementos y luego los vuelve a insertar con las claves actualizadas. Todas estas operaciones son altamente paralelas, y la eficiencia teórica y práctica se puede encontrar en artículos de investigación relacionados. [ 32 ] [ 33 ]

El resto de esta sección describe un algoritmo basado en colas para memoria distribuida. Partimos de la base de que cada procesador dispone de su propia memoria local y una cola de prioridad local (secuencial). Los elementos de la cola de prioridad global (paralela) se distribuyen entre todos los procesadores.

k_extract-minSe ejecuta en una cola de prioridad con tres procesadores. Los elementos en verde se devuelven y se eliminan de la cola de prioridad.

Una k_insertoperación asigna los elementos de forma aleatoria y uniforme a los procesadores, quienes los insertan en sus colas locales. Cabe destacar que aún se pueden insertar elementos individuales en la cola. Mediante esta estrategia, los elementos globales más pequeños se encuentran, con alta probabilidad, en la unión de los elementos locales más pequeños de cada procesador. De este modo, cada procesador posee una parte representativa de la cola de prioridad global.

Esta propiedad se utiliza cuando k_extract-minse ejecuta, como el más pequeñometro{\textstyle m}Los elementos de cada cola local se eliminan y se recopilan en un conjunto de resultados. Los elementos del conjunto de resultados siguen asociados a su procesador original. El número de elementosmetro{\textstyle m}que se elimina de cada cola local depende dek{\textstyle k}y el número de procesadorespag{\textstyle p}. [ 34 ] Mediante selección paralela elk{\textstyle k}Se determinan los elementos más pequeños del conjunto de resultados. Con alta probabilidad, estos son los globales.k{\textstyle k}elementos más pequeños. Si no,metro{\textstyle m}Los elementos se eliminan nuevamente de cada cola local y se colocan en el conjunto de resultados. Esto se hace hasta que la globalk{\textstyle k}Los elementos más pequeños están en el conjunto de resultados. Ahora bien, estosk{\textstyle k}Se pueden devolver elementos. Todos los demás elementos del conjunto de resultados se insertan de nuevo en sus colas locales. k_extract-minSe espera el tiempo de ejecución.O(kpagregistro(norte)){\textstyle O({\frac {k}{p}}\log(n))}, dóndek=Ω(pagregistro(pag)){\textstyle k=\Omega (p\cdot \log(p))}ynorte{\textstyle n}es el tamaño de la cola de prioridad. [ 34 ]

La cola de prioridad se puede mejorar aún más evitando que los elementos restantes del conjunto de resultados vuelvan directamente a las colas locales después de una k_extract-minoperación. Esto evita tener que mover elementos constantemente entre el conjunto de resultados y las colas locales.

Al eliminar varios elementos a la vez, se puede lograr una aceleración considerable. Pero no todos los algoritmos pueden usar este tipo de cola de prioridad. El algoritmo de Dijkstra, por ejemplo, no puede trabajar con varios nodos a la vez. El algoritmo toma el nodo con la distancia más pequeña de la cola de prioridad y calcula nuevas distancias para todos sus nodos vecinos. Si se eliminarak{\textstyle k}nodos, trabajando en un nodo podría cambiar la distancia de otro de losk{\textstyle k}nodos. Por lo tanto, el uso de operaciones de k elementos destruye la propiedad de configuración de etiquetas del algoritmo de Dijkstra.

Véase también

Referencias

  1. 1 2 Miller Jr., Robert G. (1960). "Colas de prioridad" (PDF) . The Annals of Mathematical Statistics . 31. Universidad de Stanford: 86–103 . doi : 10.1214/aoms/1177705990 .
  2. "PriorityQueue (Java SE 9 y JDK 9)" . docs.oracle.com . Consultado el 13 de marzo de 2025 .
  3. ^ Cormen, Thomas H .; Leiserson, Charles E .; Rivest, Ronald L .; Stein, Clifford (2022) [1990]. "Capítulo 6.5: Colas prioritarias". Introducción a los algoritmos (4ª ed.). MIT Press y McGraw-Hill. págs. 172-176 . ISBN   0-262-04630-X.
  4. 1 2 3 4 5 Rönngren, Robert; Ayani, Rassul (1997-04-01). "Un estudio comparativo de algoritmos de cola de prioridad paralelos y secuenciales" . ACM Trans. Model. Comput. Simul . 7 (2): 157– 209. doi : 10.1145/249204.249205 . ISSN 1049-3301 . 
  5. 1 2 3 4 5 Ayani, R. (diciembre de 1990). "Algoritmo LR: Operaciones concurrentes en colas de prioridad". Actas del Segundo Simposio IEEE sobre Procesamiento Paralelo y Distribuido de 1990. págs. 22–25 . doi : 10.1109/SPDP.1990.143500 . ISBN  0-8186-2087-0.
  6. Cormen, Thomas H.; Leiserson , Charles E .; Rivest, Ronald L .; Stein, Clifford (2001) [1990]. «Capítulo 20: Montículos de Fibonacci». Introducción a los algoritmos (2.ª ed.). MIT Press y McGraw-Hill. págs. 476–497 . ISBN   0-262-03293-7.Tercera edición, pág. 518.
  7. Skiena, Steven (2010). Manual de diseño de algoritmos (2.ª ed.). Springer Science+Business Media . ISBN  978-1-849-96720-4.
  8. P. van Emde Boas. Preservación del orden en un bosque en tiempo inferior al logarítmico. En Actas del 16.º Simposio Anual sobre Fundamentos de la Informática , páginas 75-84. IEEE Computer Society, 1975.
  9. Michael L. Fredman y Dan E. Willard. Superando el límite de la teoría de la información con árboles de fusión. Journal of Computer and System Sciences , 48(3):533-551, 1994
  10. 1 2 3 4 Cormen, Thomas H .; Leiserson, Charles E .; Rivest, Ronald L. (1990). Introducción a los algoritmos (1ª ed.). MIT Press y McGraw-Hill. ISBN  0-262-03141-8.
  11. 1 2 3 Sleator, Daniel Dominic ; Tarjan, Robert Endre (febrero de 1986). "Montículos autoajustables" . SIAM Journal on Computing . 15 (1): 52– 69. CiteSeerX 10.1.1.93.6678 . doi : 10.1137/0215004 . ISSN 0097-5397 .  
  12. 1 2 Tarjan, Robert (1983). "3.3. Montones izquierdistas". Estructuras de datos y algoritmos de red . págs. 38–42 . doi : 10.1137/1.9781611970265 . ISBN  978-0-89871-187-5.
  13. Hayward, Ryan; McDiarmid, Colin (1991). "Análisis del caso promedio de la construcción de montículos mediante inserción repetida" (PDF) . J. Algorithms . 12 : 126–153 . CiteSeerX 10.1.1.353.7888 . doi : 10.1016/0196-6774(91)90027-v . Archivado del original (PDF) el 5 de febrero de 2016. Recuperado el 28 de enero de 2016 . 
  14. "Montículo binomial | Brilliant Math & Science Wiki" . brilliant.org . Consultado el 30 de septiembre de 2019 .
  15. 1 2 Brodal, Gerth Stølting; Okasaki, Chris (noviembre de 1996), "Colas de prioridad puramente funcionales óptimas", Journal of Functional Programming , 6 (6): 839– 857, doi : 10.1017/s095679680000201x
  16. Okasaki, Chris (1998). "10.2. Abstracción estructural". Estructuras de datos puramente funcionales (1.ª ed.). págs. 158–162 . ISBN   9780521631242.
  17. Takaoka, Tadao (1999), Teoría de los montículos 2-3 (PDF) , pág. 12 
  18. Iacono, John (2000), "Improved upper bounds for pairing heaps", Proc. 7th Scandinavian Workshop on Algorithm Theory (PDF) , Lecture Notes in Computer Science, vol. 1851, Springer-Verlag, pp. 63–77 , arXiv : 1110.4428 , CiteSeerX 10.1.1.748.7812 , doi : 10.1007/3-540-44985-X_5 , ISBN    3-540-67690-2
  19. Fredman, Michael Lawrence (julio de 1999). "Sobre la eficiencia de los montículos de emparejamiento y estructuras de datos relacionadas" (PDF) . Journal of the Association for Computing Machinery . 46 (4): 473– 501. doi : 10.1145/320211.320214 .
  20. Pettie, Seth (2005). Hacia un análisis final de los montículos de emparejamiento (PDF) . Actas de FOCS '05 del 46.º Simposio Anual IEEE sobre Fundamentos de la Informática. págs. 174–183 . CiteSeerX 10.1.1.549.471 . doi : 10.1109/SFCS.2005.75 . ISBN   0-7695-2468-0.
  21. Haeupler, Bernhard; Sen, Siddhartha; Tarjan, Robert E. (noviembre de 2011). "Montones de emparejamiento de rangos" (PDF) . SIAM J. Informática . 40 (6): 1463–1485.doi : 10.1137 / 100785351 .
  22. Fredman, Michael Lawrence ; Tarjan, Robert E. (julio de 1987). "Montículos de Fibonacci y sus usos en algoritmos mejorados de optimización de redes" (PDF) . Journal of the Association for Computing Machinery . 34 (3): 596– 615. CiteSeerX 10.1.1.309.8927 . doi : 10.1145/28869.28874 . 
  23. Brodal, Gerth Stølting ; Lagogiannis, George; Tarjan, Robert E. (2012). Montículos estrictos de Fibonacci (PDF) . Actas del 44.º simposio sobre Teoría de la Computación - STOC '12. págs. 1177–1184 . CiteSeerX 10.1.1.233.1740 . doi : 10.1145/2213977.2214082 . ISBN   978-1-4503-1245-5.
  24. Brodal, Gerth S. ( 1996), "Colas de prioridad eficientes en el peor de los casos" (PDF) , Actas del 7.º Simposio Anual ACM-SIAM sobre Algoritmos Discretos , págs. 52–58 
  25. Goodrich, Michael T .; Tamassia, Roberto (2004). "7.3.6. Construcción de montículos ascendentes". Estructuras de datos y algoritmos en Java (3.ª ed.). págs. 338–341 . ISBN   0-471-46983-1.
  26. Thorup, Mikkel (2007). "Equivalencia entre colas de prioridad y ordenación". Journal of the ACM . 54 (6): 28. doi : 10.1145/1314690.1314692 . S2CID 11494634 . 
  27. "Copia archivada" (PDF) . Archivado (PDF) del original el 20/07/2011 . Recuperado el 10/02/2011 .{{cite web}}: CS1 mantenimiento: copia archivada como título ( enlace )
  28. ^ Cormen, Thomas H .; Leiserson, Charles E .; Rivest, Ronald L .; Stein, Clifford (2009) [1990]. Introducción a los algoritmos (3ª ed.). MIT Press y McGraw-Hill. pag. 634.ISBN   0-262-03384-4."Para implementar el algoritmo de Prim de manera eficiente, necesitamos una forma rápida de seleccionar una nueva arista para agregar al árbol formado por las aristas en A."
  29. "Algoritmo de Prim" . Geek for Geeks. 18 de noviembre de 2012. Archivado del original el 9 de septiembre de 2014. Consultado el 12 de septiembre de 2014 .
  30. 1 2 Sundell, Håkan; Tsigas, Philippas (2005). "Colas de prioridad concurrentes rápidas y sin bloqueo para sistemas multihilo" . Actas del Simposio Internacional de Procesamiento Paralelo y Distribuido . Vol. 65. págs. 609–627 . CiteSeerX 10.1.1.67.1310 . doi : 10.1109/IPDPS.2003.1213189 . ISBN    0-7695-1926-1. S2CID 20995116 . 
  31. Lindén, Jonsson (2013), "Una cola de prioridad concurrente basada en listas de salto con mínima contención de memoria" , Informe técnico 2018-003 (en alemán)
  32. Blelloch, Guy E.; Ferizovic, Daniel; Sun, Yihan (2016), "Just Join for Parallel Ordered Sets", Simposio sobre algoritmos y arquitecturas paralelas, Actas del 28.º Simposio ACM sobre algoritmos y arquitecturas paralelas (SPAA 2016) , ACM, págs. 253–264 , arXiv : 1602.02120 , doi : 10.1145/2935764.2935768 , ISBN  978-1-4503-4210-0, S2CID 2897793 
  33. Blelloch, Guy E.; Ferizovic, Daniel; Sun, Yihan ( 2018), "PAM: mapas aumentados paralelos", Actas del 23.er Simposio ACM SIGPLAN sobre Principios y Práctica de la Programación Paralela , ACM, págs. 290–304 
  34. 1 2 Sanders, Peter; Mehlhorn, Kurt; Dietzfelbinger, Martin; Dementiev, Roman (2019). Algoritmos y estructuras de datos secuenciales y paralelos: la caja de herramientas básica . Springer International Publishing. pp. 226–229 . doi : 10.1007/978-3-030-25209-0 . ISBN  978-3-030-25208-3. S2CID 201692657 . 

Lecturas adicionales

  • Referencia de C++ parastd::priority_queue
  • Descripciones de Lee Killough
  • libpqueue es una implementación genérica de cola de prioridad (montón) (en C) utilizada por el proyecto del servidor HTTP Apache.
  • Estudio de las estructuras de colas de prioridad conocidas realizado por Stefan Xenos.
  • UC Berkeley - Ciencias de la Computación 61B - Lección 24: Colas de Prioridad (video) - Introducción a las colas de prioridad usando un montón binario
  • Métodos y operaciones de la cola de prioridad en C++
  • Implementación de una cola de prioridad en Java
  • Implementación de una cola de prioridad en C