
En informática , un montón es una estructura de datos basada en árboles que satisface la propiedad de montón : En un montón máximo , para cualquier nodo C dado, si P es el nodo padre de C, entonces la clave (el valor ) de P es mayor o igual que la clave de C. En un montón mínimo , la clave de P es menor o igual que la clave de C. [ 1 ] El nodo en la "cima" del montón (sin padres) se llama nodo raíz .
El montículo es una implementación de máxima eficiencia de un tipo de dato abstracto llamado cola de prioridad . De hecho, las colas de prioridad suelen denominarse "montículos", independientemente de su implementación. En un montículo, el elemento de mayor (o menor) prioridad siempre se almacena en la raíz. Sin embargo, un montículo no es una estructura ordenada; puede considerarse parcialmente ordenada. Un montículo es una estructura de datos útil cuando es necesario eliminar repetidamente el objeto con la mayor (o menor) prioridad, o cuando las inserciones deben intercalarse con eliminaciones del nodo raíz.
Una implementación común de un montón es el montón binario , en el que el árbol es un árbol binario completo [ 2 ] (ver figura). La estructura de datos de montón, específicamente el montón binario, fue introducida por JWJ Williams en 1964, como una estructura de datos para el algoritmo de ordenación heapsort . [ 3 ] Los montones también son cruciales en varios algoritmos de grafos eficientes como el algoritmo de Dijkstra . Cuando un montón es un árbol binario completo, tiene la altura más pequeña posible: un montón con N nodos y a ramas para cada nodo siempre tiene log a N de altura.
Cabe destacar que, como se muestra en el gráfico, no existe un orden implícito entre hermanos o primos, ni una secuencia predefinida para un recorrido en orden (como ocurriría, por ejemplo, en un árbol de búsqueda binaria ). La relación de montículo mencionada anteriormente se aplica únicamente entre los nodos y sus padres o abuelos. El número máximo de hijos que puede tener cada nodo depende del tipo de montículo.
Los montículos se construyen normalmente en el mismo array donde se almacenan los elementos, y su estructura es implícita en el patrón de acceso de las operaciones. En este sentido, los montículos se diferencian de otras estructuras de datos con límites teóricos similares o, en algunos casos, mejores, como los árboles radix, en que no requieren memoria adicional más allá de la utilizada para almacenar las claves.
Operaciones
Las operaciones comunes que involucran montones son:
- Básico
- find-max (o find-min ): encuentra el elemento máximo de un montículo máximo o el elemento mínimo de un montículo mínimo, respectivamente (también conocido como peek ).
- insertar : agregar una nueva clave al montón (también conocido como push [ 4 ] )
- extract-max (o extract-min ): devuelve el nodo de valor máximo de un montón máximo [o valor mínimo de un montón mínimo] después de eliminarlo del montón (también conocido como pop [ 5 ] ).
- delete-max (o delete-min ): elimina el nodo raíz de un montón máximo (o mínimo), respectivamente.
- reemplazar : extraer la raíz y agregar una nueva clave. Esto es más eficiente que extraer seguida de agregar, ya que solo necesita equilibrarse una vez, no dos, y es apropiado para montones de tamaño fijo. [ 6 ]
- Creación
- create-heap : crea un montón vacío
- heapify : crea un montón a partir de una matriz de elementos dada.
- fusión ( unión ): unir dos montones para formar un nuevo montón válido que contenga todos los elementos de ambos, preservando los montones originales.
- fusionar : unir dos montones para formar un nuevo montón válido que contenga todos los elementos de ambos, destruyendo los montones originales.
- Inspección
- tamaño : devuelve el número de elementos en el montón.
- is-empty : devuelve verdadero si el montón está vacío, falso en caso contrario.
- Interno
- increment-key o decrease-key : actualizan una clave dentro de un montón máximo o mínimo, respectivamente.
- delete : elimina un nodo arbitrario (seguido del movimiento del último nodo y el filtrado para mantener el montón).
- sift-up : mueve un nodo hacia arriba en el árbol, tanto como sea necesario; se utiliza para restaurar la condición del montón después de la inserción. Se llama "tamiz" porque el nodo se mueve hacia arriba en el árbol hasta alcanzar el nivel correcto, como en un tamiz .
- sift-down : mueve un nodo hacia abajo en el árbol, de forma similar a sift-up; se utiliza para restaurar el estado del montón después de una eliminación o reemplazo.
Implementación mediante arreglos
Los montones se suelen implementar con un array , como se muestra a continuación:
- Cada elemento del array representa un nodo del montón, y
- La relación padre/hijo se define implícitamente mediante los índices de los elementos en el array.

