Quali sono i motivi per apprendere algoritmi / strutture dati differenti che servono allo stesso scopo?


91

Mi sono chiesto di questa domanda da quando ero uno studente universitario. È una domanda generale, ma elaborerò con esempi di seguito.

Ho visto molti algoritmi - ad esempio, per i problemi di flusso massimo, conosco circa 3 algoritmi che possono risolvere il problema: Ford-Fulkerson, Edmonds-Karp e Dinic, con Dinic che ha la migliore complessità.

Per le strutture di dati - ad esempio heap - ci sono heap binari, heap binomiali e heap di Fibonacci, con l'heap di Fibonacci che presenta la migliore complessità complessiva.

Ciò che mi confonde è: ci sono dei motivi per cui dobbiamo conoscerli tutti? Perché non solo imparare e familiarizzare con la migliore complessità?

So che è il migliore se li conosciamo tutti, voglio solo sapere ci sono ragioni "più valide", come alcuni problemi / algoritmi possono essere risolti solo usando A ma non B , ecc.


17
Come dico sempre: questi (di solito) non sono "i migliori". Una volta definito esplicitamente cosa intendi per "migliore", la risposta diventa ovvia.
Raffaello

2
Questa è una buona domanda, ma parla di ciò che considererei un buco nella tua educazione che potresti cercare di correggere. Questa è un'esperienza pratica, se non hai effettivamente scritto questi algoritmi durante la tua istruzione, potresti prendere in considerazione di scriverli ora, sospetto che la risposta a questa domanda sarebbe diventata rapidamente ovvia mentre cercavi di trovare degli usi per loro.
Sam,

@Sam Dalla mia esperienza, quello che ho pensato è che nelle lezioni, o in alcuni libri di testo, sono informativi, introducono molti algoritmi, analisi, ecc., Ma non molti casi pratici o scenari di esempio che A supererà B. Potrebbero coprire un genere di algoritmi dalla A alla Z e alcuni problemi di compiti a casa, ma per me possono tutti risolti solo con A, o solo con Z, ecc., quindi la domanda posta.
mandato il

5
Se insisti a lasciare da parte l'interesse accademico, la migliore ragione pratica per imparare meno degli algoritmi ottimali è che puoi riconoscerli per quello che sono e ottimizzarli rifattorizzando su quelli ottimali. Non puoi aggiornare un arco e una freccia a una pistola se non sai a cosa servono un arco e una freccia.
candied_orange,

1
Abbiamo effettivamente proposto un sito StackExchange per aiutare in modo specifico con domande di educazione CS come questo. Vieni a supportarci qui: area51.stackexchange.com/proposals/92460/…
vk2015

Risposte:


121

C'è un libro di testo in attesa di essere scritto ad un certo punto, con il titolo provvisorio Strutture di dati, algoritmi e compromessi . Quasi ogni algoritmo o struttura di dati che probabilmente imparerai a livello universitario ha alcune funzionalità che lo rendono migliore per alcune applicazioni rispetto ad altre.

Prendiamo l'ordinamento come esempio, poiché tutti hanno familiarità con gli algoritmi di ordinamento standard.

Prima di tutto, la complessità non è l'unica preoccupazione. In pratica, i fattori costanti contano, ed è per questo che (diciamo) l'ordinamento rapido tende ad essere usato più dell'ordinamento dell'heap anche se l'ordinamento rapido ha una terribile complessità nel caso peggiore.

In secondo luogo, c'è sempre la possibilità che ti trovi in ​​una situazione in cui stai programmando con strani vincoli. Una volta ho dovuto eseguire l'estrazione quantile da una raccolta di campioni di dimensioni modeste (circa 1000) il più velocemente possibile, ma era su un piccolo microcontrollore che aveva pochissima memoria di lettura-scrittura di riserva, quindi ha escluso la maggior parte di ordina algoritmi. L'ordinamento Shell è stato il miglior compromesso, poiché era sub-quadratico e non richiedeva memoria aggiuntiva.O(nlogn)

In altri casi, le idee di un algoritmo o di una struttura di dati potrebbero essere applicabili a un problema specifico. L'ordinamento delle bolle sembra essere sempre più lento dell'ordinamento di inserzione su hardware reale, ma l'idea di eseguire un passaggio di bolle a volte è esattamente ciò di cui hai bisogno.

