Menu
Coddy logo textTech

Coda (queue)

Ultimo aggiornamento

Una coda ha due estremità attive. I nuovi valori entrano dal fondo ed escono dalla testa, quindi chi ha aspettato più a lungo viene servito per primo. Questo è il FIFO, ed è esattamente come funziona una fila allo sportello: mettersi in fondo ed essere serviti dalla testa è ciò che rende l'attesa equa. Premi Play qui sopra e guarda i valori entrare da un lato e uscire dall'altro.

Dato che ogni estremità è tracciata da un suo indice o puntatore, entrambe le operazioni sono O(1) e nessuna delle due sposta il resto dei dati. Per questo le code stanno sotto tutto ciò che elabora il lavoro in ordine di arrivo: lavori di stampa, code di task e di messaggi, buffer delle richieste e la visita in ampiezza, che visita un grafo livello per livello proprio perché tiene la sua frontiera in una coda. Sposta l'estremità di rimozione in fondo e ottieni invece una pila.

Complessità temporale e spaziale

Per una coda basata su un buffer circolare o su una lista concatenata, le due implementazioni standard:

OperazioneComplessitàNote
EnqueueO(1)Scrivi in fondo e fai avanzare l'indice di fondo.
DequeueO(1)Leggi in testa e fai avanzare l'indice di testa, senza spostamenti.
Peek (testa)O(1)Leggi il valore in testa senza rimuoverlo.
RicercaO(n)Non è lo scopo di una coda: per guardarci dentro devi svuotarla.
SpazioO(n)Una posizione per ogni valore in attesa.

Passo dopo passo

PassoCosa succede
1La coda parte vuota, con testa e fondo che puntano alla stessa posizione.
2Enqueue scrive il valore in fondo, poi fa avanzare il fondo di uno.
3Ogni enqueue successivo finisce dietro i valori già in attesa.
4Dequeue legge il valore in testa, poi fa avanzare la testa di uno.
5Il valore restituito è sempre quello che ha aspettato più a lungo.
6Quando la testa raggiunge il fondo la coda è di nuovo vuota, e un ulteriore dequeue è un errore.

Esempio svolto

Enqueue di 3, 7, 5 e poi svuotamento della coda:

OperazioneCoda (dalla testa al fondo)Restituisce
enqueue(3)[3]niente
enqueue(7)[3, 7]niente
enqueue(5)[3, 7, 5]niente
dequeue()[7, 5]3, il valore più vecchio
dequeue()[5]7
dequeue()[]5, il valore più recente, per ultimo

Quando usare una coda

Usala quandoEvitala quando
Il lavoro va gestito in ordine di arrivo: code di lavori, buffer delle richieste, spooler di stampaTi serve prima l'elemento più recente, cioè una pila
Stai esplorando livello per livello, come fa la visita in ampiezzaGli elementi vanno serviti per priorità e non per arrivo, e lì è adatto un heap
Un produttore e un consumatore vanno a velocità diverse e serve un buffer tra loroTi serve cercare o accedere per indice al centro dei dati
Vuoi inserimento e rimozione O(1) senza spostare elementiLa implementeresti spostando un array a ogni dequeue, cosa che la rende O(n)

Codice Queue

Un'implementazione di Queue pulita ed eseguibile in Python, JavaScript, Java, C++, C. Scegli un linguaggio, copia il codice o aprilo già caricato nel Playground di Coddy.

Codice Queue in Python

Python
1from collections import deque2
3queue = deque()4
5# Enqueue three values at the rear6for value in [3, 7, 5]:7    queue.append(value)8    print(f"enqueue {value} -> {list(queue)}")9
10# Dequeue them from the front: first in, first out11while queue:12    value = queue.popleft()13    print(f"dequeue {value} -> {list(queue)}")14
15print("empty:", len(queue) == 0)
Esegui questo codice nel playground Python

Domande frequenti sulla coda

Cosa significa FIFO?
First in, first out, cioè il primo che entra è il primo che esce: il valore che ha aspettato più a lungo è il prossimo a essere servito. Una fila alla biglietteria è l'immagine quotidiana. Una pila segue la regola opposta, LIFO.
Qual è la differenza tra una coda e una pila?
Solo l'estremità da cui rimuovi. Entrambe aggiungono in fondo in O(1); una coda rimuove dalla testa (FIFO), una pila rimuove dalla stessa estremità in cui ha aggiunto (LIFO). Per il resto le loro tabelle di complessità sono identiche.
Quali sono le operazioni principali di una coda?
enqueue aggiunge un valore in fondo, dequeue rimuove e restituisce il valore in testa, peek (o front) legge la testa senza rimuoverla e is_empty indica se c'è qualcosa in attesa. Tutte e quattro sono O(1).
Perché il dequeue è lento se uso un semplice array?
Perché rimuovere l'indice 0 da un array sposta a sinistra tutti gli elementi rimasti, rendendo ogni dequeue O(n). Le implementazioni reali lo evitano con un buffer circolare che fa avanzare un indice di testa, o con una lista concatenata con un puntatore alla testa. collections.deque di Python e ArrayDeque di Java lo fanno per te, mentre list.pop(0) no.
Cos'è una coda circolare?
Una coda in un array di dimensione fissa in cui gli indici di testa e di fondo tornano a 0 quando superano la fine. Riusa le posizioni liberate dai dequeue, così una coda di capacità n continua a funzionare all'infinito invece di uscire dalla fine dell'array.
Dove si usano le code nei programmi reali?
Code di task e di messaggi tra servizi, spooler di stampa e di lavori, buffer delle richieste nei web server, buffer della tastiera e degli eventi, pipeline produttore-consumatore e la visita in ampiezza, dove è la coda a far procedere la visita livello per livello.
Illustrazione dei linguaggi di programmazione di Coddy

Padroneggia gli algoritmi con Coddy

INIZIA