C # Binaire Bomen en Woordenboeken

stemmen
15

Ik heb moeite met het concept van wanneer binaire zoekboom en wanneer gebruik van woordenboeken te gebruiken.

In mijn aanvraag heb ik een klein experiment dat de C5 bibliotheek die wordt gebruikt TreeDictionary(waarvan ik denk dat een rood-zwarte binaire zoekboom), en de C # woordenboek. Het woordenboek is altijd sneller bij add / vinden operaties en ook altijd gebruikt minder geheugenruimte. Bijvoorbeeld, op 16.809 <int, float>inzendingen, het woordenboek gebruikt 342 KiB terwijl de boom gebruikte 723 KiB.

Ik dacht dat BST's zouden meer geheugen efficiënt te zijn, maar het lijkt erop dat een knooppunt van de boom vereist meer bytes dan een vermelding in een woordenboek. Wat geeft? Is er een punt waar de BST's zijn beter dan woordenboeken?

Ook als een kant vraag, weet iemand of er een snellere + meer geheugen efficiënter datastructuur voor het opslaan van <int, float>paren voor woordenboek soort toegang dan elk van de genoemde structuren?

De vraag is gesteld op 28/01/2010 om 02:46
bron van user
In andere talen...                            


6 antwoorden

stemmen
1

Het lijkt me dat je aan het doen bent een voortijdige optimalisatie.

Wat ik zou willen voorstellen aan u is om een ​​interface te isoleren welke structuur je daadwerkelijk gebruik, en vervolgens de uitvoering van de interface met behulp van de Dictionary (die lijkt het beste te werken) te creëren.

Als het geheugen / prestaties wordt een probleem (die waarschijnlijk niet voor 20k- nummers), dan kun je andere interface-implementaties maken en controleren welke één records werkt. Je zal niet nodig om bijna alles in de rest van de code (behalve die de uitvoering u gebruikt) te wijzigen.

antwoordde op 28/01/2010 om 03:26
bron van user

stemmen
1

Het heeft geen zin dat een boom knooppunt meer opslagruimte dan een woordenboek vermelding zou vereisen te maken. Een binaire boomstructuur moet de waarde en zowel de linker en rechter sub-bomen te slaan. De generieke Dictionary<TKey, TValue>is geïmplementeerd als een hash-tabel, die - ik ga ervan uit - ofwel maakt gebruik van een gekoppelde lijst voor elk segment (waarde plus een pointer / referentie) of een soort van opnieuw in kaart brengen (alleen de waarde). Dan moet ik een kijkje in Reflector om zeker te zijn, maar voor het doel van deze vraag die ik denk niet dat het zo belangrijk.

De zeldzamer de hashtabel, hoe minder efficiënt in termen van opslag / het geheugen. Als u een hash tabel (woordenboek) te creëren en te initialiseren zijn capaciteit tot 1 miljoen, en alleen vullen met 10.000 elementen, dan ben ik er vrij zeker van dat het zou opeten veel meer geheugen dan een BST met 10,000 knooppunten.

Toch zou ik geen zorgen te maken over een van deze, indien het bedrag van de nodes / toetsen is alleen in de duizenden. Dat zal worden gemeten in het kilobytes, in vergelijking met gigabytes van fysiek RAM-geheugen.


Als de vraag is "waarom zou je willen een binaire boom te gebruiken in plaats van een hash table?" Dan IMO is het beste antwoord dat binaire bomen worden besteld terwijl hash tabellen niet. U kunt alleen zoeken een hash-tabel voor sleutels die exact gelijk is aan iets te zijn; met een boom, kunt u zoeken naar een bereik van waarden, dichtstbijzijnde waarde, enz. Dit is een vrij belangrijk onderscheid als je het creëren van een index of iets dergelijks.

antwoordde op 28/01/2010 om 03:39
bron van user

stemmen
0

De interface voor een boom en een Hash tafel (die ik gok dat is wat uw woordenboek is gebaseerd één) moeten zeer vergelijkbaar zijn. Altijd draait om ingetoetst lookups.