Considera, ad esempio, una sorta di visualizzazione 3D o videogioco su una moderna scheda video, in cui desideri disegnare gli oggetti in ordine dal più vicino alla fotocamera al più lontano dalla fotocamera per motivi di prestazioni, ma se non ottieni l'ordine esatto, l'hardware se ne occuperà. Se ti sposti nell'ambiente 3D, l'ordine relativo degli oggetti non cambierà molto tra i fotogrammi, quindi eseguire un passaggio di bolle ogni fotogramma potrebbe essere un compromesso ragionevole. (Il motore Source di Valve lo fa per gli effetti particellari.)

Esistono persistenza, concorrenza, località della cache, scalabilità in un cluster / cloud e una serie di altre possibili ragioni per cui una struttura di dati o un algoritmo può essere più appropriata di un'altra, anche alla luce della stessa complessità computazionale per le operazioni a cui tieni.

Detto questo, ciò non significa che dovresti memorizzare un gruppo di algoritmi e strutture di dati per ogni evenienza. La maggior parte della battaglia si sta rendendo conto che c'è un compromesso da sfruttare in primo luogo, e sapendo dove cercare se pensi che potrebbe esserci qualcosa di appropriato.


7
Ottima risposta con ottimi esempi! Non sapevo nemmeno passaggio bolla ha il suo uso pratico nel mondo reale ...
shole

1
@shole Non ho molta esperienza nel settore dei giochi, ma tutto quanto sopra è importante a vari livelli. (Ovviamente, il tipo di algoritmi, strutture di dati e matematica di cui hai bisogno per i giochi è probabilmente diverso da quelli richiesti per database o bioinformatica o cosa hai.) Se fossi in te, andrei qui e inizierei a guardare: handmadehero. org Potrebbe anche valere la pena nascondersi su gamedev.stackexchange.com
Pseudonimo

1
L'efficienza della cache è un fattore fortemente sottovalutato ("memory wall" di google).
Raffaello

6
Attento, Quicksort è in media molto più veloce di Heapsort, ma Heapsort è più coerente (la sua varianza nel tempo di esecuzione è inferiore e il caso peggiore è molto meglio). E Heapsort sta saltando nell'array rispetto alle scansioni lineari di Quicksort da sinistra e destra facendo una grande differenza una volta che la cache / paging entra in gioco.
vonbrand,

