edubun
Italiano

Scegliere una struttura dati

Tra 1023 chiavi, una ricerca lineare di una chiave assente fa 1023 confronti, la ricerca binaria ne fa 10, e una tabella hash con 1023 bucket ne ha fatti al massimo 6 nel laboratorio.

Parti dalle domande che farai

Nessuna struttura è la migliore in tutto. Ognuna rende economiche alcune operazioni rendendone costose altre, quindi per scegliere bisogna elencare che cosa farà più spesso il tuo programma. Il corso 6.006 del MIT divide le possibilità in due interfacce. Una sequenza tiene gli elementi in un ordine deciso da te (primo, secondo, terzo), e chiedi gli elementi per posizione. Un insieme (set) tiene gli elementi per chiave, e chiedi se una chiave c'è, oppure la chiave più piccola, oppure quella che segue una chiave data. Un insieme senza le domande sull'ordine si chiama dizionario.

Alcune situazioni comuni e la risposta di solito giusta:

  • Leggere elementi per posizione, aggiungere in fondo: un array dinamico (un array JavaScript).
  • Cronologia di Annulla, parentesi bilanciate, visita in profondità: una pila, cioè un array usato solo alla fine.
  • Lavori gestiti in ordine di arrivo, visita in ampiezza: una coda, con un indice di testa o un buffer circolare invece di shift su un array lungo.
  • Cercare cose per nome o id: una tabella hash, che in JavaScript vuol dire Map o Set.
  • Tenere le chiavi ordinate mentre inserisci ed elimini, chiedere la chiave successiva: un albero binario di ricerca bilanciato.
  • Molti inserimenti ed eliminazioni in un punto che hai già in mano: una lista concatenata.

La stessa ricerca in cinque strutture

Il laboratorio qui sotto memorizza le stesse chiavi in cinque modi e conta i confronti necessari per trovarne una. Le chiavi sono 15, 127 o 1023 numeri interi casuali. L'array non ordinato usa la ricerca lineare. L'array ordinato usa la ricerca binaria. L'albero bilanciato è stato costruito inserendo prima le chiavi centrali, quindi è il più basso possibile. L'altro albero è stato costruito dalle chiavi in ordine crescente, quindi è una catena. La tabella hash ha tanti bucket quante chiavi e conta 1 per il calcolo di h(k).

Caricamento

Trascina per ruotare. Scorri o avvicina le dita per lo zoom.

Confronti necessari per trovare una chiave in cinque strutture che contengono le stesse chiavi. Le barre mostrano la chiave scelta; la linea tratteggiata è la media su tutte le chiavi memorizzate. La tabella sotto la figura dà la media e il caso peggiore.

Con 15 chiavi le differenze sono piccole: la ricerca lineare richiede in media 8 confronti e la ricerca binaria circa 3.3. Con 1023 chiavi non lo sono. La ricerca lineare ne richiede in media 512 e 1023 per una chiave assente, mentre la ricerca binaria e l'albero bilanciato non ne richiedono mai più di 10. L'albero a catena è cattivo quanto la ricerca lineare. La tabella hash resta in media tra 2.3 e 2.5 a ogni dimensione perché le sue catene restano corte, e in questo laboratorio il suo caso peggiore per 1023 chiavi è stato 6. Ecco perché Map è la scelta predefinita per le ricerche, e perché le strutture ordinate valgono la pena solo quando ti serve anche l'ordine.

Per posizionePrendere l'elemento iInserire o eliminare in testa
Array dinamico1n
Lista concatenatan1
Array ordinato1n
Per chiaveTrovareInserireChiave successiva
Array o listannn
Array ordinatolog nnlog n
Tabella hash1 in media1 in median
ABR bilanciatolog nlog nlog n

Ogni cella di queste due tabelle è la velocità di crescita del costo per n elementi, secondo le tabelle degli appunti delle lezioni 2, 4 e 7 del MIT. Tabelle hash e alberi di ricerca compaiono solo nella seconda tabella perché lavorano per chiave, non per posizione. In un array non ordinato o in una lista, inserire una chiave costa n perché prima devi controllare che non ci sia già. L'array ordinato trova in fretta ma deve spostare valori per fare spazio a una nuova chiave.

Map od oggetto?

