Binary search tree (Norsk)

Binære søk trær støtte av tre sentrale virksomheter: innsetting av elementer, sletting av elementer, og oppslag (for å sjekke om en nøkkel er til stede).

SearchingEdit

Søker i et binært søk treet for en bestemt nøkkel kan være programmert med undermapper eller iterativt.

Vi begynne ved å ta utgangspunkt i rotnoden. Hvis treet er null, er det avgjørende vi søker etter ikke finnes i treet. Ellers, hvis nøkkelen er lik som på rot, søket er vellykket og vi kommer tilbake noden. Hvis nøkkelen er mindre enn den som root, søker vi i venstre undertreet., På samme måte, hvis nøkkelen er større enn det av roten, søker vi rett undertreet. Denne prosessen gjentas til det viktige er funnet eller de resterende undertreet er null. Hvis den søkte nøkkelen er ikke funnet etter et null undertreet er nådd, deretter nøkkelen ikke finnes i treet. Dette er enkelt uttrykt som en rekursiv algoritme (implementert i Python):

Den samme algoritmen kan implementeres iterativt:

Disse to eksemplene ikke støtte duplikater, det er, er de avhengige av den for forhold som en total orden.

En kan merke seg at den rekursive algoritmen er halen rekursiv., I et språk som støtter halen samtale optimalisering, den rekursive og iterative eksempler vil kompilere til tilsvarende programmer.

Fordi det i verste fall denne algoritmen må søke fra roten av treet til bladet lengst fra roten, søk operasjonen tar tid i forhold til treets høyde (se treet terminologi). I gjennomsnitt, binære søk trær med Noder tastene har O(log |Noder|) høyde. Imidlertid, i verste fall, binære søk trær kan ha O(|Noder|) høyde, når den ubalanserte treet ligner en lenket liste (utarte treet).,

Søk med duplikater allowedEdit

Dersom ordren forhold er bare en total preorder, en rimelig forlengelse av funksjonaliteten er følgende: i tilfelle av likhet søke ned til bladene. Og gjør det dermed mulig å angi (eller hard-wire) en retning, hvor det skal settes inn et duplikat, enten til høyre eller venstre for alle duplikater i treet så langt. Hvis retningen er hardt kablet, både valg, høyre og venstre, støtter en stabel med inn dupliserte som presse drift og slett som pop drift.,:155

Et binært tre sorter som er utstyrt med slikt søk funksjonen blir stabil.

InsertionEdit

Innsetting begynner som et søk ville begynne; dersom nøkkelen ikke er lik som for roten, søker vi i venstre eller høyre subtrees som før. Til slutt vil vi komme frem til en ekstern node og legg til den nye nøkkel / verdi-par (her kodet som en post «newNode’) som sin høyre eller venstre barn, avhengig av hvilken node som er nøkkelen., Med andre ord, vi undersøke roten og undermapper sett inn den nye noden til venstre undertreet hvis tasten er mindre enn den som root, eller rett undertreet hvis nøkkelen er større enn eller lik roten.

Her er hvordan en typisk binary search tree innsetting kan utføres i et binært tre i C++:

Alternativt, et ikke-rekursive versjonen kan være implementert som dette., Ved hjelp av en pointer-til-pekeren til å holde styr på hvor vi kom fra lar-kode unngå eksplisitt å sjekke for og håndtering av saken der det er behov for å sette inn en node i treet root:

over destruktive prosessuelle variant endrer treet på plass. Den bruker bare konstant heap space (og iterativ versjon bruker konstant stabelen plass, så vel), men den tidligere versjonen av treet er tapt., Alternativt, som i følgende eksempel Python, kan vi rekonstruere alle forfedre satt inn node; noen referanse til den opprinnelige tre rot er gyldig, noe som gjør treet en fast struktur data:

Den delen som er ombygd bruker O(log n) plass i den gjennomsnittlige undervannshuset og O(n) i verste fall.