Ik had altijd gedacht een Dictionary beter was voor één keer het maken van dingen en dan doet dan veel lookups op. Terwijl een Boom beter was als je het aanzienlijk modificeren. Echter, ik weet niet waar ik pakte dat idee uit.

(Functionele talen maken vaak gebruik van bomen als basis voor deze collecties als je kunt hergebruiken het grootste deel van de boom als u kleine wijzigingen aan te brengen is).

antwoordde op 28/01/2010 om 03:40
bron van user

stemmen
0

Je bent niet te vergelijken "appels met appels", een BST krijgt u een geven besteld representatie, terwijl een woordenboek kunt u een zoekopdracht doen op een belangrijke waarde hebben (in uw geval).

Ik zou niet veel te verwachten in het geheugen opslaan footprint tussen de 2, maar het woordenboek zal je een veel snellere lookup geven. Om een ​​item in een BST vind je (eventueel) nodig om de hele boom doorkruisen. Maar om een ​​dictnary lookup je gewoon opzoeken op basis van de sleutel.

antwoordde op 28/01/2010 om 04:05
bron van user

stemmen
8

Ik dacht dat BST's zouden meer geheugen efficiënt te zijn, maar het lijkt erop dat een knooppunt van de boom vereist meer bytes dan een vermelding in een woordenboek. Wat geeft? Is er een punt waar de BST's zijn beter dan woordenboeken?

Ik heb persoonlijk nog nooit gehoord van een dergelijk beginsel. Zelfs nog, het was slechts een algemeen principe, niet een categorische feit geëtst in het weefsel van het universum.

In het algemeen, Woordenboeken zijn eigenlijk alleen een fancy wrapper rond een reeks van gekoppelde lijsten. U invoegen in het woordenboek iets als:

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));

Dus het is bijna O (1) werking. Het woordenboek maakt gebruik van O (internalArray.Length + n) geheugen, waarbij n aantal items in de collectie.

In het algemeen BSTS kan worden uitgevoerd als:

  • gekoppelde lijsten, die O (n) ruimte, waarbij n het aantal items in de collectie gebruikt.
  • arrays die gebruikt O (2 h - n) ruimte waarin h de hoogte van de boom en n is het aantal items in de collectie.
    • Aangezien rood-zwarte bomen hebben een begrensde hoogte O (1,44 * n), moet een array implementatie een begrensd geheugengebruik van ongeveer O (2 hebben 1.44n - n)

Odds zijn, de C5 TreeDictionary wordt geïmplementeerd met behulp van arrays, die waarschijnlijk verantwoordelijk is voor de verspilde ruimte.

Wat geeft? Is er een punt waar de BST's zijn beter dan woordenboeken?

Woordenboeken hebben een aantal ongewenste eigenschappen:

  • Er kan niet genoeg continugous blokken van het geheugen op uw woordenboek te houden, zelfs als het geheugen eisen zijn veel minder dan dan de totale beschikbare RAM.

  • Evalueren van de hashfunctie kan een willekeurig lange tijd duren. Strings, bijvoorbeeld, gebruiken Reflector aan de onderzoeken System.String.GetHashCodemethode - u zult merken hashen van een reeks vindt altijd O (n) tijd, wat betekent dat het kan geruime tijd duren voor een zeer lange reeksen. Aan de ene kant, het vergelijken van strings voor ongelijkheid bijna altijd sneller dan hashing, omdat hij kan verlangen te kijken naar alleen de eerste paar tekens. Haar volle mogelijk boom inzetstukken sneller dan woordenboek inserts zijn als hash-code evaluatie te lang duurt.

    • Int32's GetHashCodemethode is letterlijk net return this, dus je zou hardpressed om een zaak te vinden waarin een hash met int toetsen is langzamer dan een boom woordenboek.