I programmi JavaScript usano spesso un oggetto semplice come dizionario, scrivendo prices["apple"]. MDN elenca alcuni motivi per preferire Map quando le chiavi vengono dai dati: un oggetto ha un prototipo, quindi contiene chiavi predefinite che potrebbero scontrarsi con le tue; una Map può usare qualsiasi valore come chiave, non solo stringhe e simboli; la sua dimensione è una sola proprietà, map.size; e viene percorsa nell'ordine di inserimento. Gli oggetti restano la scelta naturale per record con un insieme fisso di campi con nome.

  • 1953: Il memorandum IBM di H. P. Luhn propone l'hashing in bucket con concatenamento.
  • Intorno al 1956: L'IPL di Newell, Shaw e Simon introduce le liste concatenate.
  • 1957: Bauer e Samelson chiedono un brevetto per il metodo della pila; il Fortran esce con gli array.
  • 1962: Adelson-Velsky e Landis pubblicano l'albero AVL, il primo albero di ricerca bilanciato.
  • 2015: ECMAScript 2015 aggiunge Map e Set a JavaScript.
  1. Una ricerca lineare di una chiave assente tra 1023 chiavi fa quanti confronti?
  2. La ricerca binaria tra 1023 chiavi ordinate fa al massimo quanti confronti?
  3. Ricerca lineare su 15 chiavi: qual è il numero medio di confronti su tutte le 15 chiavi?
  4. Un ABR costruito da 127 chiavi inserite in ordine crescente: quanti confronti per la chiave più grande?
  5. Un editor di testo ha bisogno di Annulla. Quale struttura è adatta?
    • Coda
    • Pila
    • Tabella hash
    • Array ordinato
  6. Un server di stampa deve gestire i lavori nell'ordine in cui arrivano. Quale struttura è adatta?
    • Coda
    • Pila
    • ABR
    • Lista concatenata usata come pila
  7. Devi cercare il record di un utente in base al suo id molte volte al secondo. Qual è la scelta abituale in JavaScript?
    • Un array percorso con un ciclo
    • Una Map con chiave id
    • Una pila
    • Una lista concatenata
  8. Ti servono chiavi tenute in ordine crescente mentre inserisci ed elimini, e chiedi spesso la chiave successiva più grande. Che cosa è più adatto?
    • Tabella hash
    • ABR bilanciato
    • Coda
    • Array non ordinato
  9. Nei termini di MIT 6.006, un insieme senza le operazioni d'ordine si chiama
    • una sequenza
    • un dizionario
    • una pila
    • una coda
  10. Secondo MDN, perché un oggetto semplice può essere rischioso come dizionario per chiavi che vengono dai dati?
    • Gli oggetti non possono contenere stringhe
    • Il suo prototipo porta chiavi predefinite che possono scontrarsi con le tue
    • Gli oggetti sono sempre più lenti degli array
    • Gli oggetti dimenticano i valori dopo un secondo
Punti chiave
  • Scegli in base alle operazioni che farai più spesso.
  • Sequenza: array, lista concatenata, pila, coda. Insieme: tabella hash, ABR.
  • Con 1023 chiavi: ricerca lineare fino a 1023 confronti, ricerca binaria e albero bilanciato fino a 10.
  • Map è il dizionario abituale in JavaScript; usa un albero bilanciato quando ti serve anche l'ordine.
Fonti di questo corso (11)
  • MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon)
  • lecture notes 2 Data Structures (interface vs data structure, Sequence and Set interfaces, stack = insert_last/delete_last, queue = insert_last/delete_first, array, linked list, dynamic array, amortized Θ(1) append)
  • 4 Hashing (chaining, pigeonhole collisions, chain length n/m)
  • 6 Binary Trees Part 1 (height, traversal order, O(h) operations) and 7 Binary Trees Part 2: AVL (Adelson-Velsky and Landis, 1962) at ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes
  • MDN Web Docs, Array.prototype.shift (shifts all values left by 1)
  • Array.prototype.unshift, Map (insertion order, Map vs Object, spec requires sublinear average access) and Set (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)
  • ECMAScript 2025 Language Specification (tc39.es/ecma262)
  • 24.1 Map Objects and 24.2 Set Objects ("must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements")
  • Array.prototype.shift steps (Repeat, while k < len: move element k to k - 1)
  • D. E. Knuth, The Art of Computer Programming vol. 3 (2nd ed. 1998) section 6.4 History (H. P. Luhn, IBM internal memorandum January 1953, hashing with chaining; digit pairs added mod 10, 31415926 -> 4548) via gwern.net copy, and IEEE Spectrum, "Hans Peter Luhn and the Birth of the Hashing Algorithm" (2018)
  • "A brief history of the stack", SIGCIS (sigcis.org/files/A brief history.pdf: Bauer and Samelson applied for the patent in 1957, US 3,047,228 granted July 31, 1962; IPL list processing by Newell, Simon and Shaw at RAND 1956) and Wikipedia, Information Processing Language (Newell, Shaw, Simon, RAND and Carnegie Institute of Technology, about 1956).

Consultato il: 2026-10-18