Pagini: [1] 2   În jos
  Imprimă  
Ajutor Subiect: Subset maxim  (Citit de 11445 ori)
0 Utilizatori şi 1 Vizitator pe acest subiect.
pauldb
Nu mai tace
*****

Karma: 821
Deconectat Deconectat

Mesaje: 1.901



Vezi Profilul
« : Decembrie 13, 2011, 00:48:20 »

Discutati aici pe marginea post-ului Subset maxim.
Memorat

Am zis Mr. Green
Bogdan_tmm
De-al casei
***

Karma: 4
Deconectat Deconectat

Mesaje: 122



Vezi Profilul
« Răspunde #1 : Decembrie 13, 2011, 01:43:52 »

Parcurgem sirul si pentru fiecare element x, verificam daca x - 1 si/sau x + 1 au fost intalnite anterior(cu un hash). Daca ambele au fost, atunci inseram una dintre multimi in cealalta(multimea lui X= {multimea maximala de numere consecutive intalnite inaintea lui X}  U  {X} ), inclusiv pe x(cu multimi disjuncte), daca doar una din valori a fost intalnita anterior il inseram pe x in acea multime.
Memorat
freak93
Echipa infoarena
Nu mai tace
*****

Karma: 342
Deconectat Deconectat

Mesaje: 819



Vezi Profilul
« Răspunde #2 : Decembrie 13, 2011, 01:56:11 »

asta e N log* N. Cred ca se asteapta o solutie mai buna.

Later Edit:
Se poate totusi implementa in O(N) solutia cu multimi disjuncte datorita particularitatii problemei(mai exact faptul ca niciodata nu vei uni doua multimi decat dupa elemente de la capetele lor, deci informatii legate de multimea unui element nu trebuie updatate decat in capete)
« Ultima modificare: Decembrie 13, 2011, 02:10:14 de către Budau Adrian » Memorat
pauldb
Nu mai tace
*****

Karma: 821
Deconectat Deconectat

Mesaje: 1.901



Vezi Profilul
« Răspunde #3 : Decembrie 13, 2011, 02:20:50 »

Adi are dreptate, nu o solutie in complexitate O(Nlog*N) se asteapta.

Legat de modul de implementare in O(N), ai putea detalia pentru ca nu inteleg ce vrei sa spui?
Memorat

Am zis Mr. Green
alisa
Strain


Karma: 0
Deconectat Deconectat

Mesaje: 1



Vezi Profilul
« Răspunde #4 : Decembrie 13, 2011, 02:35:44 »

o idee ..cred cam nepractica: ptr fiecare element din multimea data , un v[nr.resp] va lua valorile 1,2 sau 3.... 1 daca nr din multime e pozitiv si v[nr.resp] este 0, 2 daca elementul din multime este negativ si v[nr.resp] este 0, 3 daca v[nr.resp]nu era 0 ->adica daca exista in multime si x si -x..... apoi... ar mai ramane problema numararii celui mai lung suubsir de ne-zerouri la modul urmator...daca v[0] este 0 nu mai e problema unei submultimi care sa contina atat nr negativa, cat si pozitive.. ci trebui determinat cel mai lung subsir de 1si 3..sau de 2si3..daca v[0] este 1, atunci nu prea mai stiu:))
Memorat
pauldb
Nu mai tace
*****

Karma: 821
Deconectat Deconectat

Mesaje: 1.901



Vezi Profilul
« Răspunde #5 : Decembrie 13, 2011, 02:53:31 »

o idee ..cred cam nepractica: ptr fiecare element din multimea data , un v[nr.resp] va lua valorile 1,2 sau 3.... 1 daca nr din multime e pozitiv si v[nr.resp] este 0, 2 daca elementul din multime este negativ si v[nr.resp] este 0, 3 daca v[nr.resp]nu era 0 ->adica daca exista in multime si x si -x..... apoi... ar mai ramane problema numararii celui mai lung suubsir de ne-zerouri la modul urmator...daca v[0] este 0 nu mai e problema unei submultimi care sa contina atat nr negativa, cat si pozitive.. ci trebui determinat cel mai lung subsir de 1si 3..sau de 2si3..daca v[0] este 1, atunci nu prea mai stiu:))