1
@shole A che tipo di sviluppo di giochi ti interessa? Esistono almeno due sottocampi molto diversi, la grafica 3D e il gameplay (che include l'IA). Ho solo esperienza con la grafica, ma posso dire che le strutture dati e la matematica sono estremamente importanti in grafica e algoritmi in misura minore. Se stai usando un motore, la maggior parte di queste cose sarà ovviamente curata, ma dovresti comunque capire la matematica di base della geometria 3D.
gardenhead,

51

A parte il fatto che ci sono miriadi di misure di costo (tempo di esecuzione, utilizzo della memoria, errori nella cache, previsioni errate sulle filiali, complessità di implementazione, fattibilità della verifica ...) su miriadi di modelli di macchine (TM, RAM, PRAM, ...) , il caso medio contro il caso peggiore e le considerazioni relative all'ammortamento che si contrappongono, spesso ci sono anche differenze funzionali oltre l'ambito delle specifiche di base del libro di testo.

Qualche esempio:

  • Mergesort è stabile dove Quicksort non lo è.
  • Gli alberi di ricerca binari forniscono iterazione in ordine, gli hashtable no.
  • Bellman-Ford è in grado di gestire pesi con bordi negativi, Dijkstra no.

Ci sono anche considerazioni didattiche da fare:

  • Quanto è facile capire una soluzione più coinvolta prima di una più semplice? (Alberi AVL (e loro analisi) senza BST; Dinic senza Ford-Fulkerson; ...)
  • Vedi gli stessi principi e schemi quando sei esposto a una sola soluzione per problema rispetto a quando sei esposto a molte soluzioni?
  • L'esposizione a una sola soluzione per problema fornisce una formazione sufficiente (verso la padronanza)?
  • Dovresti conoscere l'ampiezza di quali soluzioni sono state trovate (in modo da impedirti di reinventare la ruota ancora e ancora¹)?
  • Se esposto a una sola soluzione per problema, capirai altre soluzioni che trovi in ​​natura (diciamo, in una biblioteca di programmazione del mondo reale)?

  1. Questo è qualcosa che vediamo molto dai tipi di programmatori che non hanno una ricca cassetta degli attrezzi CS a loro disposizione.

4
+1 per l'inclusione delle motivazioni didattiche! Relativo a diversi razionali (in particolare il secondo e il terzo), vedere come vengono sviluppati e ottimizzati algoritmi e strutture di dati insegna tecniche di sviluppo e ottimizzazione e una comprensione dei compromessi (imparando non solo "cosa" ma anche "come" e "perché" ).
Paul A. Clayton,

2
Un'ulteriore considerazione è che l' analisi delle diverse alternative offre esempi di strumenti utili per l'analisi di nuovi algoritmi per impostazioni forse insolite.
vonbrand,

1
Buon punto, @vonbrand. L'analisi della complessità ammortizzata è stata inventata per comprendere il comportamento degli alberi di splay, ma gli alberi di splay sono usati raramente in pratica. Beh, non allargare gli alberi come pubblicato, comunque. Il kernel di Windows NT utilizza notoriamente alberi di visualizzazione per implementare mappe di memoria virtuale, ma non riordina ad ogni ricerca.
Pseudonimo,

1
@vonbrand Sì. Comprenderei come qualcuno interessato principalmente alla dimensione della cassetta degli attrezzi su una classe di algoritmi, però, deriderebbe quella ragione.
Raffaello

7

Nel mondo reale , a un certo punto probabilmente lavorerai su un software che è stato scritto da un team di altre persone. Alcuni di questi software saranno stati scritti prima della tua nascita!

Al fine di comprendere gli algoritmi / le strutture di dati utilizzati, è molto utile conoscere un gran numero di algoritmi / strutture di dati, comprese le opzioni che non sono più considerate "allo stato dell'arte".

Dovrai anche lavorare su algoritmi che non sono standard e vengono utilizzati solo nell'applicazione su cui stai lavorando. Quando devi migliorare questi algoritmi, scoprirai che il tuo cervello è stato riempito con metodi utili per migliorare gli algoritmi, poiché hai studiato come altre persone hanno migliorato gli algoritmi.

Questo è ciò che distingue qualcuno che ha studiato informatica a parte qualcuno che ha appena imparato a programmare. Nella maggior parte dei lavori in cui ho lavorato, quando ho studiato informatica ho potuto risolvere un problema che un programmatore "imparato dai libri" non poteva, ma il 95% delle volte ho scoperto che aver studiato informatica non mi ha dato alcun vantaggio rispetto ad altri programmatori esperti .


a meno che il 95% delle cose che stai cercando di risolvere siano legate all'apprendimento automatico. Non riesco a vedere come un normale programmatore possa avere la giusta possibilità di tentare uno qualsiasi dei problemi affrontati da problemi di ML reali.
Pinocchio,

3
Obiettivo: ottenere un lavoro con una percentuale migliore del 5%.
Raffaello

Ricorda che studiare CS è stato un ottimo modo per raccogliere conoscenze su algoritmi e strutture dati. La codifica è la migliore occupazione - per i programmatori.
Greybeard,

5

Molte persone hanno giustamente menzionato che spesso non esiste un algoritmo migliore - dipende dalla situazione.

C'è anche la possibilità che un giorno ti imbatterai in una situazione sconosciuta. Più algoritmi conosci, più possibilità avrai di conoscerne uno che è quasi una soluzione che puoi usare come base.


5
Questa risposta ripete solo i punti di quelli più vecchi.
Raffaello

1

Molte grandi risposte, solo qualcosa che penso manchi, anche se la risposta di Raphael menziona in qualche modo questo.

Anche la facilità di implementazione è qualcosa da prendere in considerazione.
Questo di solito non è un problema con gli algoritmi di ordinamento, perché la maggior parte delle piattaforme / lingue ne ha già implementato uno (e spesso migliore di quello che potresti fare), ma potrebbero non essere disponibili algoritmi più insoliti.
A seconda del problema, potrebbe non essere necessario l'algoritmo migliore in assoluto se il tempo di implementazione è di 1 giorno contro 2 settimane.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.