Montículo y cola de prioridad
Un árbol guardado en un array en el que cada padre es menor (o mayor) que sus hijos: el mínimo está siempre en la raíz y meter o sacar cuesta O(log n). Es la cola de prioridad de PriorityQueue.
Visualízalo paso a paso
Cambia los datos, dale a reproducir y sigue cada paso en el dibujo, en la línea de Java que se ejecuta y en sus variables.
Montículo de mínimos
Escribe las operaciones (meter x o sacar) y mira cómo el nuevo sube hasta su sitio y cómo, al sacar el mínimo, el último baja desde la raíz.
- fuera de juego
Paso 1
Un montículo de mínimos vacío: cada padre será menor o igual que sus hijos, así que el mínimo estará siempre en la raíz, a[0].
1class MonticuloMin {
2 private int[] a = new int[16];
3 private int n = 0;
4
5 void meter(int x) {
6 a[n] = x;
7 int i = n++;
8 while (i > 0 && a[(i - 1) / 2] > a[i]) {
9 int p = (i - 1) / 2;
10 int t = a[i]; a[i] = a[p]; a[p] = t;
11 i = p;
12 }
13 }
14
15 int sacar() {
16 int min = a[0];
17 a[0] = a[--n];
18 int i = 0;
19 while (true) {
20 int menor = i, izq = 2 * i + 1, der = 2 * i + 2;
21 if (izq < n && a[izq] < a[menor]) menor = izq;
22 if (der < n && a[der] < a[menor]) menor = der;
23 if (menor == i) return min;
24 int t = a[i]; a[i] = a[menor]; a[menor] = t;
25 i = menor;
26 }
27 }
28}Variables
- n
- 0
- mínimo
- —
- sacados
- —
Atajos con el foco dentro del visualizador: ← → paso a paso, Espacio reproducir o pausar, Inicio/Fin ir al principio o al final.
La idea
Una cola de prioridad es una cola en la que no sale el que llegó primero, sino el más importante: el paciente más grave, la tarea más urgente, el proceso con más prioridad, el camino más corto encontrado hasta ahora. Hacerla con una lista ordenada cuesta O(n) al meter; con una desordenada, O(n) al sacar. El montículo hace las dos cosas en O(log n).
Un montículo de mínimos es un árbol binario casi completo (todos los niveles llenos salvo el último, que se llena de izquierda a derecha) en el que cada padre es menor o igual que sus hijos. No tiene por qué estar ordenado: solo garantiza que, en cualquier camino de la raíz hacia abajo, los valores crecen. Por eso el mínimo está siempre en la raíz.
Al ser casi completo, se guarda en un array sin referencias: la raíz en la posición 0 y los hijos de la posición i en 2i + 1 y 2i + 2. Para meter un elemento se pone al final y se «sube» intercambiándolo con su padre mientras sea menor que él. Para sacar el mínimo se pone el último en la raíz y se «hunde» intercambiándolo con su hijo menor mientras sea mayor que él. Las dos cosas recorren como mucho la altura del árbol, log₂ n.
Un montículo de máximos es lo mismo con la comparación al revés. Con él se ordena un array en O(n log n) (heapsort) y con dos montículos se mantiene la mediana de un flujo de datos.
Cuándo usarlo
- Sacar una y otra vez el mínimo o el máximo de una colección que cambia: tareas por prioridad, eventos por hora en una simulación.
- Algoritmos de grafos: Dijkstra y Prim sacan en cada paso el nodo más cercano.
- Los k mayores (o menores) de muchos datos, o de un flujo que no cabe en memoria: un montículo de tamaño k.
- Mezclar k listas ordenadas: el montículo guarda el primero de cada una.
Cuándo no
- Si hay que buscar un elemento cualquiera o recorrerlos en orden: el montículo solo da el mínimo; para el resto, un árbol (
TreeSet). - Si solo se saca el mínimo una vez: basta con un recorrido O(n).
Paso a paso
- El array como árbol. Raíz en
a[0]; hijos deien2i + 1y2i + 2; padre deien(i − 1) / 2. - Meter (subir). Se pone en
a[n]y, mientras su padre sea mayor, se intercambian. O(log n). - Consultar el mínimo. Es
a[0], O(1). - Sacar el mínimo (hundir). Se guarda
a[0], se pone el último en la raíz y, mientras alguno de sus hijos sea menor, se intercambia con el menor de los dos. O(log n).
El código
Una cola de prioridad de tareas
Un montículo de mínimos por prioridad: siempre sale la tarea más urgente, aunque haya llegado la última.
1import java.util.Arrays;
2
3public class Main {
4 record Tarea(int prioridad, String nombre) { }
5
6 /** Cola de prioridad de tareas: un montículo de mínimos por prioridad (1 = la más urgente). */
7 static class ColaPrioridad {
8 private Tarea[] a = new Tarea[4];
9 private int n = 0;
10
11 void meter(Tarea t) {
12 if (n == a.length) a = Arrays.copyOf(a, 2 * n);
13 a[n] = t;
14 int i = n++;
15 while (i > 0 && a[(i - 1) / 2].prioridad() > a[i].prioridad()) { // sube mientras su padre sea mayor
16 int p = (i - 1) / 2;
17 Tarea x = a[i]; a[i] = a[p]; a[p] = x;
18 i = p;
19 }
20 }
21
22 Tarea sacar() {
23 Tarea min = a[0];
24 a[0] = a[--n]; // el último pasa a la raíz…
25 a[n] = null;
26 int i = 0;
27 while (true) { // …y baja hasta su sitio
28 int menor = i, izq = 2 * i + 1, der = 2 * i + 2;
29 if (izq < n && a[izq].prioridad() < a[menor].prioridad()) menor = izq;
30 if (der < n && a[der].prioridad() < a[menor].prioridad()) menor = der;
31 if (menor == i) return min;
32 Tarea x = a[i]; a[i] = a[menor]; a[menor] = x;
33 i = menor;
34 }
35 }
36
37 boolean vacia() { return n == 0; }
38 }
39
40 public static void main(String[] args) {
41 ColaPrioridad cola = new ColaPrioridad();
42 cola.meter(new Tarea(3, "responder correos"));
43 cola.meter(new Tarea(1, "arreglar el servidor caído"));
44 cola.meter(new Tarea(4, "ordenar el escritorio"));
45 cola.meter(new Tarea(2, "preparar la reunión"));
46 System.out.println("Ahora: " + cola.sacar().nombre());
47 cola.meter(new Tarea(0, "llamar al cliente enfadado"));
48 while (!cola.vacia()) {
49 Tarea t = cola.sacar();
50 System.out.println("Después: " + t.nombre() + " (prioridad " + t.prioridad() + ")");
51 }
52 }
53}from dataclasses import dataclass
@dataclass
class Tarea:
prioridad: int
nombre: str
class ColaPrioridad:
"""Cola de prioridad de tareas: un montículo de mínimos por prioridad (1 = la más urgente)."""
def __init__(self):
self._a = []
def meter(self, t):
a = self._a
a.append(t)
i = len(a) - 1
while i > 0 and a[(i - 1) // 2].prioridad > a[i].prioridad: # sube mientras su padre sea mayor
p = (i - 1) // 2
a[i], a[p] = a[p], a[i]
i = p
def sacar(self):
a = self._a
minimo = a[0]
ultimo = a.pop() # el último pasa a la raíz…
if a:
a[0] = ultimo
i, n = 0, len(a)
while True: # …y baja hasta su sitio
menor, izq, der = i, 2 * i + 1, 2 * i + 2
if izq < n and a[izq].prioridad < a[menor].prioridad:
menor = izq
if der < n and a[der].prioridad < a[menor].prioridad:
menor = der
if menor == i:
break
a[i], a[menor] = a[menor], a[i]
i = menor
return minimo
def vacia(self):
return not self._a
cola = ColaPrioridad()
cola.meter(Tarea(3, "responder correos"))
cola.meter(Tarea(1, "arreglar el servidor caído"))
cola.meter(Tarea(4, "ordenar el escritorio"))
cola.meter(Tarea(2, "preparar la reunión"))
print("Ahora:", cola.sacar().nombre)
cola.meter(Tarea(0, "llamar al cliente enfadado"))
while not cola.vacia():
t = cola.sacar()
print(f"Después: {t.nombre} (prioridad {t.prioridad})")/** Cola de prioridad de tareas: un montículo de mínimos por prioridad (1 = la más urgente). */
class ColaPrioridad {
#a = [];
meter(t) {
const a = this.#a;
a.push(t);
let i = a.length - 1;
while (i > 0 && a[(i - 1) >> 1].prioridad > a[i].prioridad) { // sube mientras su padre sea mayor
const p = (i - 1) >> 1;
[a[i], a[p]] = [a[p], a[i]];
i = p;
}
}
sacar() {
const a = this.#a;
const min = a[0];
const ultimo = a.pop(); // el último pasa a la raíz…
if (a.length) {
a[0] = ultimo;
let i = 0;
while (true) { // …y baja hasta su sitio
let menor = i;
const izq = 2 * i + 1, der = 2 * i + 2;
if (izq < a.length && a[izq].prioridad < a[menor].prioridad) menor = izq;
if (der < a.length && a[der].prioridad < a[menor].prioridad) menor = der;
if (menor === i) break;
[a[i], a[menor]] = [a[menor], a[i]];
i = menor;
}
}
return min;
}
vacia() { return this.#a.length === 0; }
}
const cola = new ColaPrioridad();
cola.meter({ prioridad: 3, nombre: "responder correos" });
cola.meter({ prioridad: 1, nombre: "arreglar el servidor caído" });
cola.meter({ prioridad: 4, nombre: "ordenar el escritorio" });
cola.meter({ prioridad: 2, nombre: "preparar la reunión" });
console.log("Ahora: " + cola.sacar().nombre);
cola.meter({ prioridad: 0, nombre: "llamar al cliente enfadado" });
while (!cola.vacia()) {
const t = cola.sacar();
console.log(`Después: ${t.nombre} (prioridad ${t.prioridad})`);
}using System;
record Tarea(int Prioridad, string Nombre);
// Cola de prioridad de tareas: un montículo de mínimos por prioridad (1 = la más urgente).
class ColaPrioridad {
private Tarea[] a = new Tarea[4];
private int n = 0;
public void Meter(Tarea t) {
if (n == a.Length) Array.Resize(ref a, 2 * n);
a[n] = t;
int i = n++;
while (i > 0 && a[(i - 1) / 2].Prioridad > a[i].Prioridad) { // sube mientras su padre sea mayor
int p = (i - 1) / 2;
(a[i], a[p]) = (a[p], a[i]);
i = p;
}
}
public Tarea Sacar() {
Tarea min = a[0];
a[0] = a[--n]; // el último pasa a la raíz…
int i = 0;
while (true) { // …y baja hasta su sitio
int menor = i, izq = 2 * i + 1, der = 2 * i + 2;
if (izq < n && a[izq].Prioridad < a[menor].Prioridad) menor = izq;
if (der < n && a[der].Prioridad < a[menor].Prioridad) menor = der;
if (menor == i) return min;
(a[i], a[menor]) = (a[menor], a[i]);
i = menor;
}
}
public bool Vacia => n == 0;
}
class Program {
static void Main() {
var cola = new ColaPrioridad();
cola.Meter(new Tarea(3, "responder correos"));
cola.Meter(new Tarea(1, "arreglar el servidor caído"));
cola.Meter(new Tarea(4, "ordenar el escritorio"));
cola.Meter(new Tarea(2, "preparar la reunión"));
Console.WriteLine("Ahora: " + cola.Sacar().Nombre);
cola.Meter(new Tarea(0, "llamar al cliente enfadado"));
while (!cola.Vacia) {
var t = cola.Sacar();
Console.WriteLine(quot;Después: {t.Nombre} (prioridad {t.Prioridad})");
}
}
}<?php
/** Cola de prioridad de tareas: un montículo de mínimos por prioridad (1 = la más urgente). */
class ColaPrioridad {
private array $a = [];
public function meter(int $prioridad, string $nombre): void {
$a = &$this->a;
$a[] = [$prioridad, $nombre];
$i = count($a) - 1;
while ($i > 0 && $a[intdiv($i - 1, 2)][0] > $a[$i][0]) { // sube mientras su padre sea mayor
$p = intdiv($i - 1, 2);
[$a[$i], $a[$p]] = [$a[$p], $a[$i]];
$i = $p;
}
}
public function sacar(): array {
$a = &$this->a;
$min = $a[0];
$ultimo = array_pop($a); // el último pasa a la raíz…
if ($a) {
$a[0] = $ultimo;
$i = 0;
$n = count($a);
while (true) { // …y baja hasta su sitio
$menor = $i;
$izq = 2 * $i + 1;
$der = 2 * $i + 2;
if ($izq < $n && $a[$izq][0] < $a[$menor][0]) $menor = $izq;
if ($der < $n && $a[$der][0] < $a[$menor][0]) $menor = $der;
if ($menor === $i) break;
[$a[$i], $a[$menor]] = [$a[$menor], $a[$i]];
$i = $menor;
}
}
return $min;
}
public function vacia(): bool { return !$this->a; }
}
$cola = new ColaPrioridad();
$cola->meter(3, "responder correos");
$cola->meter(1, "arreglar el servidor caído");
$cola->meter(4, "ordenar el escritorio");
$cola->meter(2, "preparar la reunión");
echo "Ahora: " . $cola->sacar()[1] . "\n";
$cola->meter(0, "llamar al cliente enfadado");
while (!$cola->vacia()) {
[$prioridad, $nombre] = $cola->sacar();
echo "Después: $nombre (prioridad $prioridad)\n";
}Salida al ejecutarlo (la misma en los 5 lenguajes)
Ahora: arreglar el servidor caído Después: llamar al cliente enfadado (prioridad 0) Después: preparar la reunión (prioridad 2) Después: responder correos (prioridad 3) Después: ordenar el escritorio (prioridad 4)
Los k mayores de un flujo
Un montículo de mínimos de tamaño k guarda los k mayores vistos; su raíz es el listón que hay que superar para entrar.
1/** Los k mayores de un flujo de datos sin guardarlos todos: un montículo de MÍNIMOS de tamaño k.
2 Su raíz es el menor de los k mayores vistos; un número nuevo solo entra si es mayor que ella. */
3static List<Integer> kMayores(Iterable<Integer> datos, int k) {
4 PriorityQueue<Integer> mejores = new PriorityQueue<>();
5 for (int x : datos) {
6 if (mejores.size() < k) mejores.offer(x);
7 else if (x > mejores.peek()) {
8 mejores.poll(); // sale el menor de los k
9 mejores.offer(x);
10 }
11 }
12 List<Integer> r = new ArrayList<>(mejores);
13 r.sort(Comparator.reverseOrder());
14 return r; // O(n log k) en tiempo y O(k) en memoria
15}import heapq
def k_mayores(datos, k):
"""Los k mayores de un flujo sin guardarlos todos: un montículo de MÍNIMOS de tamaño k.
Su raíz es el menor de los k mayores vistos; un número nuevo solo entra si es mayor que ella."""
mejores = []
for x in datos:
if len(mejores) < k:
heapq.heappush(mejores, x)
elif x > mejores[0]:
heapq.heapreplace(mejores, x) # sale el menor de los k y entra x
return sorted(mejores, reverse=True) # O(n log k) en tiempo y O(k) en memoria
# La biblioteca ya lo trae: heapq.nlargest(k, datos)/** Los k mayores de un flujo sin guardarlos todos. Sin montículo en la biblioteca, se puede usar
un array ordenado de tamaño k (O(n·k)) o el MonticuloMin del ejemplo de arriba (O(n log k)). */
function kMayores(datos, k) {
const mejores = []; // de menor a mayor; mejores[0] es el listón
for (const x of datos) {
if (mejores.length < k || x > mejores[0]) {
if (mejores.length === k) mejores.shift();
let i = mejores.findIndex((y) => y > x);
if (i < 0) i = mejores.length;
mejores.splice(i, 0, x);
}
}
return mejores.reverse();
}// Los k mayores de un flujo sin guardarlos todos: un montículo de MÍNIMOS de tamaño k.
// Su raíz es el menor de los k mayores vistos; un número nuevo solo entra si es mayor que ella.
static List<int> KMayores(IEnumerable<int> datos, int k) {
var mejores = new PriorityQueue<int, int>();
foreach (int x in datos) {
if (mejores.Count < k) mejores.Enqueue(x, x);
else if (x > mejores.Peek()) mejores.EnqueueDequeue(x, x); // entra x y sale el menor
}
var r = new List<int>();
while (mejores.Count > 0) r.Add(mejores.Dequeue());
r.Reverse();
return r; // O(n log k) en tiempo y O(k) en memoria
}/** Los k mayores de un flujo sin guardarlos todos: un montículo de MÍNIMOS de tamaño $k.
Su raíz es el menor de los k mayores vistos; un número nuevo solo entra si es mayor que ella. */
function kMayores(iterable $datos, int $k): array {
$mejores = new SplMinHeap();
foreach ($datos as $x) {
if (count($mejores) < $k) $mejores->insert($x);
elseif ($x > $mejores->top()) {
$mejores->extract(); // sale el menor de los k
$mejores->insert($x);
}
}
return array_reverse(iterator_to_array($mejores, false)); // O(n log k), O(k) de memoria
}Traza: un montículo de mínimos
| Operación | Array | Mínimo (raíz) |
|---|---|---|
| meter 5 | [5] | 5 |
| meter 3 | [3, 5] | 3 |
| meter 8 | [3, 5, 8] | 3 |
| meter 1 | [1, 3, 8, 5] | 1 |
| meter 9 | [1, 3, 8, 5, 9] | 1 |
| meter 2 | [1, 3, 2, 5, 9, 8] | 1 |
| sacar → 1 | [2, 3, 8, 5, 9] | 2 |
| meter 4 | [2, 3, 4, 5, 9, 8] | 2 |
| sacar → 2 | [3, 5, 4, 8, 9] | 3 |
El array no está ordenado (5 y 8 aparecen después de 9 o 2), pero la raíz es siempre el mínimo.
Complejidad
| Operación | Montículo | Lista ordenada | Lista desordenada |
|---|---|---|---|
| Meter | O(log n) | O(n) | O(1) |
| Consultar el mínimo | O(1) | O(1) | O(n) |
| Sacar el mínimo | O(log n) | O(1) | O(n) |
| Construir con n datos | O(n) | O(n log n) | O(n) |
Memoria: O(n), en un simple array. Es la estructura equilibrada para meter y sacar mezclados.
- Mejor caso: O(1)
- Caso medio: O(log n)
- Peor caso: O(log n)
Consultar el mínimo es O(1); meter y sacar, O(log n): como mucho recorren la altura del árbol. Las curvas grises son las demás clases, para comparar.
En la práctica
PriorityQueueen Java,heapqen Python,PriorityQueue<T, P>en .NET ySplPriorityQueueen PHP.- El algoritmo de Dijkstra (rutas de un GPS) usa una cola de prioridad con las distancias provisionales.
- Los planificadores de procesos por prioridad, los temporizadores de un sistema operativo y las colas de eventos de los motores de juegos y simulaciones.
- La compresión de Huffman (ZIP, JPEG) construye su árbol sacando una y otra vez los dos símbolos menos frecuentes.
Errores típicos
- Esperar que el array de un montículo esté ordenado, o recorrer una
PriorityQueuecon un for-each esperando el orden: solopoll()saca en orden. - Usar las fórmulas de los hijos de un array que empieza en 1 (
2iy2i + 1) con uno que empieza en 0. - Al hundir, intercambiar con el primer hijo menor que se encuentra en vez de con el menor de los dos: el montículo se rompe.
- Cambiar la prioridad de un elemento que ya está dentro: el montículo no se entera. Hay que sacarlo y volver a meterlo.
- Olvidar que
PriorityQueuees de mínimos: para máximos hace faltaComparator.reverseOrder().
Ejercicios
Cada ejercicio se corrige solo con sus pruebas (algunas ocultas). Escribe tu solución en el editor y pulsa Ejecutar o Comprobar; la solución explicada está debajo, por si te atascas.
1. Urgencias
Simula la sala de espera de urgencias. Las órdenes llegan una por línea: llega nombre gravedad (de 1 a 5, 5 es lo más grave) y atender. Se atiende siempre al más grave y, con la misma gravedad, al que llegó antes. El main ya lee las órdenes y usa la cola: completa nuevaCola para que la PriorityQueue tenga ese orden.
- Órdenes:
llega Ana 3,atender. atenderescribeAtiende a Luis (gravedad 5)oNo hay nadie esperando; al final,Quedan esperando: N.- Otra orden:
Orden no válida: «…».
Ejemplo
llega Ana 2 llega Luis 5 llega Eva 3 atender atender llega Pablo 4 atender atender
Atiende a Luis (gravedad 5) Atiende a Eva (gravedad 3) Atiende a Pablo (gravedad 4) Atiende a Ana (gravedad 2) Quedan esperando: 0
Ver la solución explicada
1import java.util.*;
2
3public class Main {
4 record Paciente(String nombre, int gravedad, int llegada) { }
5
6 /** Primero el más grave (5 es lo más grave); con la misma gravedad, el que llegó antes. */
7 static final Comparator<Paciente> ORDEN = Comparator.comparingInt(Paciente::gravedad).reversed()
8 .thenComparingInt(Paciente::llegada);
9
10 static PriorityQueue<Paciente> nuevaCola() {
11 return new PriorityQueue<>(ORDEN);
12 }
13
14 public static void main(String[] args) {
15 Scanner sc = new Scanner(System.in);
16 PriorityQueue<Paciente> cola = nuevaCola();
17 int llegada = 0;
18 while (sc.hasNextLine()) {
19 String linea = sc.nextLine().trim();
20 if (linea.isEmpty()) continue;
21 String[] p = linea.split("\\s+");
22 if (p.length == 3 && p[0].equals("llega") && p[2].matches("[1-5]")) {
23 cola.offer(new Paciente(p[1], Integer.parseInt(p[2]), llegada++));
24 } else if (linea.equals("atender")) {
25 Paciente x = cola.poll();
26 System.out.println(x == null ? "No hay nadie esperando" : "Atiende a " + x.nombre() + " (gravedad " + x.gravedad() + ")");
27 } else System.out.println("Orden no válida: «" + linea + "»");
28 }
29 System.out.println("Quedan esperando: " + cola.size());
30 }
31}Un montículo no es estable: con la misma prioridad no garantiza el orden de llegada. Por eso se añade el número de llegada como segundo criterio del comparador.
Cada llegada y cada atención cuestan O(log n), tenga la sala 10 o 10.000 pacientes.
2. La mediana mientras llegan los datos
Llegan números de uno en uno y, después de cada uno, hay que dar la mediana de todos los recibidos, sin ordenarlos cada vez. El truco son dos montículos: uno de máximos con la mitad menor y otro de mínimos con la mitad mayor; la mediana está en sus raíces. Completa meter y mediana.
- Entrada: números enteros separados por espacios o saltos de línea.
- Salida, tras cada número:
5 → mediana 5, o con una cantidad par8 → mediana entre 5 y 8. - Errores:
Número no válido: «x»(se salta) yNo hay números.
Ejemplo
5 15 1 3 8
5 → mediana 5 15 → mediana entre 5 y 15 1 → mediana 5 3 → mediana entre 3 y 5 8 → mediana 5
Ver la solución explicada
1import java.util.*;
2
3public class Main {
4 // la mitad menor (montículo de máximos) y la mitad mayor (montículo de mínimos)
5 static final PriorityQueue<Integer> menores = new PriorityQueue<>(Comparator.reverseOrder());
6 static final PriorityQueue<Integer> mayores = new PriorityQueue<>();
7
8 /** Mete x en su mitad y reequilibra: menores puede tener como mucho uno más que mayores. */
9 static void meter(int x) {
10 if (menores.isEmpty() || x <= menores.peek()) menores.offer(x);
11 else mayores.offer(x);
12 if (menores.size() > mayores.size() + 1) mayores.offer(menores.poll());
13 else if (mayores.size() > menores.size()) menores.offer(mayores.poll());
14 }
15
16 /** La mediana con lo que hay: el del medio o, con un número par, los dos del medio. */
17 static String mediana() {
18 if (menores.size() > mayores.size()) return String.valueOf(menores.peek());
19 return "entre " + menores.peek() + " y " + mayores.peek();
20 }
21
22 public static void main(String[] args) {
23 Scanner sc = new Scanner(System.in);
24 int n = 0;
25 while (sc.hasNext()) {
26 String t = sc.next();
27 if (!t.matches("-?\\d{1,6}")) {
28 System.out.println("Número no válido: «" + t + "»");
29 continue;
30 }
31 meter(Integer.parseInt(t));
32 n++;
33 System.out.println(t + " → mediana " + mediana());
34 }
35 if (n == 0) System.out.println("No hay números");
36 }
37}Las dos raíces son justo los elementos del centro: el mayor de la mitad menor y el menor de la mitad mayor. No hace falta saber nada del resto.
Cada número cuesta O(log n); reordenar todo en cada paso costaría O(n log n) por número.
Test
Test: Montículo y cola de prioridad
0/5 respondidas · 0 aciertosElige una respuesta en cada pregunta: verás al momento si es correcta y por qué. Con un 80 % de aciertos se da por superada.
1.En un montículo de mínimos, ¿dónde está el mínimo?
2.¿Cuánto cuesta meter un elemento en un montículo de n elementos?
3.¿Qué devuelve recorrer una PriorityQueue de Java con un for-each?
4.¿Cómo se crea en Java una cola de prioridad que saque primero el mayor?
5.¿Qué algoritmo de grafos necesita una cola de prioridad?