Exista o problema cu solutia oferita de tine. Abordarea ta e ok daca numerele (in modul) sunt relativ mici, insa acest lucru nu e specificat in enunt. Daca facem presupunerea standard ca numerele vor fi reprezentate pe 32 biti (int), atunci nu vei putea declara un vector v de ~2*109 elemente. Problema asta poate fi depasita folosind hash-uri, dupa cum a sugerat si Bogdan mai sus.
Memorat

Am zis Mr. Green
Cosmin
Echipa infoarena
Nu mai tace
*****

Karma: 351
Deconectat Deconectat

Mesaje: 1.799



Vezi Profilul
« Răspunde #6 : Decembrie 13, 2011, 06:50:09 »

merge doar cu hash, n-ai nevoie de structuri de multimi disjuncte.
« Ultima modificare: Decembrie 13, 2011, 07:21:32 de către Cosmin Negruseri » Memorat
claudiumihail
Strain
*

Karma: 5
Deconectat Deconectat

Mesaje: 33



Vezi Profilul
« Răspunde #7 : Decembrie 13, 2011, 08:04:39 »

Just my 2 cents:

Daca este permis sa folosim O(n) memorie, unde n este marimea sirului (banuiesc ca se poate daca se tot discuta solutia cu has-uri). Putem folosi un radix sort mai tunat (dupa cum se discuta http://www.cubic.org/docs/radix.htm) pentru a sorta sirul. O data sortat gasirea celui mai lung subsir crescator este banal. Dezavantajul major al acestei solutii este ca din punct de vedere teoretic complexitatea este O(n*number_of_radixes). Insa cum putem fixa numarul de bytes din care este alcatuit numarul la o valoare constanta (4 pentru numere pe 32 biti sau 8 pentru numere pe 64 biti) complexitatea practica este liniara cu o constanta relativ mica. Nu e cea mai eleganta solutie dar macar e putin inovatoare Smile.

Cateva note:

1) Daca e sa analizam compelxitatea teoretica, solutia cu hash-uri nu e neaparat mai buna decat cea cu radix sort-ul. Asta pentru ca oricum pentru a calcula acel hash (oricare ar fi el), trebuie parcursi toti bitii numarului, deci complexitatea teoretica cam tot aia e.

2) Pentru valori in virgula mobila este mai dificil (desi nu imposibil, dupa cum se vede aici http://www.codercorner.com/RadixSortRevisited.htm). Problema cu valorile in virgula mobila este ca depinde de implementarea specifica (care poate diferi de la un limbaj la altul etc).

Una peste alta, solutia cu has-urile in practica ar necesita mai putine parcurgeri decat solutia cu radix sort si pare si mai versatila. Dar I felt like throwing my 2 cents into the ring. Va rog sa ma corectati daca am gresit in diverse locuri.

Claudiu



2) Se poate argumenta ca solutia cu radix sort nu va merge pe numere signed sau pe valori in floating point. Nu neaparat. Pentru numere negative merge, doar ca algoritmul le va considera valori unsigned si deci foarte mari. Acest neajuns se poate compensa cu o parcurgere in plus.
Memorat
yonatan
Strain
*

Karma: 10
Deconectat Deconectat

Mesaje: 47



Vezi Profilul
« Răspunde #8 : Decembrie 13, 2011, 10:03:04 »

Folosim solutia  lui Bogdan numai ca in loc de multimi disjucte folosim o padure de arbori direct. Nodurile sunt numerotate folosind indicii vectorului.
Practic cand ajungem la un numar cautam in Hash indicele numarului v[ i ]-1 si v[ i ]+1
si daca  le gasim(pe oricare dintre ele, nu neaparat pe amandoua) trasam o muchie de la  i la indicele/indicii valorilor gasite.
La final putem face un DFS in care determinam numarul de elemente din fiecare arbore(lant) si minimul sau maximul ceea ce este suficient pentru a afisa numerele.
DFS-ul este O(N) fiindca avem maxim N-1 muchii.  
« Ultima modificare: Decembrie 13, 2011, 10:17:13 de către Cont de teste » Memorat
Cosmin
Echipa infoarena
Nu mai tace
*****

