C # Binary Trees og Ordbøker

stemmer
15

Jeg sliter med begrepet når man skal bruke binære søketrær og når man skal bruke ordbøker.

I søknaden min gjorde jeg et lite eksperiment som brukte C5 bibliotek TreeDictionary(som jeg tror er en rød-svart binært søketre), og C # ordbok. Ordboken var alltid raskere på add / finne drift og også alltid brukt mindre plass i minnet. For eksempel på 16809 <int, float>oppføringer, ordlisten brukt 342 KiB mens treet brukes 723 KiB.

Jeg tenkte at BST er skulle være mer minne effektive, men det virker som en node i treet krever flere bytes enn én oppføring i en ordbok. Hva gir? Er det et punkt der BST er er bedre enn ordbøker?

Også, som et underspørsmål, vet noen om det er en raskere + mer minne effektiv datastruktur for lagring av <int, float>parvis for ordboken typen adgang enn hver av de nevnte strukturene?

Publisert på 28/01/2010 klokken 01:46
kilden bruker
På andre språk...                            


6 svar

stemmer
1

Det virker for meg at du gjør en prematur optimalisering.

Hva jeg vil foreslå for deg er å lage et grensesnitt for å isolere hvilken struktur du faktisk bruker, og deretter implementere grensesnittet ved hjelp av ordbok (som synes å fungere best).

Hvis minnet / ytelse blir et problem (som sannsynligvis ikke for 20k- tall), så kan du lage andre grensesnitt implementeringer, og sjekke hvilken som fungerer rekorder. Du trenger ikke å endre nesten alt i resten av koden (unntatt som implementering du bruker).

Svarte 28/01/2010 kl. 02:26
kilden bruker

stemmer
1

Det gir mening at et tre node vil kreve mer lagringsplass enn en ordbok oppføring. En binærtreet node trenger å lagre verdien og både venstre og høyre subtre. Den generiske Dictionary<TKey, TValue>er implementert som en nøkkeltabell som - jeg antar - enten bruker en lenket liste for hver bøtte (verdi pluss en peker / referanse) eller annen form for tilordning (bare den verdi). Jeg måtte ha en titt på Reflektor for å være sikker, men i den hensikt å dette spørsmålet tror jeg ikke det er så viktig.

Den sparsomme hash tabellen, desto mindre effektiv når det gjelder lagring / minne. Hvis du oppretter en hash table (ordbok) og initial sin kapasitet til 1 million, og bare fylle den med 10.000 elementer, så er jeg ganske sikker på at det ville spise opp mye mer minne enn en BST med 10.000 noder.

Likevel, jeg vil ikke bekymre deg om noe av dette hvis mengden av noder / nøkler er bare i tusenvis. Som kommer til å bli målt i kilobytes, i forhold til GB fysisk RAM.


Hvis spørsmålet er "hvorfor ville du ønsker å bruke et binært tre i stedet for en hash table?" Så det beste svaret IMO er at binære trær er bestilt mens hash tabeller er det ikke. Du kan bare søke en hash tabell for nøkler som er nøyaktig lik noe; med et tre, kan du søke etter en rekke verdier, nærmest verdi, etc. Dette er en ganske viktig forskjell hvis du oppretter en indeks eller noe lignende.

Svarte 28/01/2010 kl. 02:39
kilden bruker

stemmer
0

Grensesnittet for et tre og en Hash bord (som jeg gjetter er hva ordbok er basert én) bør være svært lik. Alltid rullerende rundt tastet oppslag.

Jeg hadde alltid tenkt Ordbok var bedre for å skape ting en gang og så deretter gjøre masse oppslag på det. Mens a Tree var bedre hvis du skulle endre den betydelig. Men jeg vet ikke hvor jeg plukket den ideen opp fra.

(Funksjonelle språk ofte bruker trær som grunnlag for de samlinger som du kan re-bruker mest av treet hvis du gjør små endringer til det).

Svarte 28/01/2010 kl. 02:40
kilden bruker

stemmer
0

Du er ikke å sammenligne "epler med epler", en BST vil gi deg en organisert representasjon mens en ordbok kan du gjøre et oppslag på en nøkkelverdi par (i ditt tilfelle).

Jeg ville ikke forvente mye størrelse i minne fotavtrykk mellom to, men ordlisten vil gi deg en mye raskere oppslag. For å finne et element i en BST deg (potensielt) må krysse hele treet. Men for å gjøre en dictnary oppslags du bare oppslag basert på nøkkelen.

Svarte 28/01/2010 kl. 03:05
kilden bruker

stemmer
9

Jeg tenkte at BST er skulle være mer minne effektive, men det virker som en node i treet krever flere bytes enn én oppføring i en ordbok. Hva gir? Er det et punkt der BST er er bedre enn ordbøker?

Jeg har personlig aldri hørt om et slikt prinsipp. Enda det bare et generelt prinsipp, ikke en kategorisk faktum etset i stoffet i universet.

Vanligvis Ordbøker er egentlig bare en fancy wrapper rundt en rekke lenkede lister. Du setter inn i ordlisten noe sånt som:

LinkedList<Tuple<TKey, TValue>> list =
    internalArray[internalArray % key.GetHashCode()];
if (list.Exists(x => x.Key == key))
    throw new Exception("Key already exists");
list.AddLast(Tuple.Create(key, value));