enten versjon, denne operasjonen krever tid er proporsjonal med høyden på treet i verste fall, som er O(log n) tid i gjennomsnitt sak over alle trær, men O(n) tid i verste fall.,

en Annen måte å forklare innsetting er at for å sette inn en ny node i treet, nøkkelen er første sammenlignet med roten. Hvis tasten er mindre enn roten, det er så sammenlignet med nøkkelen av roten er venstre barn. Hvis tasten er større, det er sammenlignet med roten er høyre barn. Denne prosessen fortsetter inntil den nye noden er sammenlignet med et blad node, og da er det er lagt til som denne noden er til høyre eller venstre for barn, avhengig av sin nøkkel: hvis nøkkelen er mindre enn leaf er viktige, da det er satt som bladet er venstre barn, på annen måte som bladet er høyre barn.,

Det er andre måter å sette inn noder i et binært tre, men dette er den eneste måten å sette inn noder i blader og på samme tid bevare BST struktur.

DeletionEdit

Når du fjerner en node fra en binary search tree det er obligatorisk å opprettholde i-for sekvens av noder. Det er mange muligheter til å gjøre dette. Imidlertid følgende metode som har blitt foreslått av T. Hibbard i 1962 garantier for at de høyder av emnet subtrees er endret av på de fleste en., Det er tre mulige tilfeller å vurdere:

  • for å Slette en node med ingen barn: er det bare å fjerne den noden fra treet.
  • for å Slette en node med ett barn: fjern noden og erstatte det med sitt barn.
  • for å Slette en node D har to barn: velg enten D er i orden forgjenger eller-for etterfølgeren E (se figur). I stedet for å slette D, overskrive sin nøkkel og verdi med E ‘ s. Hvis E ikke har et barn, ta E fra sin tidligere overordnede G. Hvis E har et barn F, det er en rett barnet, slik at det er til å erstatte E i E s forelder.,

Slette en node med to barn fra et binært søk treet. Første lengst til venstre node i høyre undertreet, i rekkefølge etterfølger E, er identifisert. Dens verdi er kopiert inn i node D blir slettet. På ordre etterfølger kan da lett bli slettet fordi den har på det meste ett barn. Den samme metoden fungerer symmetrisk bruke i-for forgjenger C.

I alle tilfeller, når D skjer for å være roten, få erstatning node rot igjen.

Noder med to barn er det vanskeligere å slette., En node er i orden etterfølger sin rett undertreet som er igjen-for de fleste barn, og en node er i orden forgjenger, er den venstre undertreet er riktig-de fleste barn. I begge tilfeller, denne noden har bare ett eller ingen barn i det hele tatt. Slett den, i henhold til en av de to enklere sakene ovenfor.

Konsekvent bruke i-ordre etterfølger eller i ordre forgjenger for hver forekomst av to-barns-saken kan føre til en ubalansert treet, så noen implementasjoner velger det ene eller det andre til forskjellige tider.,

Runtime analyse: Selv om denne operasjonen ikke alltid traversere treet ned til et blad, dette er alltid en mulighet, og dermed i verste fall det krever tid i forhold til høyden av treet. Det krever ikke mer selv når node har to barn, siden det fortsatt følger en enkel bane, og ikke gå til en node to ganger.,

TraversalEdit

utdypende artikkel: Tre traversal

Når binary search tree har blitt opprettet, elementene kan hentes ut i rekkefølgen av undermapper traversing venstre undertreet av rotnoden, få tilgang til noden selv, da undermapper traversing rett undertreet av noden, fortsetter dette mønsteret med hver node i treet som det er undermapper tilgjengelig. Som med alle binære trær, kan man gjennomføre en pre-order traversal eller en post-order traversal, men ingen av dem er sannsynligvis å være nyttig for binære søk trær., En ordre traversal av et binært søk treet vil alltid resultere i en sortert liste over node elementer (tall, strenger eller andre lignende gjenstander).