Karma: 351
Deconectat Deconectat

Mesaje: 1.799



Vezi Profilul
« Răspunde #9 : Decembrie 13, 2011, 10:53:08 »

Am solutie in python in O(n) de 12 linii. O puteti scoate mai scurt?
« Ultima modificare: Decembrie 13, 2011, 10:58:44 de către Cosmin Negruseri » Memorat
bent_larsen
Strain


Karma: 1
Deconectat Deconectat

Mesaje: 18



Vezi Profilul
« Răspunde #10 : Decembrie 13, 2011, 12:46:03 »

Tinem doua hashuri. Pentru fiecare hash cheia e valoarea numarului intalnit si valoarea asociata cheii
e numarul de elemente care incep sau se termina la numarul intalnit. Cand intalnim un numar facem update
la cele doua hashuri in O(1) (vedem daca exista valoarea+1 si valoare-1 in hashtable si facem update). La sfarsit, pentru fiecare numar cautam cele doua lungimi memorate in hashtable, facem suma lor si updatam lungimea maxima.
Memorat
freak93
Echipa infoarena
Nu mai tace
*****

Karma: 342
Deconectat Deconectat

Mesaje: 819



Vezi Profilul
« Răspunde #11 : Decembrie 13, 2011, 18:45:03 »

Solutia O(N) cu hashuri e exact cea din primul post. Mai exact pentru fiecare element tinem capatul din stanga si capatul din dreapta al intervalului din care apartine. Atunci cand dam de un element cu valoarea x facem urmatorii pasi

1) Daca l-am intalnit il ignoram, sarim pasii urmatori
2) Daca exista in hash x - 1 unim hashul lui cu elementul curent
     mai exact fie [y, x - 1] intervalul din care apartine x - 1(nu se poate mai la dreapta pentru ca pana la momentul actual nu exista x)
     updatam in hash-ul lui y ca intervalul e [y, x] si la fel si in hash-ul lui x.
3) Daca exista in hash x + 1 unim intervalul lui x cu cel al lui x + 1 pe aceeasi idee ca la pasul 2

In total la un pas facem un numar constant de operatii si sunt numar constanti de pasi => pentru fiecare element facem un numar constant de operatii => complexitate O(N).

Aduce a paduri de multimi disjuncte dar este o particularitate.

Pentru Cosmin Negruseri: Exista vreo solutie care nu foloseste hash-uri si e mai buna de O(N log N)?
Memorat
rgrig
De-al casei
***

Karma: 46
Deconectat Deconectat

Mesaje: 144



Vezi Profilul WWW
« Răspunde #12 : Decembrie 13, 2011, 18:52:37 »

@Cosmin: Depinde cât trișez. Smile Dacă le înghesui încape pe 10 linii (cu tot cu I/O).
Memorat
palcuiealex
Strain
*

Karma: 7
Deconectat Deconectat

Mesaje: 43



Vezi Profilul
« Răspunde #13 : Decembrie 13, 2011, 19:16:31 »

Sau chiar 9 daca citesti direct in int cu struct.readInt32  Dancing
Normal sunt vreo 20 de linii, iar memoria e O(n*3) [cred].
Memorat
wefgef
Nu mai tace
*****

Karma: 1049
Deconectat Deconectat

Mesaje: 3.008


razboinicu' luminii


Vezi Profilul
« Răspunde #14 : Decembrie 13, 2011, 19:19:51 »

Sau chiar 9 daca citesti direct in int cu struct.readInt32  Dancing
Normal sunt vreo 20 de linii, iar memoria e O(n*3) [cred].

O(N*3) nu exista. Faptul ca tii 3 vectori/liste/hashuri cu N elemente nu inseamna ca aloci O(N*3) memorie.
Memorat

omului i-au fost date instinctele pentru a supravietui, nu pentru a fi sclavul lor.
rgrig
De-al casei
***

Karma: 46
Deconectat Deconectat

Mesaje: 144



Vezi Profilul WWW
« Răspunde #15 : Decembrie 13, 2011, 20:10:59 »

Sau chiar 9 daca citesti direct in int cu struct.readInt32  Dancing

Nu știu ce zici aici. Uite codul meu:

Cod:
import sys
xs = set([int(x) for x in sys.stdin.read().split()])
start, end, first = 0, -1, dict()
while len(xs) > 0:
  y = x = xs.pop()
  while y - 1 in xs: y = y - 1
  xs -= set(range(y, x))
  first[x] = first[y - 1] if y - 1 in first else y
  if x - first[x] > end - start: start, end = first[x], x
print (start, end)
Memorat
klamathix
Echipa infoarena
Nu mai tace
*****

Karma: 733
Deconectat Deconectat

Mesaje: 1.216



Vezi Profilul
« Răspunde #16 : Decembrie 13, 2011, 20:47:28 »

Solutia O(N) cu hashuri e exact cea din primul post. Mai exact pentru fiecare element tinem capatul din stanga si capatul din dreapta al intervalului din care apartine. Atunci cand dam de un element cu valoarea x facem urmatorii pasi

1) Daca l-am intalnit il ignoram, sarim pasii urmatori
2) Daca exista in hash x - 1 unim hashul lui cu elementul curent
     mai exact fie [y, x - 1] intervalul din care apartine x - 1(nu se poate mai la dreapta pentru ca pana la momentul actual nu exista x)
     updatam in hash-ul lui y ca intervalul e [y, x] si la fel si in hash-ul lui x.
3) Daca exista in hash x + 1 unim intervalul lui x cu cel al lui x + 1 pe aceeasi idee ca la pasul 2

In total la un pas facem un numar constant de operatii si sunt numar constanti de pasi => pentru fiecare element facem un numar constant de operatii => complexitate O(N).

Aduce a paduri de multimi disjuncte dar este o particularitate.

Pentru Cosmin Negruseri: Exista vreo solutie care nu foloseste hash-uri si e mai buna de O(N log N)?

Probabil imi scapa ceva, dar de ce nu duci doar muchie de la pozitia lui x la pozitia lui x + 1 si faci un DF la final?
Memorat
freak93
Echipa infoarena
Nu mai tace
*****

Karma: 342
Deconectat Deconectat

Mesaje: 819



Vezi Profilul
« Răspunde #17 : Decembrie 13, 2011, 21:05:35 »

Asa merge interactiv. Alta utilitate nu vad, DF-ul tot e varianta mai simpla.
Memorat
Cosmin
Echipa infoarena
Nu mai tace
*****

Karma: 351
Deconectat Deconectat

Mesaje: 1.799



Vezi Profilul
« Răspunde #18 : Decembrie 13, 2011, 22:39:47 »

Pare ca v-ati cam complicat. Asa fac eu
Cod:
a = [6, 3, 1, 5, 9, 11, 8, 7, 2]

max_set = set()
S = set(a)

for x in S:
  if x - 1 not in S:
    current_set = set()
    y = x
    while y in S:
      current_set.add(y)
      y += 1
    if len(current_set) > len(max_set):
      max_set = current_set

print max_set

Ideea e ca punctele interesante sunt doar capetele din stanga ale posibilelor multimi compacte.

Codul mai compresat putin:
Cod:
a = [6, 3, 1, 5, 9, 11, 8, 7, 2]

max_set, S = set(), set(a)

for x in S:
  if x - 1 not in S:
    current_set, y = set(), x
    while y in S:
      current_set.add(y)
      y += 1
    if len(current_set) > len(max_set): max_set = current_set

print max_set
« Ultima modificare: Decembrie 14, 2011, 03:17:56 de către Cosmin Negruseri » Memorat
rgrig
De-al casei
***

Karma: 46
Deconectat Deconectat

Mesaje: 144



Vezi Profilul WWW
« Răspunde #19 : Decembrie 14, 2011, 02:44:59 »

Îmi aduce aminte de statusul unui amic:
Citat
by this point, we were deep in facepalm territory. the facepalms were coming thick and fast, Johnson was hit and went down
Memorat
Cosmin
Echipa infoarena
Nu mai tace
*****

Karma: 351
Deconectat Deconectat

