|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Apr 2006
Messaggi: 22462
|
[Java] ricerca e ordinamento
salve a tutti, nel mio studio dei linguaggi di programmazzione mi sono ritrovato ad affrontare i sistemi di ricerca e ordinamento.
ora dopo varie analisi mi sono posto alcuni quesiti che da solo non riesco a risolvere (ed essendo autodidatta) e che non so a chi chiedere 1)mettiamo un array utilizzato una sola volta nell'esecuzione di un programma, nel quale va ricercato un valore, qui io ho davanti due alternative: ricerca lineare o ordinamento+ricerca binaria. se sceglo la prima so che nel caso peggiore avrò una complessità di O(n), se scelgo la seconda avrò per la ricerca una complessità pari a O(log n) più una complessità derivata dall'ordinamento che nel caso dei più efficenti sistemi è di O(n log n). facendo ora due conti viene fuori che nel primo caso la complessità nel caso peggiore è O(n), nel secondo O(log n+n log n), difatto mettendo un array di 20 elementi nel primo caso avrei 20 confronti, nel secondo 2^4+ 20*2^4=336. da qui si evince che il primo costa meno del secondo in termini di prestazioni, escludendo gli alberi binari ma operando solo su degli array, esistono altre scappatoie o effettivamente conviene la ricerca lineare? 2) dovendo ordinare una array mi conviene sfruttare un algoritmo di ordinamento, o mi conviene sfruttare gli alberi binari?
__________________
amd a64x2 4400+ sk939;asus a8n-sli; 2x1gb ddr400; x850 crossfire; 2 x western digital abys 320gb|| asus g1
Se striscia fulmina, se svolazza l'ammazza |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2780
|
Scusa ma log(20) non fa 2^4
Ad ogni modo devi considerare anche il fatto che in genere nel campo pratico le ricerche non si fanno su una quantità di elementi così piccola PS: mi sono dimenticato di aggiungere che, sempre nel campo pratico, gli elementi non vengono ordinati nel momento in cui devi fare una ricerca ma in genere viene fatto un inserimento ordinato Ultima modifica di wingman87 : 29-02-2008 alle 19:41. |
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Apr 2006
Messaggi: 22462
|
Quote:
per il secondo punto lo so, ma visto che solo per 20 elementi la dimensione aumenta, mi immagino cosa succede con un array di un miliardo, comunque il primo è più una sottigliezza teorica che un qualcosa che mi serve, quel che mi interessa è il secondo punto
__________________
amd a64x2 4400+ sk939;asus a8n-sli; 2x1gb ddr400; x850 crossfire; 2 x western digital abys 320gb|| asus g1
Se striscia fulmina, se svolazza l'ammazza |
|
|
|
|
|
|
#4 | |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2780
|
Quote:
Per il secondo punto vedi il PS del mio primo post EDIT: Aggiungo anche che se non devi fare una sola ricerca ma diciamo n ricerche, è meglio fare l'ordinamento una volta e poi tutte le ricerche con il metodo binario. Ultima modifica di wingman87 : 29-02-2008 alle 20:02. |
|
|
|
|
|
|
#5 | ||
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Resta che se devi cercare l'esistenza di un valore in un insieme, la struttura migliore non e' la lista ordinata. La lista ordinata serve quando devi cercare range di valori (Es: Tutti i valori compresi tra X e Y), oppure quando devi cercare elementi per posizione in una lista ordinata secondo un criterio (ES: Voglio sapere qual e' il quinto elemento se avessi ordinato gli elementi con questo criterio) Se invece devi cercare semplicemente l'esistenza di un valore in un insieme, la struttura migliore e' la hastable, che si costruisce in O(1) per ogni elemento (quindi O(n) per il tuo caso) e si interroga in poco piu' di O(1) ogni volta che si cerca qualcosa. Quindi perche' non costruire la hastable anche nel tuo caso limite, ovvero quando si cerca una volta sola, dato che costa O(n)? Perche' la hastable occupa anche memoria, solitamente si approssima per eccesso in 2n, dove n e' l'occupazione della memoria della lista non ordinata di partenza (Sia che sia un array semplice, sia che sia una lista in senso stretto, ovvero in cui ogni elemento ha il proprio valore, e poi il riferimento (puntatore) al prossimo elemento della lista) Quindi nel tuo caso la complessita' sarebbe O(n) comunque, e, non servendo piu' la hastable, "consumi meno" a scorrere tutta la lista disordinata e cercare il tuo elemento. Ora, parentesi. E' la terza volta in 3 settimane che mi ritrovo a rinfrescare l'esistenza delle hashtable e dl loro utilizzo. Ma per caso non vengono piu' spiegate? Vengono spiegate male e non si capiscono? Booh? edit: Scusa, ho visto ora che sei autodidatta, e quindi tanto di cappello per la tua volonta'. Quote:
Questo perche' se non sbaglio c'era qualcosa (un teorema? Boh?) che affermava che e' possibile rappresentare un albero binario come una lista ordinata, ma anche il viceversa. Secondo questa affermazione sarebbero equivalenti.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 29-02-2008 alle 21:38. Motivo: scusa |
||
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Apr 2006
Messaggi: 22462
|
questo è quello che volevo sapere.
Per l'ultimo caso però forse ho espresso male la mia richiesta: vorrei sapere se per ordinare un array è più conveniente sfruttare, che ne so, un quicksort, o un ordinamento con albero binario e poi ritirarlo fuori tramite una lettura inordine. ecco quello che vorrei, se non mi sbaglio a livello complessità computazionale il sistema ad albero binario è più efficente se non mi sbaglio log2 n in entrata e lo stesso valore in uscita quindi 2 *(log2 n ), mentre per un quicksort serve n*log n, quindi teoricamente è più conveniente un albero binario, solo che un array occupa meno memoria di un intera classe ricorsiva e si accede più velocemente a dei suoi elementi, quindi non so quanto tempo alla fine possa servire. secondo te quale è più conventiente?
__________________
amd a64x2 4400+ sk939;asus a8n-sli; 2x1gb ddr400; x850 crossfire; 2 x western digital abys 320gb|| asus g1
Se striscia fulmina, se svolazza l'ammazza |
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Dec 2005
Messaggi: 7258
|
Quote:
nel caso in esame io userei: - ricerca lineare se il numero di elementi non è molto grande - lista ordinata (mediante inserimenti ordinati) + ricerca binaria se il numero di elementi è molto grande |
|
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Vediamo se riesco a farti capire in modo intuitivo il costo: Immagina di essere a meta' dell'algoritmo di costruzione di un albero binario, ovvero che tu abbia gia' inserito N elementi della tua lista disordinata nell'albero, ma che te ne manchino altrettanti. Devi inserire l'N+1 esimo. Quanto costa inserirlo? Costa Log(n), perche' log(n) saranno i confronti che dovrai fare (al massimo) per cercare la posizione giusta del tuo nuovo elemento. E quindi, poiche' ogni elemento costa log(N) , ma tu hai N elementi da inserire nell'albero, ne consegue che anche costruire un albero binario a partire da un insieme disordinato costa N Log(N), proprio come il quicksort e altri algoritmi di ordinamento ottimi. Anche perche' se avessi trovato un modo di ordinare una lista ordinata in meno di O( N LOG(n)), allora avresti trovato un algoritmo di ordinamento migliore del quicksort, mergesort, etc. E chi ce lo farebbe fare di studiare e usare ancora quegli algoritmi li' e non il tuo? Concluderei quindi che in quanto a costo sono equivalenti. E questo rafforza la mia ipotesi di prima sul teorema che non ricordo piu', e che sicuramente non riusciro' a trovare.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Apr 2006
Messaggi: 22462
|
Quote:
__________________
amd a64x2 4400+ sk939;asus a8n-sli; 2x1gb ddr400; x850 crossfire; 2 x western digital abys 320gb|| asus g1
Se striscia fulmina, se svolazza l'ammazza |
|
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Direi quindi che nel caso della ricerca di esistenza la hastable continuerebbe ad essere la migliore anche valutando il caso peggiore.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: Dec 2005
Messaggi: 7258
|
Quote:
comunque io non ho affatto consigliato insertion sort ho detto che nel caso in cui gli elementi sono molti è conveniente mantenere una lista ordinata mentre li si inseriscono. in questo modo è possibile usare una ricerca binaria.
|
|
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Comunque, nel caso peggiore, per costruire una hastable ci metto O(N), e per andare a cercare un valore invece che il "medio (non migliore)" O(1), ci metto di nuovo O(N), perche' tutti gli elementi sono collassati nella stessa chiave. Quindi a costruirla ci metto O(N) e a cercare ci metto O(N). Nel caso peggiore quindi siamo a O(N)+O(N) = O(N) Nel caso medio di un algoritmo di ordinamento tra quelli ottimi, scegli quello che vuoi, ci metterai N LOG(N) ad ordinare, e LOG(N) a cercare. NLOG(N) + LOG(N) = NLOG(N) Mi sai dire dove ci guadagni a costruire la lista ordinata per poi cercare dentro? Invece sul ragionamento "mantenere la lista ordinata mentre li si inseriscono" si puo' applicare sia alla hastable che al caso della lista ordinata. Per inserire un elemento in una hastable ci metto O(1), per inserirlo in una lista gia' ordinata ci metto O(LOG(N)). Di nuovo, non vedo nessun vantaggio.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#13 | |||
|
Senior Member
Iscritto dal: Dec 2005
Messaggi: 7258
|
Quote:
probabilmente non ci siamo capiti ps. ah per il O(N^2) mi riferivo a quicksort. quicksort in realtà è molto utilizzato perchè ha una complessità spaziale minore di molti altri algoritmi, non per la sua efficienza temporale (anche se un NlogN nel caso medio è di tutto rispetto) Quote:
Quote:
se valutiamo il caso peggiore allora l'inserimento nella hash table è in O(n) dove n indica il numero di elementi presenti nella hash table (cioè caso in cui l'elemento da inserire collide con tutti gli elementi già presenti). Ultima modifica di k0nt3 : 29-02-2008 alle 22:49. |
|||
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Anche qualora tu avessi la collisione, e' suffiente appendere l'elemento alla lista degli elementi di quella chiave, tipicamente in coda o in testa. E' sempre O(1), anche nel caso collassato, non hai bisogno di scorrere tutti gli elementi per farlo.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Dec 2005
Messaggi: 7258
|
Quote:
ps. ciò non toglie che le hash table siano estremamente utili in molti contesti Ultima modifica di k0nt3 : 29-02-2008 alle 23:18. |
|
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Allora, diciamo cosi'. Se ti senti particolarmente sfortunato usa la lista ordinata, perche' inserisci in O(lOG(N)) e cerchi in O(LOG(N)) Se invece ti senti una persona nella media, allora usa la hashtable, inserisci in O(1) e cerchi in poco piu' di O(1). Per questo problema, nei grandi numeri io preferisco la hastable, perche' nei grandi numeri e' probabile essere nella media. Tu che algoritmo useresti per la cache nei microprocessori? Preferiresti che ogni volta che il microprocessore cerca un indirizzo, allora lo va a cercare in O(Ln(N)) su tutta la cache e ogni volta che deve inserirne uno ci mette O(LN(N)) oppure preferiresti usare una hastable come effettivamente fanno?
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
|
#17 | ||
|
Senior Member
Iscritto dal: Dec 2005
Messaggi: 7258
|
Quote:
stai confrontando il caso pessimo del primo con il caso ottimo del secondo. in una hash table cerchi in O(n).Quote:
|
||
|
|
|
|
|
#18 | ||||
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Quote:
Quote:
Quote:
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
||||
|
|
|
|
|
#19 | |
|
Senior Member
Iscritto dal: Dec 2005
Messaggi: 7258
|
Quote:
ma in fondo non è che mi interessi più di tanto la faccenda, il mio consiglio l'ho dato e volevo solo precisare che le hash table non risolvono tutti i mali del mondo. |
|
|
|
|
|
|
#20 | ||
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Quote:
Le hashtable non servono per rispondere a domande tipo: Quale e' il piu' alto? Quale e' il piu' basso? Quale e' il sesto se li ordinassi con questo criterio? Quali sono i valori tra 5 e 75, presenti in questo elenco? Per queste risposte ci vuole il concetto di ordinamento, che una hastable classica non ha. Una lista ordinata invece e' nella maggior parte dei casi il modo migliore, soprattutto se queste domande non sono spot, ma sono ripetute piu' volte nel tempo. Ma per rispondere a una domanda come "C'e' il 753 in questo elenco di valori disordinati?", che e' proprio la domanda da cui e' partito questo post, allora la hashtable e' la soluzione ottima, soprattutto se la domanda e' ripetuta in modo simile piu' volte nel tempo.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
||
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 00:33.












ho detto che nel caso in cui gli elementi sono molti è conveniente mantenere una lista ordinata mentre li si inseriscono. in questo modo è possibile usare una ricerca binaria.