– koden for i-for traversal i Python er gitt nedenfor. Det vil ringe tilbakeringing (noen funksjon programmerer ønsker å ringe på node-verdi, som for eksempel utskrift til skjerm) for hver node i treet.

Traversal krever O(n) tid, siden det må besøke hver node. Denne algoritmen er også O(n), så det er asymptotically optimal.

Traversal kan også gjennomføres iterativt. For enkelte programmer, For eksempel, større lik søk, approximative søk, en operasjon for ett trinn (iterativ) traversal kan være svært nyttig. Dette er, selvfølgelig, gjennomført uten innb. konstruere og tar O(1) i gjennomsnitt og O(log n) i verste fall.

VerificationEdit

noen Ganger er vi allerede har et binært tre, og vi må finne ut om det er en norsk tid. Dette problemet har en enkel rekursiv løsning.,

BST eiendom—hver node på høyre undertreet har til å være større enn den nåværende noden, og hver node på venstre undertreet har til å være mindre enn den nåværende node—er nøkkelen til å finne ut om et tre er et BST eller ikke. Den grådige algoritmen—det er bare å traversere treet, på hver node sjekke om den noden som inneholder en verdi som er større enn verdien på venstre barn, og mindre enn verdien på høyre barn—fungerer ikke for alle tilfeller., Vurdere følgende tre:

 20 / \ 10 30 / \ 5 40

I treet ovenfor, hver node oppfyller vilkåret om at den noden som inneholder en verdi som er større enn dens venstre barn, og mindre enn dens høyre barn inne, men det er ikke et BST: verdien 5 er på rett undertreet av den noden som inneholder 20, en overtredelse av BST eiendom.

i Stedet for å ta en avgjørelse basert utelukkende på verdiene i en node og sine barn, vi trenger også informasjon som flyter ned fra foreldre som godt., I tilfelle av treet ovenfor, hvis vi kunne huske om den noden som inneholder verdien 20, ville vi se at den noden med verdien 5 er brudd BST eiendom kontrakt.,

Så tilstand vi må se på hver node er:

  • hvis noden er venstre barn av sine foreldre, må det være mindre enn (eller lik) det overordnede og det må passere ned verdien av sine foreldre til sin rett undertreet å sørge for at ingen av nodene i at undertreet er større enn foreldre
  • hvis noden er høyre barn til sin forelder, da må det være større enn den overordnede og det må passere ned verdien av sine foreldre til venstre undertreet å sørge for at ingen av nodene i at undertreet er mindre enn foreldrene.,

En rekursiv løsning i C++ kan forklare dette nærmere:

node->key+1 og node->key-1 er gjort for å tillate bare forskjellige elementer i BST.

Hvis vi vil ha de samme elementene skal også være til stede, så vi kan bare bruke node->key begge steder.

Den første ringe til denne funksjonen kan være noe sånt som dette:

if (isBST(root, INT_MIN, INT_MAX)) { puts("This is a BST.");} else { puts("This is NOT a BST!");}

Egentlig vi holder opprette en gyldig område (fra ) og holde krympende det ned for hver node som vi går ned med undermapper.,

Som påpekt i avsnitt #Traversal, en in-order traversal av en binary search tree returnerer noder sortert. Dermed trenger vi bare å holde den sist besøkte node mens du reiser gjennom treet og for å sjekke om de viktigste er mindre (eller mindre/lik, om duplikater skal være tillatt i treet) i forhold til den aktuelle tasten.

Parallell algorithmsEdit

Det er også parallelle algoritmer for binære søk trær, inkludert sette inn/slette flere elementer, konstruksjon fra matrisen, filter med visse verbal, flate til en matrise, sammenslåing/substracting/kryssende to trær, etc., Disse algoritmene kan gjennomføres ved hjelp av delta-basert treet algoritmer, noe som kan også holde treet balansert, ved hjelp av flere balansere ordninger (inkludert AVL-trær rød-svarte treet, vekt-balansert treet og treap) .

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *