Hva er fordelene med binære søketrær enn hash tabeller?
Hash tabeller kan slå opp et hvilket som helst element i Theta (1) tid, og det er like enkelt å legge til et element .... men jeg er ikke sikker på fordelene som går den andre veien rundt.
Hva er fordelene med binære søketrær enn hash tabeller?
Hash tabeller kan slå opp et hvilket som helst element i Theta (1) tid, og det er like enkelt å legge til et element .... men jeg er ikke sikker på fordelene som går den andre veien rundt.
En "fordel" av et binært tre er at det kan bli krysset til listen av alle elementer i rekkefølge. Dette er ikke mulig med en Hash-tabell, men er ikke en normal drift av en design i en kryptert struktur.
En hashtabellen ville ta opp mer plass når det første laget - det vil ha tilgjengelige plasser for de elementene som er ennå å bli satt inn (om ikke de noen gang er satt inn), vil et binært søketre bare være så stor som det er behov for å være. Også når en hash-tabell trenger mer plass, utvide til en annen struktur kan være tidkrevende, men det kan avhenge av gjennomføringen.
Husk at Binary Søk Trees (referanse-basert) er minneeffektiv. De trenger ikke reservere mer minne enn de må.
For eksempel, hvis en hash-funksjon har en rekke R(h) = 0...100, så må for å tildele en rekke 100 (pekere-til) elementer, selv om man bare hashing 20 elementer. Hvis du skulle bruke et binært søketre for å lagre den samme informasjonen, ville du bare tildele så mye plass som du trengte, så vel som noen metadata om koblinger.
En binærtreet er tregere til å søke og sette inn, men har veldig fin funksjon av infiks traversering som i hovedsak betyr at du kan iterere gjennom nodene i treet i en sortert rekkefølge.
Itera gjennom oppføringene i en hash table bare ikke mye fornuftig, fordi de er alle spredt i minnet.
En binært søketre kan implementeres med en vedvarende grensesnitt, der et nytt tre returneres, men det gamle treet fortsetter å eksistere. Implementert nøye, gamle og nye trær aksjer de fleste av sine noder. Du kan ikke gjøre dette med en standard hash table.
De viktigste fordelene med et binært tre over en hash tabellen er at det binære treet gir deg ytterligere to operasjoner du ikke kan gjøre (lett, raskt) med en hash table
finne det element som ligger nærmest (ikke nødvendigvis lik) en vilkårlig nøkkelverdien (eller nærmest over / under)
iterere gjennom innholdet i treet i sortert rekkefølge
De to er koblet - det binære treet holder innholdet i en sortert rekkefølge, så ting som krever at sortert rekkefølge er enkelt å gjøre.
A (balansert) binært søketre har også den fordelen at den asymptotiske kompleksitet er faktisk en øvre grense, mens "konstant" tider for hash-tabeller er amortisert ganger: Hvis du har en uegnet hash-funksjon, kan du ende opp nedverdigende til lineær tid , snarere enn konstant.
Hvis du ønsker å få tilgang til data i en sortert måte, da en sortert liste må opprettholdes parallelt med hash tabellen. Et godt eksempel er ordbok i Net. (se http://msdn.microsoft.com/en-us/library/3fcwy8h6.aspx ).
Dette har den bivirkning av ikke bare bremse innsatser, men det forbruker en større mengde minne enn et B-tre.
Videre, siden en b-treet er sortert, er det enkelt å finne områder av resultater, eller utføre fagforeninger eller fusjonerer.
I tillegg til alle de andre gode kommentarer:
Hash tabeller generelt har bedre cache atferd som krever mindre minne leser i forhold til et binært tre. For en hash table du normalt bare medføre en enkelt lese før du har tilgang til en referanse holde dine data. Den binært tre, hvis det er en balansert variant krever noe i størrelsesorden k * lg (n) hukommelse leses av en eller annen konstant k.
På den annen side, hvis en fiende kjenner din hash-funksjon fienden kan håndheve din hash table å gjøre kollisjoner, i stor grad hindrer ytelsen. Løsningen er å velge hash-funksjon tilfeldig fra en familie, men en BST har ikke denne ulempen. Også når hash table trykket vokser for mye, du ofte har en tendens til å enlargen og omfordele hash tabellen som kan være en kostbar operasjon. BST har enklere oppførsel her og ikke tendens til å plutselig allokere mye data og gjøre en rehashing operasjon.
Trærne har en tendens til å være det optimale gjennomsnittlige datastrukturen. De kan virke som lister, lett kan deles for parallelldrift, har rask fjerning, innsetting og oppslag i størrelsesorden O (lg n) . De gjør ingenting spesielt godt, men de har ikke noe overdrevent dårlig oppførsel heller.
Endelig BSTs er mye enklere å gjennomføre i (ren) funksjonelle språk i forhold til hash-tabeller og de krever ikke destruktive oppdateringer som skal gjennomføres (den utholdenhet argument ved Pascal ovenfor).
Hovedfordelen med nøkkeltabell er at den gjør det nesten alle op i ~ = O (1). Og det er veldig lett å forstå og implementere. Det gjør løse mange "intervju problemer" effektivt. Så hvis u ønsker å knekke en koding intervju, må beste venner med hash table ;-)
BSTs gir også "findPredecessor" og "findSuccessor" operasjoner (for å finne neste minste og nest største elementer) i O (LOGN) tid, som også kan være svært hendig operasjoner. Hash tabell kan ikke gi i den tiden effektivitet.
Det avhenger også av bruk, kan Hash å finne eksakt match. Hvis du ønsker å søke på en rekke så BST er valget. Tenk deg at du har en masse data e1, e2, e3 ..... no.
Med hash tabellen kan du finne noe element i konstant tid.
Hvis du ønsker å finne områdeverdier større enn E41 og mindre enn E8 kan BST raskt finne det.
Det viktigste er hash-funksjonen brukes for å unngå en kollisjon. Selvfølgelig kan vi ikke helt unngå en kollisjon, og da vi ty til kjeding eller andre metoder. Dette gjør gjenfinning ikke lenger konstant tid i verste fall.
Når full, har nøkkeltabell for å øke dets grabb størrelse og kopiere over alle elementer på nytt. Dette er en ekstra kostnad ikke til stede over BST.
En fordel som ingen andre har påpekt er at binært søketre lar deg gjøre utvalg søk effektivt.
For å illustrere min idé, jeg ønsker å gjøre et ekstremt tilfelle. Si at du ønsker å få alle de elementene som har nøklene er mellom 0 til 5000. Og faktisk er det bare ett slikt element og 10000 andre elementer som har nøkler som ikke er i området. BST kan gjøre range søk ganske effektivt siden den ikke søke et subtre som er umulig å ha svaret.
Mens, hvordan kan du gjøre utvalg søkene i en hash table? Du enten må gjenta hver bøtte plass, som er O (n), eller du må se etter om hver av 1,2,3,4 ... opp til 5000 eksisterer. (Det som om de nøkler mellom 0 og 5000 finnes et uendelig set? For eksempel nøkler kan være desimaler)
En hash table er et uordnet datastruktur, Når du utformer en mobiltelefon, ønsker du å holde så mye data som mulig tilgjengelig for datalagring. En nøkkeltabell er en ikke-sorterte datastruktur - noe som betyr at det ikke holder sine elementer i noen bestemt rekkefølge. Så, hvis du bruker en hash tabell for en mobiltelefon adressebok, så du vil trenge ekstra minne til å sortere verdiene fordi du vil definitivt trenger å vise verdiene i alfabetisk rekkefølge - det er en adressebok tross alt. Så, ved å bruke en hash tabell må du sette av minne til å sortere elementer som ellers ville ha bli brukt som lagringsplass. Men binært søketre er en sorterte data structure.Because et binært søketre er allerede sortert, vil det ikke være nødvendig å kaste bort minne eller behandlingstid sortering poster i en mobiltelefon. Som vi har nevnt tidligere, gjør et oppslag eller en innsats på et binært tre er tregere enn å gjøre det med en hash table, men en mobiltelefon adressebok vil nesten aldri har mer enn 5000 oppføringer. Med et så lite antall oppføringer, vil et binært søketre er O (log (n)) definitivt være rask nok. Så, gitt all denne informasjonen, er et binært søketre datastrukturen som du bør bruke i dette scenariet, siden det er et bedre valg enn en hash table.
Hash Tabeller er ikke bra for indeksering. Når du søker etter en rekke, BSTs er bedre. Det er grunnen til at de fleste databaseindeksene bruke B + trær i stedet for Hash Tables
Fra Sprengning av kode intervju, 6. utgave
Vi kan implementere hash tabellen med et balansert binært søketre (BST). Dette gir oss en O (log n) oppslag. Fordelen med dette er potensielt bruke mindre plass, siden vi ikke lenger tildele et stort utvalg. Vi kan også iterere gjennom tastene i rekkefølge, noe som kan være nyttig noen ganger.
Klassene HashSet og tabell er unordered samlinger. Det er ikke åpenbart fra grensesnittet (og kan være noe annet), men hash tabeller har blitt gjennomført ved hjelp av AVL Trees. Dette betyr at den hash-koden ikke blir redusert ved modulo av en matrise (mindre kollisjoner) og det betyr også at det ikke er noen rehashing av en matrise som skal gjøres (jevnere ytelse). Det faktum at de er unordered samlinger betyr at du bare levere en lik funksjon og en hashCode funksjon - ikke en full comparer som for trær. Så om du bruker en hash table tabell <K, T> eller et binært tre Tre <K, T> avhenger av klasse K - enten det er fullt ut sammenlignbare eller bare likestilling sammenlignbare.
Det finnes tilfeller der datatypen er både sammenlignbare og likestilling sammenlignbare - som String. Dette betyr at HashSet <String> og Set <String> er både mulig. Søk på en hash sett med strenger pleier å være omtrent 10 ganger raskere enn søk på et ordnet sett med strenger. Dersom komparatoren er kostbart da trær avta i forhold til HashTables. Dersom komparatoren er hurtig, (som for heltall og flyter) deretter trærne vil løpe hurtigere enn nøkkeltabeller.
En HashMap er et sett assosiativ array. Så blir din rekke inngangsverdier samlet i bøtter. I et åpent adressering ordningen, har du en peker til en bøtte, og hver gang du legger til en ny verdi i en bøtte, finner du ut hvor i bøtta er det friområder. Det finnes noen måter å gjøre dette-du starter i begynnelsen av bøtte og tilvekst pekeren hver gang og teste om det er okkupert. Dette kalles lineær sondering. Deretter kan du gjøre et binært søk som add, hvor du doble forskjellen mellom begynnelsen av bøtta og hvor du dobbelt opp eller ned hver gang du søker etter en ledig plass. Dette kalles kvadratisk sondering. OK. Nå problemer i begge disse metodene er at hvis bøtta flyter over i de neste bøtter adresse, så må til-
OK. men hvis du bruker en Linked det bør ikke være et slikt problem ikke sant? Ja, I lenkede lister du ikke har dette problemet. Vurderer hver bøtte til å begynne med en lenket liste, og hvis du har 100 elementer i en bøtte det krever at du krysse disse 100 elementer å komme til slutten av Linked derav List.add (Element E) vil ta tid til-
Fordelen med Linked gjennomføringen er at du ikke trenger minnetildeling drift og O (N) overføring / kopi av alle skuffer som i tilfelle av åpen adressering gjennomføring.
Så, hvordan å minimere O (N) operasjon er å konvertere gjennomføringen som for en binært søketre der finner operasjoner er O (log (N)) og du legger elementet i sin posisjon basert på den verdi. Den ekstra funksjon i en BST er at det kommer sortert!
Binære søketrær er godt valg å implementere ordboken hvis nøklene har noen samlet ordre (tastene er sammenlign) definert på dem, og du ønsker å bevare bestillingsinformasjon.
Som BST bevarer ordreinformasjon, gir det deg med fire ekstra dynamisk sett operasjoner som ikke kan utføres (effektivt) med hash tabeller. Disse operasjonene er:
Alle disse operasjonene som hver BST drift har tid kompleksitet O (H). I tillegg alle de lagrede nøkler forbli sortert i BST dermed gjør det mulig å få sortert sekvens av taster bare ved å gå gjennom treet i bestilling.
Oppsummert Hvis alt du ønsker er operasjoner sette inn, slette og deretter fjerne hash table er uslåelig (mesteparten av tiden) i ytelse. Men hvis du vil ha noen eller alle operasjonene nevnt ovenfor bør du bruke en BST, fortrinnsvis en selvbalanserende BST.
Binære søketrær kan være raskere når den brukes med streng nøkler. Spesielt når strengene er lange.
Binære søketrær ved hjelp av sammenligninger for mindre / større som er raske for strykere (når de ikke er like). Så en BST kan raskt svare når en streng ikke er funnet. Når det er funnet vil det trenger å gjøre bare en full sammenligning.
I en nøkkeltabell. Du må beregne hash av strengen, og dette betyr at du trenger å gå gjennom alle bytes minst en gang å beregne hash. Så igjen, når motpost er funnet.