Mesaje: 1.799



Vezi Profilul
« Răspunde #20 : Decembrie 14, 2011, 04:19:29 »

Ovidiu Gheorghioiu stie programare functionala Smile si reduce solutia mea la 3 linii:
Cod:
import itertools
a = set(a)
print max((list(itertools.takewhile(lambda x: x in a, itertools.count(head)))
           for head in a if head - 1 not in a), key = len)
« Ultima modificare: Decembrie 14, 2011, 05:51:36 de către Cosmin Negruseri » Memorat
mpatrascu
Strain


Karma: 85
Deconectat Deconectat

Mesaje: 18



Vezi Profilul
« Răspunde #21 : Decembrie 14, 2011, 20:43:25 »

Mişto problema! Soluţia  nu e deloc evidentă şi eu nu mai auzisem de problemă, dar până la urmă e foarte simplă (un hashtable ca să trasăm o muchie între valori x şi x+/-1, urmat de componente conexe).

M-a rugat Cosmin să-mi dau cu părerea dacă există soluţie în timp liniar fără hashing. Probabil că nu, fiindcă fără hashing nu știm să facem în O(n) nici element distinctness (ai n întregi; se repetă vreunul?). De fapt asta e problemă majoră în teorie.

Dar hai să profit de ocazie să discut un pic filosofic.

1. Care-i problema cu hashingul?
E un algoritm simplu care chiar merge bine. La companiile mari ale momentului, ai de lucrat cu date foarte mari și aproape că nu există cod fără hashing la problemele din industrie. Deci mi se pare aproape obligatoriu să fie întrebări de hashing la interviu.

Ca să ilustrez cu o poveste Smile Am fost la bere cu niște ingineri de la Google NY și după 3-4 beri s-au apucat să mă întrebe de puzzles cu hashing, zicând că ei vor să facă toate întrebările de interviuri despre hashing, fiindcă citez "e singura chestie de la algoritmi fundamentali care chiar e esențială".

Eu la AT&T n-am păreri așa drastice, fiindcă sunt în research și nu intervievez ingineri Smile Dar la ce lucrez zilele ăştea chiar e hashing, şi e esenţial în practică Tongue

Teoria și cât de rapid merg algoritmii
Eu în liceu eram foarte confuz la capitolul "cât de mari sunt întregii", în ce complexitate merge radix sort, etc. Mi-aș fi dorit o explicaţie pe îndelete, și o să încerc acuma să dau o astfel de explicaţie, fiindcă văd că sunt oameni cu întrebări similare în comentarii.

În particular vreau să explic de ce radix sort nu e O(n) şi calcularea unui hash chiar e O(1), nu timp proporţional cu numărul de biţi.

Despre teorie: Dacă nu se pogoară Duhul Sfânt să ne dea o teorie aprobată de sus, teoria o definim noi matematic după cum ni se scoală, și n-are valoare decât în măsura în care scoate rezultate utile despre realitate. Matematic să poate defini orice, inclusiv o teorie fizică fără gravitație, doar că n-o să prezică chestiile care le vedem în experimente (ignorăm pe moment experimente despre cum acţionează gravitația pe Coyote și Roadrunner).

De la teoria algoritmilor vrem să aflăm care algoritmi sunt mai rapizi când îi codăm în C, și aproximativ cam cât de rapid e un algoritm relativ la un altul. Ca să obținem o astfel de teorie, trebe să admitem următorul fapt. Codul ăsta:
Cod:
int add(int a, int b)
{
    return(a+b);
}
... rulează mult mai repede decât să facem adunarea bit cu bit cu un for de la 1 la 32. Nu e greu să definești o teorie simplă care înglobează această proprietate:

Teoria spune că ai date de intrare pe un anume tip int, care nu știi fix câți biți are. Mărimea e o variabilă, nu o constantă, și nu se poate ignora în running time; notaţia încetăţenită pt nr. de biţi per int este "w" (vine de la machine Word). Teoria spune că operațiile din limbaj pe astfel de ints rulează în O(1), nu în O(w).

Mie personal mi se pare o presupunere rezonabilă. Limbajul C e foarte popular când ne doare de eficiență și orice proiectant de procesoare îl ia în seamă. Deci probabil orice procesor comercial are instrucțiuni care fac acele operațiile fundamentale din C, gen adunare, xor, etc. Deci o teorie care măsoară numărul de operații în C aproape măsoară numărul de cicluri de procesor, care e o măsură corectă pt timpul de rulare. Empiric se constată că modul ăsta de a defini complexitatea are corelații utile cu timpul de rulare măsurat pe multe calculatoare reale, cel puțin dacă nu iei complexitatea prea în serios (dacă îmbunătățeși un algoritm de la 7n operații la 5n operații, nu-mi e clar că ai îmbunătățit timpul de rulare;fix de-asta teoreticienii sunt mai mândrii când obțin îmbunătățiri asimptotice, nu doar de constantă).

În acest model, să calculezi un hash e O(1) pt hash functions simple (vezi universal hashing pe  wikipedia). Cel mai simplu universal hashing face doar o îmulţire cu o constantă (un număr mare pe int care e musai să fie impar) urmat un shift. Ceva în genul:
Cod:
#define BITS_PER_HASH 14

int a;
void init_hash(void)
{
   srand(time(NULL));
   a = rand()*2 +1;
}

int hash(int x)
{
  return(((unsigned)a*x) >> (32-BITS_PER_HASH));
}

În această teorie, hash tables sunt algoritmi randomizaţi, iar running time chiar e O(1) pe operaţie (operaţie = insert /delete/lookup); bineînțeles, e vorba de expected running time, fiindcă nu e algoritm deterministic. Sunt multe hash tables și hash functions, care în combinații diverse obţin caracteristici variabile. Spre exemplu, unele combinații au varianță mică în timpul de rulare, etc.

Acuma, care e complexitatea la radix sort? Dacă nu putem ignora w, o să depindă de w. În practică w=32,  dar ce contează? În practică totul e o constantă,  inclusiv n (să zicem un milion), luăm acele constante, le  băgăm în formula de running time, și estimăm cam cât de bine merge algoritmul. Radix sort depinde de cât spațiu ai pt algoritm, fiindcă faci un tabel cu spațiul ăla și indexezi în el ca să distribui valorile. Să notăm spațiul cu S (dacă faci byte cu byte, S=256). Atunci folosești radix S,iar timpul total o să fie fix O(n w/lgS).  Acest timp nu e O(n) decât dacă ai spaţiu de counting sort, în care caz problema devine trivială (nu-ţi trebe nici hashing, faci un vector mare). Dar cât e S? Cât e disponibil în implementarea ta; în realitate S e un #define în cod. Fără presupuneri suplimentare, în teorie putem spune sigur că S>= n, fiindcă spaţiu O(n) e optim (trebe măcar să stocăm inputul). Folosind acest raţionament, timpul de rulare la radix sort e maxim O(nw/lg n), care nu e liniar deloc.

Normal că radix sort rămâne cel mai rapid algoritm de sortare în practică şi e mult mai bun ca quicksort, heapsort şi alţi algoritmi. Dar algoritmii ăştia chiar rulează în nlgn operații, şi dacă băgăm în formule valorile reale de n, w şi S, devine clar că radix sort va merge mai bine. Nu apare nicio surpriză aici; radix sort merge în ceva timp mai mare ca O(n) și mai mic ca O(nlg n), care depinde de w (un parametru necunoscut când ne gândim teoretic).

Totuşi, radix sort nu merge în O(n). Aici teoria chiar ne spune ceva interesant. Anume, ne spune că dacă ai de ales între radix sort şi hashing (care dă O(n) curat), ar trebui să alegi hashing. N-am avut timp să codez dar cred că e corect ce spune teoria aici şi la problema asta hashing chiar merge mai repede (cel puțin dacă implementezi bine). Legat de implementare, e clar că hashing e un pic mai neevident de codat și optimizat; la capitolul implementare e clar care soluție câștigă, și teoria algoritmică nu are nimic de spus despre asta.
« Ultima modificare: Decembrie 14, 2011, 21:04:31 de către Mihai Patrascu » Memorat
Cosmin
Echipa infoarena
Nu mai tace
*****

Karma: 351
Deconectat Deconectat

Mesaje: 1.799



Vezi Profilul
« Răspunde #22 : Decembrie 15, 2011, 00:56:13 »

@Mihai, mersi de contributie. Ar fi mers comentariul tau ca spot separat pe blog Smile.
Legat de problema elementelor distincte, ai ceva referinte curate?
Bun "rule of thumb" hashing > radix sort > quick sort.

Pare ca in industrie lumea nu foloseste radix sort asa des, probabil pt ca trebuie sa sorteze obiecte nu intregi.

M-am uitat la cateva limbaje sa vad cum fac:

C are implementat un quick sort care e tunat sa nu aiba probleme cu cazuri degenerate si sa aiba complexitate O(n log n) in general. Jon Bentley, autorul are un talk de care v-am mai spus: http://www.youtube.com/watch?v=aMnn0Jq0J-E

In C++ se foloseste intro sort.
http://www.sgi.com/tech/stl/sort.html (documentatie)
www.sgi.com/tech/stl/stl_algo.h (cod sursa)

Python pare ca foloseste un merge sort modificat, si daca sirul de la intrare e scurt face binary insertion sort.
http://hg.python.org/cpython/file/1eae8154c109/Objects/listsort.txt (explicatie detaliata)
http://hg.python.org/cpython/file/1eae8154c109/Objects/listobject.c (cod sursa)

Java pare ca foloseste merge sort pentru liste, varianta de quick sort din C pentru siruri de bytes, floats, ints si un  merge sort modificat pt siruri de obiecte.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Arrays.html (documentatie)
http://www.docjar.com/html/api/java/util/Arrays.java.html (cod)
Uitandu-ma la cod vad ca cei din Java sunt in proces de tranzitie pe sortul din python pentru obiecte generale.


E interesant ca pentru sortari distribuite in MapReduce sau Hadoop, iau intai un sample al datelor. Asa se prind de distributie, pentru a partitiona datele in bucati de marime cat de cat egala si a le copia doar o data prin retea la calculatorul care le va sorta pe final. Pasul asta e important pentru ca la sortari distribuite se petrece mult timp in pasul de copiere al datelor pe retea.La terasort/petasort obiectele sortate erau siruri de 100 de bytes, deci presupun ca se foloseste radix sort pentru sortarea locala (nu am gasit nici o referinta externa la hadoop sau mapreduce care sa zica clar ce fac pt sortare locala).
http://googleresearch.blogspot.com/2011/09/sorting-petabytes-with-mapreduce-next.html
http://research.google.com/archive/mapreduce-osdi04.pdf
Memorat
rgrig
De-al casei
***

Karma: 46
Deconectat Deconectat

Mesaje: 144



Vezi Profilul WWW
« Răspunde #23 : Decembrie 15, 2011, 02:40:28 »

Varianta din Python e descrisă ceva mai pe scurt în Wikipedia: Timsort.

Am scris mai demult ceva de radix sort. (Dacă vă uitați, aveți grijă că folosesc alte litere.) Citind acum în diagonală văd două lucruri care nu cred că s-au spus mai sus.
1. Numarul optim de bucketuri depinde de lungimea listei sortate, dar nu depinde de numărul de biți pe cuvânt.
2. O implementare de mână e cam de 2--3 ori mai rapidă decât std::sort.
« Ultima modificare: Decembrie 15, 2011, 03:04:39 de către Radu Grigore » Memorat
Cosmin
Echipa infoarena
Nu mai tace
*****

Karma: 351
Deconectat Deconectat

Mesaje: 1.799



Vezi Profilul
« Răspunde #24 : Decembrie 15, 2011, 03:57:10 »

Hmm, cred ca am incercat radix sort pentru suffix arrays si tin minte ca std::sort() mergea mai repede. (http://infoarena.ro/siruri-de-sufixe) Ar trebui sa incerc din nou.
Memorat
Pagini: [1] 2   În sus
  Imprimă  
 
Schimbă forumul:  

Powered by SMF 1.1.19 | SMF © 2006-2013, Simple Machines