RB Bomen hebben een aantal wenselijke eigenschappen:

  • U kunt vinden / verwijderen van de Min en Max elementen in O (log n) tijd, in vergelijking met O (n) tijd met behulp van een woordenboek.

  • Als een boom wordt geïmplementeerd als verbonden lijst in plaats van een array, de boom is meestal meer ruimte efficiënter dan een woordenboek.

  • Ook zijn belachelijk makkelijk te schrijven onveranderlijke versies van de bomen welk inzetstuk / lookup ondersteunen / verwijderen in O (log n) tijd. Woordenboeken niet goed aanpassen aan onveranderlijkheid, omdat je nodig hebt om de gehele inwendige reeks te kopiëren voor elke operatie (eigenlijk, ik heb een aantal array-gebaseerde implementaties van onveranderlijke vinger bomen, een soort algemene doeleinden woordenboek datastructuur gezien, maar de uitvoering is zeer complex).

  • U kunt alle elementen in een boom te doorlopen in gesorteerde volgorde voortdurend in de ruimte en O (n) tijd, terwijl je nodig hebt om een ​​hash-tabel dumpen in een array en te sorteren dat om hetzelfde effect te krijgen.

Dus, de keuze van de datastructuur echt afhankelijk van welke eigenschappen je nodig hebt. Als je wil gewoon een ongeordende zak en kan garanderen dat uw hash-functie snel te evalueren, te gaan met een .Net Dictionary. Als u een geordende tas nodig hebt of een langzaam draaiende hash-functie, ga met TreeDictionary.

antwoordde op 28/01/2010 om 04:16
bron van user

stemmen
0

Een evenwichtige BST is beter als je nodig hebt om uw gegevens structuur te beschermen tegen latentie spikes en hash botsingen aanvallen.

Eerstgenoemde gebeurt wanneer een array-backed structuur groeit een verkleind wordt, dit orgaan een onvermijdelijke eigenschap van hashingalgoritme als projectie van oneindige ruimte beperkte integer bereik.

Een ander probleem in .NET is dat er LOH, en met een voldoende groot woordenboek je in een LOH fragmentatie. In dit geval kunt u een BST gebruiken, het betalen van een prijs van grotere algoritmische complexiteit klasse.

Kortom, met een BST gesteund door de toewijzing hoop je krijgt het slechtste geval O (log (N)) de tijd, met hashtable je O (N) het slechtste geval tijd.

BST komt op een prijs van O (log (N)) gemiddelde tijd, erger cache plaats en nog veel meer hoop toewijzingen, maar het heeft latency garanties en is beschermd tegen dictionary-aanvallen en het geheugen fragmentatie.

Vermeldenswaard dat BST is ook een onderwerp om het geheugen fragmentatie op andere platformen, niet met behulp van een verdichten garbage collector.

Wat betreft de grootte van het geheugen, het .NET Dictionary`2 klasse is meer geheugen efficiënter, omdat deze gegevens als een off-heap gelinkte lijst, die uitsluitend bewaart waarde opslaat en offset informatie. BST moet objectkop slaan (zoals elk knooppunt een klasse-instantie op de heap), twee pointers en sommige Augmented boom gegevens gebalanceerde bomen. Bijvoorbeeld, een rood-zwarte boom een ​​boolean geïnterpreteerd als kleur (rood of zwart) nodig. Dit is ten minste 6 machine woorden, als ik me niet vergis. Dus, elk knooppunt in een rood-zwarte boom op 64-bit systeem is een minimum van:

3 woorden van de kop = 24 bytes 2 woorden voor het kind wijzers = 16 bytes 1 woord voor de kleur = 8 bytes Minstens 1 woord de waarde 8+ bytes = 16 + 24 + 8 + 8 = 56 bytes (8 bytes als de boom maakt gebruik van een bovenliggend knooppunt pointer).

Tegelijkertijd zou de minimale grootte van het woordenboek binnenkomst slechts 16 bytes.

antwoordde op 10/12/2018 om 13:18
bron van user

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