Så det er nesten O (1) drift. Ordlisten benytter O (internalArray.Length + n) hukommelse, hvor n er antallet av elementer i samlingen.

Generelt BSTs kan gjennomføres som:

  • koblede-lister, som bruker O (n) mellomrom, hvor N er antall elementer i samlingen.
  • matriser , som bruker O (2 t - n) plass hvor h er høyden av treet og n er antallet elementer i samlingen.
    • Siden rød-svart trær har en begrenset høyde på O (1,44 * n), bør en matrise gjennomføringen har en avgrenset minnebruken på ca. O (2 1.44n - n)

Odds er, C5 TreeDictionary er implementert ved hjelp arrays, som sannsynligvis er ansvarlig for bortkastet plass.

Hva gir? Er det et punkt der BST er er bedre enn ordbøker?

Ordbøker ha noen uønskede egenskaper:

  • Det kan ikke være nok continugous blokker av minne til å holde din ordboken, selv om minnet kravene er mye mindre enn enn den totale tilgjengelig RAM.

  • Evaluering av hash-funksjon kan ta et vilkårlig lange tidsrom. Trenger, for eksempel bruke Reflector å undersøke System.String.GetHashCodemetoden - du vil merke hashing en streng alltid tar O (n) tid, noe som betyr at det kan ta lang tid for svært lange strenger. På hånden, sammenligne strenger for ulikhet nesten alltid raskere enn hashing, siden det kan kreve å se på bare de første tegn. Sin helt mulig for tre innsatser å være raskere enn ordbok innsatser hvis hash-kode evalueringen tar for lang tid.

    • Int32 sin GetHashCodemetode er bokstavelig talt rett return this, så du vil bli hardpressed å finne en sak der en hashtabellen med int nøkler er tregere enn et tre ordbok.

RB Trees har noen ønskelige egenskaper:

  • Kan finne / fjerne minimums- og maksimums elementer i O (log n) tid, sammenlignet med O (n) tid ved hjelp av en ordbok.

  • Hvis et tre er implementert som lenket liste i stedet for en matrise, er treet som regel mer plass effektiv enn en ordbok.

  • Likeledes er det latter lett å skrive uforanderlige versjoner av trær som støtter innsatsen / oppslag / slette i O (log n) tid. Ordbøker ikke tilpasse seg godt til uforanderlighet, siden du trenger å kopiere hele interne array for hver operasjon (faktisk, jeg har sett noen arraybaserte implementeringer av uforanderlige finger trær, en slags generell ordbok datastruktur, men gjennomføringen er svært kompleks).

  • Du kan bla gjennom alle elementene i et tre i sortert rekkefølge i konstant plass og O (n) tid, mens du trenger å dumpe en hash tabell i en matrise og sortere det for å få samme effekt.

Så, valg av datastruktur er egentlig avhengig av hvilke egenskaper du trenger. Hvis du bare vil ha en uordnet bag og kan garantere at hash-funksjon evaluere raskt, gå med en Net ordbok. Hvis du trenger en ordnet bag eller har en treg kjører hash-funksjon, gå med TreeDictionary.

Svarte 28/01/2010 kl. 03:16
kilden bruker

stemmer
0

En balansert BST er å foretrekke hvis du trenger for å beskytte datastruktur fra latency pigger og hash kollisjoner angrep.

Den tidligere skjer når en matrise-støttede struktur vokser en blir endret størrelse, sistnevnte er en uunngåelig egenskap av nøkkeltransformeringsalgoritme som et fremspring fra uendelig plass til et begrenset utvalg heltall.

Et annet problem i .NET er at det er LOH, og med en tilstrekkelig stor ordbok du kjører inn i et LOH fragmentering. I dette tilfellet kan du bruke en BST, betaler en pris på større algoritmisk kompleksitet klasse.

Kort sagt, med en BST støttet av tildeling haugen får du verste fall O (log (N)) tid, med hashtabellen du får O (N) worst case tid.

BST kommer til en pris på O (log (N)) gjennomsnittlig tid, verre cache lokalitet og flere heap bevilgninger, men det har ventetid garantier og er beskyttet mot ordbokangrep og minne fragmentering.

Verdt å merke seg at BST er også en gjenstand for å minne fragmentering på andre plattformer, ikke ved hjelp av en komprimerende søppel samler.

Når det gjelder minnekapasiteten, er det NET Dictionary`2 klasse mer minne effektiv, fordi den lagrer data som et off-haug lenket liste, som bare lagrer verdien og offsetinformasjon. BST har til å lagre objekt header (som hver node er en klasse eksempel på haugen), to pekere, og noen forstørrede treet data for balanserte trær. For eksempel vil en rød-svart tre trenger en boolsk tolket som farge (rød eller svart). Dette er minst 6 maskin ord, hvis jeg ikke tar feil. Så, hver node i en rød-svart tre på 64-bit system er et minimum av:

3 ord for overskriften = 24 byte 2 ord for de underordnede pekerne = 16 byte ord en for den farge = 8 bytes minst ett ord for verdien 8+ bytes = 24 + 16 + 8 + 8 = 56 byte (byte +8 hvis treet benytter en foreldrenoden peker).

Samtidig ville minimumsstørrelsen på oppslagsord være bare 16 bytes.

Svarte 10/12/2018 kl. 13:18
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more