Para un montón binario , en el arreglo, el primer índice contiene el elemento raíz. Los siguientes dos índices del arreglo contienen los hijos de la raíz. Los siguientes cuatro índices contienen los cuatro hijos de los dos nodos hijos de la raíz, y así sucesivamente. Por lo tanto, dado un nodo en el índice i , sus hijos están en los índicesy , y su padre está en el índice ⌊( i −1)/2⌋ en una matriz que comienza desde el índice , o en , , y ⌊ i /2⌋ , respectivamente, en una matriz que comienza desde Este sencillo esquema de indexación permite recorrer el árbol de forma eficiente, tanto hacia arriba como hacia abajo.
El equilibrio de un montón se logra mediante operaciones de intercambio (intercambio de elementos que están fuera de orden). Dado que podemos construir un montón a partir de un arreglo sin necesidad de memoria adicional (para los nodos, por ejemplo), el algoritmo de ordenación por montículos (heapsort ) se puede utilizar para ordenar un arreglo in situ.
Después de insertar o eliminar un elemento de un montón, la propiedad del montón puede verse comprometida y este debe reequilibrarse intercambiando elementos dentro del array.
Aunque los distintos tipos de montículos implementan las operaciones de manera diferente, la forma más común es la siguiente:
- Inserción: Añada el nuevo elemento al final del montón, en el primer espacio libre disponible. Si esto infringe la propiedad del montón, mueva el nuevo elemento hacia arriba ( operación de natación ) hasta que se restablezca dicha propiedad.
- Extracción: Elimine la raíz e inserte el último elemento del montón en la raíz. Si esto infringe la propiedad del montón, procese la nueva raíz ( operación de sumidero ) para restablecer dicha propiedad.
- Reemplazo: Elimine la raíz, coloque el nuevo elemento en la raíz y proceda a filtrar hacia abajo. En comparación con la extracción seguida de la inserción, esto evita un paso de filtrado hacia arriba.
La construcción de un montón binario (o d -ario) a partir de un arreglo dado de elementos se puede realizar en tiempo lineal utilizando el algoritmo clásico de Floyd , con un número de comparaciones en el peor de los casos igual a 2 N − 2 s 2 ( N ) − e 2 ( N ) (para un montón binario), donde s 2 ( N ) es la suma de todos los dígitos de la representación binaria de N y e 2 ( N ) es el exponente de 2 en la factorización prima de N . [ 7 ] Esto es más rápido que una secuencia de inserciones consecutivas en un montón originalmente vacío, que es logarítmicamente lineal. [ a ]
Variantes
- 2–3 montones
- Montón B
- Beap
- Montón binario
- Montículo binomial
- Cola ancha
- montón d -ario
- Montículo de Fibonacci
- Montón KD
- Montón de hojas
- montón de izquierdistas
- Montículo binomial asimétrico
- Montículo de Fibonacci estricto
- Montículo min-max
- Montón de emparejamiento
- Montón de raíz
- Montón mezclable aleatorio
- Montón sesgado
- Montón blando
- Montón ternario
- Trepa
- Montón débil
Comparación de límites teóricos para variantes
Aquí se muestran las complejidades temporales [ 8 ] 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áximo.
- ↑ Cada inserción toma O(log( k )) en el tamaño existente del montón, por lo tanto. Desde, un factor constante (la mitad) de estas inserciones están dentro de un factor constante del máximo, por lo que asintóticamente podemos asumir; formalmente el tiempo esEsto también se puede apreciar fácilmente en la aproximación de Stirling .
- ↑ 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). [ 9 ] [ 10 ] Otro algoritmo alcanza Θ ( n ) para montones binarios. [ 11 ]
- 1 2 3 Paramontículos persistentes (que no admiten increase-key ), una transformación genérica reduce el costo de meld al de insert , mientras que el nuevo costo de delete-max es la suma de los costos antiguos de delete-max y meld . [ 14 ] Aquí, hace que meld se ejecute en tiempo Θ (1) (amortizado, si el costo de insert lo es) mientras que delete-max 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. [ 13 ]
- ↑ Límite inferior de[ 17 ] límite superior de[ 18 ]
- 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 operación de incremento de clave .
Aplicaciones
La estructura de datos de montón tiene muchas aplicaciones.
- Heapsort : Uno de los mejores métodos de ordenación, ya que se realiza in situ y no presenta escenarios cuadráticos en el peor de los casos.
- Algoritmos de selección : Un montículo permite acceder al elemento mínimo o máximo en tiempo constante, y otras selecciones (como la mediana o el k-ésimo elemento) se pueden realizar en tiempo sublineal sobre datos que se encuentran en un montículo. [ 24 ]
- Algoritmos de grafos : Al usar montículos como estructuras de datos internas para el recorrido, el tiempo de ejecución se reduce en orden polinomial. Ejemplos de estos problemas son el algoritmo de árbol de expansión mínima de Prim y el algoritmo de camino más corto de Dijkstra .
- Cola de prioridad : Una cola de prioridad es un concepto abstracto como "una lista" o "un mapa"; al igual que una lista se puede implementar con una lista enlazada o un arreglo, una cola de prioridad se puede implementar con un montón o con una variedad de otros métodos.
- Fusión de K vías : Una estructura de datos de montón es útil para fusionar múltiples flujos de entrada ya ordenados en un único flujo de salida ordenado. Ejemplos de la necesidad de fusión incluyen la ordenación externa y la transmisión de resultados de datos distribuidos, como un árbol de fusión estructurado en registro. El bucle interno obtiene el elemento mínimo, lo reemplaza con el siguiente elemento del flujo de entrada correspondiente y luego realiza una operación de reducción de montón. (Alternativamente, se puede usar la función de reemplazo). (El uso de las funciones de extracción del máximo e inserción de una cola de prioridad es mucho menos eficiente).
Implementaciones de lenguajes de programación
- La biblioteca estándar de C++ proporciona los algoritmos `make_heap` , `push_heap` y `pop_heap` para montículos (generalmente implementados como montículos binarios), que operan sobre iteradores de acceso aleatorio arbitrarios . Trata los iteradores como referencias a un array y utiliza la conversión de array a montículo. También proporciona la clase `std::priority_queue` , que encapsula estas funcionalidades en una clase tipo contenedor. Sin embargo, no existe soporte estándar para las operaciones de reemplazo, desplazamiento ascendente/descendente ni disminución/incremento de claves.
- Las bibliotecas Boost C++ incluyen una biblioteca de montículos [ 25 ] . A diferencia de la STL, admite operaciones de disminución e incremento, y admite tipos adicionales de montículos: específicamente, admite montículos d- arios, binomiales, de Fibonacci, de emparejamiento y sesgados.
- Existe una implementación genérica de montón para C y C++ con soporte para montones D y B. Proporciona una API similar a la de la STL.
- La biblioteca estándar del lenguaje de programación D incluye std.container.BinaryHeap , que se implementa en términos de rangos de D. Se pueden construir instancias a partir de cualquier rango de acceso aleatorio . BinaryHeap expone una interfaz de rango de entrada que permite la iteración con las sentencias foreach integradas de D y la integración con la API basada en rangos del paquete std.algorithm .
- Para Haskell existe el módulo Data.Heap .
- La plataforma Java (desde la versión 1.5) proporciona una implementación de montón binario con la clase
java.util.PriorityQueuedel Java Collections Framework . Esta clase implementa por defecto un montón mínimo; para implementar un montón máximo, el programador debe escribir un comparador personalizado. No se admiten las operaciones de reemplazo, desplazamiento ascendente/descendente ni disminución/incremento de claves. - Python cuenta con un módulo heapq que implementa una cola de prioridad utilizando un montón binario. La biblioteca expone una función heapreplace para admitir la fusión de k vías.
- PHP cuenta con memoria máxima ( SplMaxHeap ) y memoria mínima ( SplMinHeap ) desde la versión 5.3 en la biblioteca estándar de PHP.
- Perl cuenta con implementaciones de montículos binarios, binomiales y de Fibonacci en la distribución Heap disponible en CPAN .
- El lenguaje Go incluye un paquete `heap` con algoritmos que operan sobre un tipo arbitrario que satisface una interfaz determinada. Este paquete no admite las operaciones de reemplazo, indexación ascendente/descendente ni de disminución/aumento de clave.
- La biblioteca Core Foundation de Apple contiene una estructura CFBinaryHeap .
- Pharo incluye una implementación de un montón en el paquete Collections-Sequenceable, junto con un conjunto de casos de prueba. El montón se utiliza en la implementación del bucle de eventos del temporizador.
- El lenguaje de programación Rust cuenta con una implementación de montículo máximo binario, BinaryHeap , en el módulo collections de su biblioteca estándar.
- .NET cuenta con la clase PriorityQueue , que utiliza una implementación de min-heap cuaternaria (d-aria). Está disponible a partir de .NET 6.
Véase también
- Algoritmo de ordenación
- Estructura de datos de búsqueda
- Treap , una forma de árbol de búsqueda binaria basada en árboles ordenados por montículo.
Referencias
- ↑ Black (ed.), Paul E. (14 de diciembre de 2004). Entrada para heap en el Diccionario de algoritmos y estructuras de datos . Versión en línea. Instituto Nacional de Estándares y Tecnología de EE. UU. , 14 de diciembre de 2004. Recuperado el 8 de octubre de 2017 de https://xlinux.nist.gov/dads/HTML/heap.html .
- ↑ CORMEN, THOMAS H. (2009). INTRODUCCIÓN A LOS ALGORITMOS . Estados Unidos de América: The MIT Press. Cambridge, Massachusetts. Londres, Inglaterra. pp. 151–152 . ISBN 978-0-262-03384-8.
- ↑ Williams, JWJ (1964), "Algoritmo 232 - Heapsort", Communications of the ACM , 7 (6): 347– 348, doi : 10.1145/512274.3734138
- ↑ La biblioteca estándar de Python, 8.4. heapq — Algoritmo de cola de montón, heapq.heappush
- ↑ La biblioteca estándar de Python, 8.4. heapq — Algoritmo de cola de montón, heapq.heappop
- ↑ La biblioteca estándar de Python, 8.4. heapq — Algoritmo de cola de montón, heapq.heapreplace
- ↑ Suchenek, Marek A. (2012), "Análisis elemental pero preciso del peor caso del programa de construcción de montones de Floyd", Fundamenta Informaticae , 120 (1), IOS Press: 75–92 , doi : 10.3233/FI-2012-751.
- 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.
- 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 .
- 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.
- ↑ 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 .
- ↑ "Montículo binomial | Brilliant Math & Science Wiki" . brilliant.org . Consultado el 30 de septiembre de 2019 .
- 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
- ↑ Okasaki, Chris (1998). "10.2. Abstracción estructural". Estructuras de datos puramente funcionales (1.ª ed.). págs. 158–162 . ISBN 9780521631242.
- ↑ Takaoka, Tadao (1999), Teoría de los montículos 2-3 (PDF) , pág. 12
- ↑ 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
- ↑ 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 .
- ↑ 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.
- ↑ 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 .
- ↑ 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 .
- ↑ 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.
- ↑ 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
- ↑ 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.
- ↑ Frederickson, Greg N. (1993), "Un algoritmo óptimo para la selección en un montículo mínimo", Information and Computation (PDF) , vol. 104, Academic Press, pp. 197–214 , doi : 10.1006/inco.1993.1030 , archivado del original (PDF) el 3 de diciembre de 2012 , consultado el 31 de octubre de 2010.
- ↑ "Boost.Heap" . www.boost.org . Consultado el 18 de julio de 2026 .
{{cite web}}: CS1 mantenimiento: estado de la URL ( enlace )
Enlaces externos
- Montón en Wolfram MathWorld
- Explicación de cómo funcionan los algoritmos básicos de montículo.
- Bentley, Jon Louis (2000). Perlas de programación (2.ª ed.). Addison Wesley. págs. 147–162 . ISBN 0201657880.
- Montones (estructuras de datos)