SplFixedArray y SplHeap en PHP: arrays de tamaño fijo y colas de prioridad

La SPL de PHP incluye estructuras de datos más especializadas para casos donde el rendimiento en memoria o el tiempo de acceso importan. SplFixedArray crea arrays de tamaño fijo que consumen significativamente menos memoria que los arrays asociativos normales de PHP. SplMinHeap, SplMaxHeap y SplPriorityQueue implementan colas de prioridad con inserción y extracción en tiempo O(log n).

SplFixedArray: arrays de tamaño fijo

Un array PHP normal es una tabla hash que gestiona memoria dinámicamente. SplFixedArray usa un array de C de tamaño fijo por debajo, lo que puede consumir hasta cuatro veces menos memoria al trabajar con grandes colecciones de enteros o valores simples.

<?php
// Array PHP normal con 1.000.000 de enteros
$array = range(0, 999999);
echo memory_get_usage(true) / 1024 / 1024; // ~32 MB

// SplFixedArray con 1.000.000 de enteros
$fixed = new SplFixedArray(1000000);
for ($i = 0; $i < 1000000; $i++) {
    $fixed[$i] = $i;
}
echo memory_get_usage(true) / 1024 / 1024; // ~8 MB (aprox 4x menos)

// Solo acepta índices enteros no negativos dentro del rango
echo $fixed[0];      // 0
echo $fixed[999999]; // 999999
// $fixed[1000000]   // RuntimeException: out of bounds

// Tamaño fijo: no se puede hacer push ni pop
echo $fixed->getSize(); // 1000000

// Convertir desde/hacia array normal
$normal = $fixed->toArray();
$nuevo  = SplFixedArray::fromArray([1, 2, 3, 4, 5]);
?>

SplMinHeap: cola de prioridad mínima

Un heap (montículo) es una estructura de árbol que garantiza que el nodo raíz siempre es el menor (min-heap) o el mayor (max-heap) de todos los elementos. La inserción y extracción son O(log n), mucho más eficientes que ordenar un array en cada operación.

<?php
$minHeap = new SplMinHeap();

$minHeap->insert(15);
$minHeap->insert(3);
$minHeap->insert(9);
$minHeap->insert(1);
$minHeap->insert(7);

// extract() devuelve y elimina el elemento más pequeño
while (!$minHeap->isEmpty()) {
    echo $minHeap->extract() . ' ';
}
// Salida: 1 3 7 9 15  (orden ascendente)

// top() devuelve el mínimo sin extraerlo
$heap = new SplMinHeap();
$heap->insert(5);
$heap->insert(2);
$heap->insert(8);
echo $heap->top(); // 2 (sin extraer)
?>

SplMaxHeap: cola de prioridad máxima

<?php
$maxHeap = new SplMaxHeap();

$maxHeap->insert(15);
$maxHeap->insert(3);
$maxHeap->insert(9);
$maxHeap->insert(1);
$maxHeap->insert(7);

while (!$maxHeap->isEmpty()) {
    echo $maxHeap->extract() . ' ';
}
// Salida: 15 9 7 3 1  (orden descendente)

// Caso práctico: obtener los 3 ficheros más grandes de un directorio
$heap = new SplMaxHeap();
foreach (new FilesystemIterator('/var/log') as $fichero) {
    if ($fichero->isFile()) {
        $heap->insert($fichero->getSize());
    }
}

$top3 = [];
for ($i = 0; $i < 3 && !$heap->isEmpty(); $i++) {
    $top3[] = $heap->extract();
}
// $top3 contiene los tres tamaños mayores
?>

SplPriorityQueue: cola con prioridad explícita

SplPriorityQueue permite asociar una prioridad numérica a cada elemento. Los elementos con mayor prioridad se extraen primero. Cuando dos elementos tienen la misma prioridad, el orden de extracción es indefinido.

<?php
$cola = new SplPriorityQueue();

// insert(dato, prioridad): mayor prioridad = sale antes
$cola->insert(['tarea' => 'enviar_email',     'urgencia' => 'baja'],  1);
$cola->insert(['tarea' => 'pago_pendiente',   'urgencia' => 'alta'],  10);
$cola->insert(['tarea' => 'generar_informe',  'urgencia' => 'media'], 5);
$cola->insert(['tarea' => 'alerta_seguridad', 'urgencia' => 'critica'], 100);

// Por defecto extract() solo devuelve el dato, no la prioridad
$cola->setExtractFlags(SplPriorityQueue::EXTR_BOTH); // devuelve ['data' => ..., 'priority' => ...]

while (!$cola->isEmpty()) {
    $item = $cola->extract();
    echo $item['data']['tarea'] . " (prioridad: {$item['priority']})n";
}
// alerta_seguridad (prioridad: 100)
// pago_pendiente   (prioridad: 10)
// generar_informe  (prioridad: 5)
// enviar_email     (prioridad: 1)
?>

La documentación oficial de SplFixedArray incluye los benchmarks de memoria, y la de SplHeap detalla cómo extender la clase para definir criterios de comparación personalizados mediante el método compare().

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP