[Powered by Google Translate] [Walkthrough - Probleem Set 5]
[Zamyla Chan - Harvard University]
[Dit is CS50. - CS50.TV]
>> Oke. Hallo, iedereen, en welkom bij Walkthrough 5.
>> Pset5 is Spelfouten, waarin we een spellingcontrole worden maken.
Spell-checkers zijn uiterst belangrijk.
Is dit ooit overkomen?
Je werkt zeer, zeer oppotten op een papier voor een botsing
en dan nog uiteindelijk het krijgen van een zeer gloed rade als een D-of een D =
en dat allemaal omdat je de leverworst spoiler in de walvis breed woord.
Ja, proeflezen uw paprika's is een kwestie van de, de grootst mogelijke impotentie.
Dit is een probleem dat mannelijke, mannelijke studenten beïnvloedt.
Ik werd ooit verteld door mijn sith graad folteraar die ik nooit zou krijgen in een goede collega.
En dat is alles wat ik ooit wilde, dat is alles wat elk kind wil op mijn leeftijd,
gewoon om in een goede collega.
En niet zomaar een collega. Nee, ik wilde naar een Ivory Legal collega.
Dus als ik het niet deed verbetering, zou gegaan zijn mijn dromen van naar Harvard,
Jale, of Gevangenis - je weet wel, in Gevangenis, New Jersey.
Dus ik heb mezelf een spellingcontrole.
Dat is een fragment uit een van mijn favoriete spoken word artiesten, Taylor Mali.
Hoe dan ook, zoals hij zegt, het belang van het hebben van een spellingcontrole is erg belangrijk.
>> Dus welkom om Walkthrough 5, waarin we het zullen hebben over pset5: spelfouten,
waarin wij zal het maken van onze eigen spell-checker.
De toolbox voor deze week, de verdeelsleutel, zal van belang om te kijken naar
alleen maar om de verschillende functies die uw woordenboek zal moeten begrijpen.
We zijn eigenlijk gaan worden het hebben van meerdere. C bestanden die samen onze PSET.
En dus kijken door de verschillende aspecten, hoewel we in feite niet aan het wijzigen
een van de bestanden, speller.c, weten hoe het werkt met betrekking tot dictionary.c,
die we zullen schrijven, zal worden erg belangrijk.
De PSET spec bevat ook veel nuttige informatie
in termen van dingen die je kunt aannemen, regels en dat soort dingen,
dus zorg ervoor dat de PSET spec zorgvuldig te lezen voor tips.
En bij twijfel van een regel of iets dergelijks, dan altijd verwijzen naar de PSET spec
of Bespreek.
Dit PSET gaat sterk afhankelijk zijn van pointers,
dus we willen ervoor zorgen dat we het verschil tussen het toevoegen sterren te begrijpen
voor de naam van de aanwijzer en ampersands, hoe ze te bevrijden, enz.
Dus als een meester van pointers zal zeer nuttig zijn in dit probleem set.
We gaan kijken naar gelinkte lijsten een beetje meer,
waar we elementen we knooppunten die zowel een waarde en een pointer hebben voldoende
naar het volgende knooppunt, en dus in wezen verbinden van verschillende elementen na elkaar.
Er zijn een paar verschillende opties van de uitvoering van uw werkelijke woordenboek.
We gaan kijken naar twee belangrijkste methoden, die hash tabellen en vervolgens probeert.
In deze beide brengen ze een soort begrip verbonden lijst
waar u met elkaar verbonden elementen aan elkaar.
En dus we gaan om te kijken over hoe je zou kunnen werken rond gelinkte lijsten,
deze maken, navigeert u in termen van hoe je, bijvoorbeeld, plaatst u een knooppunt in het
of vrije alle knooppunten ook.
In termen van het vrijmaken van knooppunten, dat is echt belangrijk
dat wanneer we malloc geheugen achteraf, we bevrijden.
Dus we willen ervoor zorgen dat er geen wijzer unfreed gaat, dat we geen geheugenlekken hebben.
We gaan een tool genaamd Valgrind dat uw programma wordt uitgevoerd introduceren
en controleert of al het geheugen dat u toegewezen wordt dan bevrijd.
Uw PSET is pas compleet als het werkt en het heeft volledige functionaliteit,
maar ook, Valgrind je vertelt dat je er is geen geheugenlekken gevonden.
Tot slot, voor deze PSET, ik wil echt benadrukken -
Ik bedoel, zoals gewoonlijk, ik ben zeker een voorstander van het gebruik van pen en papier voor uw probleem sets,
maar voor deze ene, ik denk dat pen en papier gaat worden met name van belang
wanneer u wilt worden tekenen pijlen om dingen en te begrijpen hoe dingen werken.
Dus zeker proberen om pen en papier te gebruiken om dingen te trekken uit voordat u aan de codering
want het kan een beetje rommelig.
>> Laten we eerst eens gaan in gelinkte lijsten een beetje.
Gelinkte lijsten bestaan ​​uit knooppunten, waar elke knoop heeft een waarde die ermee verbonden zijn,
en een pointer naar het volgende knooppunt na.
Een paar dingen van belang bij de gelinkte lijsten zijn die we nodig hebben om te onthouden
waar onze eerste knooppunt is, en dan als we eenmaal weten waar het eerste knooppunt is,
op die manier kunnen we toegang krijgen tot het knooppunt dat het eerste knooppunt wijst naar
en degene daarna en die daarna.
En dan het laatste element in de gelinkte lijst is dat knooppunt wijzer
zal altijd wijzen op NULL.
Wanneer een knooppunt punten op NULL, dan weet je dat je hebt aan het einde van de lijst bereikt,
dat dat knooppunt is de laatste, dat er niets na dat.
Hier in dit schema, zie je dat de pijlen zijn de pointers,
en het blauwe deel is waar de waarde is opgeslagen,
en dan de rode doos met de aanwijzer naar het is de node wijzer
wijst naar het volgende knooppunt na.
En zo zie je hier, zou de D knooppunt wijzen op NULL omdat het het laatste element in de lijst.
>> Laten we eens kijken hoe we misschien een struct te definiëren voor een knooppunt.
En omdat we willen meerdere nodes hebben,
dit gaat om een ​​typedef struct geworden
waarin we gaan naar verschillende gevallen van knooppunten.
En dus hebben we definiëren als een nieuw gegevenstype.
Hier hebben we een typedef struct node.
In dit voorbeeld gaan we te maken met integer knooppunten,
dus we hebben een integer met de naam waarde en dan hebben we nog een pointer,
en in dit geval, het is een pointer naar een node, dus we hebben een struct knoop * genaamd volgende.
En dan zijn we noemen dit alles node.
Zorg ervoor dat u deze syntax volgen.
Merk op dat knooppunt is in feite verwezen up zowel boven als onder de accolades.
Dan bij te houden waar mijn eerste node is in deze gelinkte lijst,
dan heb ik een knoop pointer genaamd hoofd, en ik malloc ruimte genoeg voor de grootte van een knoop.
Notice echter dat hoofd eigenlijk een knooppunt pointer in tegenstelling tot een werkelijke knoop zelf.
Dus het hoofd doet eigenlijk bevat geen waarde,
het wijst alleen naar welke het eerste knooppunt in mijn gelinkte lijst is.
>> Om een ​​beter idee van gekoppelde lijsten te krijgen, want het is heel belangrijk
bij te houden om ervoor te zorgen dat u de ketting te houden,
Ik denk graag dat het als mensen in een lijn hand in hand,
waar elke persoon hand in hand met de volgende.
Je kunt niet zien in deze tekening, maar in principe zijn ze wijzend naar de volgende persoon
die in de keten.
En dus als je wilt een gelinkte lijst waar deze mensen doorkruisen -
stel je al die mensen hebben waarden die met hen
en wijzen ook op de volgende persoon in de rij -
als je wilt de gelinkte lijst doorlopen, bijvoorbeeld, om ofwel de waarden bewerken
of zoeken naar een waarde of iets dergelijks,
dan zul je met een pointer naar de specifieke persoon.
Dus we gaan naar een gegevenstype knooppunt pointer te hebben.
Voor dit geval, is het wel de cursor.
Een andere veel voorkomende manier om dit te noemen zou iterator of iets dergelijks zijn
omdat het itereren over en eigenlijk bewegen welk knooppunt het is te wijzen op.
Dit hier onze cursor.
Onze cursor zal eerst wijzen op het eerste element in onze lijst.
En dus wat we willen doen is dat we zouden in principe worden de voortzetting van de cursor,
verplaatsen van links naar rechts.
In dit geval willen we verplaatsen naar het volgende element in de lijst.
Met arrays, wat we zouden doen is dat we zouden we zeggen dat we de index met 1 te verhogen.
In dit geval is wat we moeten doen eigenlijk vinden welke persoon deze stroom persoon wordt verwezen,
en dat gaat naar de volgende waarde te zijn.
Dus als de cursor bevindt zich op slechts een knooppunt aanwijzer, dan wat we willen doen
is dat we willen krijgen op de waarde die de cursor op.
We willen naar die node en dan, als we op dat knooppunt, vinden waar het naar verwijst.
Om naar de werkelijke knooppunt dat de cursor op,
Meestal geven we aan door (* cursor).
Dat zou geven u de werkelijke knooppunt dat de cursor op.
En dan na dat, wat we willen doen is dat we toegang wilt
wat dat dan ook node volgende waarde is.
Om dat te doen, om de waarden binnenkant van de struct toegang, hebben we de puntoperator.
Dus dan zou het (* cursor). Volgende.
Maar dit is een beetje rommelig in termen van het hebben van de haakjes rond de * cursor,
en dus vervangen we dit hele verklaring met de cursor->.
Dit is een streepje en dan een groter dan teken, dus het maken van een pijl.
cursor-> volgende.
Dat is eigenlijk krijgt u het knooppunt dat de cursor op. Die waarde is van het volgende.
Dus in plaats van de ster en de stip, je vervangt die met een pijl.
Wees erg voorzichtig om ervoor te zorgen dat u probeert om deze syntax te gebruiken.
>> Nu hebben we onze cursor, als we willen dat de waarde toegang te krijgen,
eerder hadden we de cursor-> volgende,
maar om de waarde op het knooppunt dat de cursor om toegang te krijgen, hebben we gewoon zeggen
node-> waarde.
Vanaf daar is het van het gegevenstype wat we hebben de waarden en de knooppunten zijn gedefinieerd.
Als het een int knooppunt, dan cursor-> waarde wordt gewoon een geheel getal zijn.
Dus we kunnen bewerkingen doen op die, controleer gelijkheden, toewijzen verschillende waarden, enz.
Dus wat je wilt doen als je wilt om de cursor te verplaatsen naar de volgende persoon,
je eigenlijk de waarde van de cursor.
Omdat cursor is een knooppunt aanwijzer, wijzigt u de actuele pointer adres
aan het adres van het volgende knooppunt in uw lijst.
Dit is slechts een code waar je kon herhalen.
Waar heb ik de opmerking iets doen,
dat is waar je waarschijnlijk gaan om de waarde te openen
of iets te maken heeft met die specifieke knooppunt.
Om het te beginnen, ik zeg dat mijn cursor in eerste instantie
zal wijzen op het eerste element in de gekoppelde lijst.
En dus verderop, ik gedefinieerd als het hoofd van het knooppunt.
>> Zoals ik al zei, het vrijmaken is echt belangrijk.
U wilt ervoor zorgen dat u elk element vrij in de lijst als je eenmaal klaar bent met het.
Wanneer je hoeft niet meer te verwijzen naar een van deze pointers,
wilt u ervoor zorgen dat u al die verwijzingen te bevrijden.
Maar je wilt hier heel voorzichtig zijn in dat u wilt een geheugen lekkage te voorkomen.
Als u gratis een persoon te vroeg, dan is alle aanwijzingen die die knooppunten te
zullen verloren gaan.
Terug te gaan naar de persoon voorbeeld om het een beetje meer high stakes,
laten we deze mensen, behalve in dit geval worden ze zweven boven een meer met een monster.
We willen ervoor zorgen dat wanneer we vrij, we niet verliezen
en laat elke nodes voordat we echt bevrijd ze.
Bijvoorbeeld, als je gewoon hier te bellen gratis op deze man,
dan zou hij worden vrijgelaten, maar dan al deze jongens zou dan verloren gaan
en ze zouden afdrijven en naar beneden vallen.
Dus we willen ervoor zorgen dat in plaats daarvan willen we een link naar de rest te behouden.
Ons hoofd pointer, die wijst naar het eerste element in de lijst.
Het is een soort van een touw het verankeren van de eerste persoon.
Wat je zou willen doen als je te bevrijden van een lijst hebben -
Als u wilt dat het eerste element eerste vrije, dan kunt u een tijdelijke pointer
die naar wat het eerste element.
Dus je hebt je tijdelijke pointer die wijst hier.
Op die manier hebben we een greep van het eerste knooppunt.
En dan, omdat we weten dat het eerste knooppunt zal worden bevrijd,
dan kunnen we gaan dit touw, dit anker, ons hoofd,
om daadwerkelijk wijzen op wat de eerste wijst.
Dus dit hoofd wijst eigenlijk aan het tweede element nu.
Nu mogen we vrij wat er opgeslagen in temp,
en zo kunnen we wissen dat zonder het in gevaar te brengen alle de andere knooppunten in onze lijst.
Een andere manier die je kan dit niet, dan kan worden
elke keer dat je gewoon vrij het laatste element in de lijst
omdat ze gegarandeerd niet te worden gewezen op wat dan ook.
Dus je zou kunnen gewoon gratis deze ene, dan vrij deze, dan is gratis deze.
Dat is zeker werkt, maar is een beetje trager, omdat door de aard van de gelinkte lijsten,
we kunnen niet zomaar direct naar de laatste.
We moeten elk element doorlopen in de verbonden lijst
en controleer of dat men wijst op NULL, check elke keer,
en dan als we eenmaal aan het einde, dan vrij dat.
Als je aan dit proces te doen, zou je eigenlijk hier controleren,
het controleren van hier, dan het controleren van hier, het vrijmaken van het,
dan terug te gaan, het controleren van hier, het controleren van hier, het vrijmaken van het,
controleren hier en ontdoen.
Dat kost wat meer tijd. Ja.
>> [Student] Zou het mogelijk zijn om een ​​gekoppelde lijst die een exit wijzer slaat naar het einde te maken?
Dat zou zeker mogelijk zijn.
Nogmaals de vraag, is het mogelijk om een ​​gekoppelde lijststructuur
zodat een pointer wijst naar het eind van de verbonden lijst hebben?
Ik zou zeggen dat mogelijk is, en elke keer dat je iets invoegen in uw gelinkte lijst
je zou hebben om die wijzer en dat soort dingen bij te werken.
Je zou een knooppunt * staart, bijvoorbeeld.
Maar als je deze functie uitvoeren, moet u denken aan de trade-offs,
zoals hoe vaak ga ik te itereren over deze,
Hoe moeilijk is het gaat worden voor het bijhouden van de staart en de kop te houden
en mijn iterator, en dat soort dingen.
Is dat -? >> [Student] Ja.
Het is mogelijk, maar in termen van ontwerpbeslissingen, moet u de opties af te wegen.
>> Hier is een skelet van code die laat je toe om elk element te bevrijden in een gelinkte lijst.
Nogmaals, aangezien ik itereren over een gelinkte lijst, ik ga wil een soort van de cursor zijn
of iterator.
We itereren totdat de cursor zich NULL.
Je wilt niet te herhalen wanneer uw cursor NULL
want dat betekent dat er niet iets in de lijst.
Dus dan is hier maak ik een tijdelijke knoop *
wijzen op wat ik overweeg is de eerste van mijn lijst,
en dan verplaats ik mijn cursor vooruit 1 en dan vrij wat ik had in de tijdelijke opslag.
>> Nu komen we bij het invoegen in gekoppelde lijsten.
Ik heb drie knooppunten in mijn gelinkte lijst, en laten we gaan met het eenvoudige geval
waar we willen naar een ander knooppunt te voegen aan het einde van onze gekoppelde lijst.
Om dat te doen, al zouden we doen is dat we doorkruisen zouden
te vinden waar de huidige einde van de gekoppelde lijst is, dus welke knoop wijst op NULL -
dat is deze -
en dan zeggen, eigenlijk, deze is niet van plan om de laatste node;
we eigenlijk naar een andere een te hebben.
Dus zouden we de huidige ene punt naar wat we het plaatsen.
Dus nu deze rode persoon wordt hier het laatste knooppunt in de gelinkte lijst.
En dat de karakteristiek van het laatste knooppunt in de gekoppelde lijst is dat het wijst NULL.
Dus dan wat we zouden moeten doen is deze rode kerel aanwijzer op NULL. Er.
>> Maar wat als we wilden een knooppunt in te voegen in tussen de tweede en derde?
Die ene is niet zo eenvoudig, omdat we willen ervoor zorgen dat
dat we niet laten gaan van een knooppunt in onze gelinkte lijst.
Wat we zouden moeten doen is ervoor te zorgen dat we ons verankeren aan een ieder.
Bijvoorbeeld, laten we noemen dit de tweede.
Als je zei dat de tweede verwijst nu naar deze nieuwe
en je zojuist een pointer daar, dan zou dat leiden tot deze man verloren
want er is geen link naar hem.
In plaats daarvan - Ik zal opnieuw te tekenen dit. Excuseer mijn artistieke capaciteiten.
We weten dat we niet zomaar direct 2 te koppelen aan de nieuwe.
We moeten ervoor zorgen dat we vasthouden aan de laatste.
Wat wij zou willen doen is een tijdelijke pointer
om het element dat gaat worden toegevoegd op.
Dus dan hebben we er een tijdelijke pointer.
Omdat we weten dat dit derde spoor wordt gehouden van,
2 kan nu een link naar onze nieuwe.
En als dit nieuwe rode man zal zijn tussen de 2 en 3,
dan wat is die vent wijzer gaan om te verwijzen naar? >> [Student] Temp.
Temp. Ja.
Dus dan is deze rode kerel volgende waarde gaat worden temp.
Als je het invoegen in gelinkte lijsten, zagen we dat we konden
gemakkelijk iets toevoegen aan het einde van het creëren van een tijdelijke array,
of als we wilden iets toe te voegen in het midden van ons aanbod,
dan zou het een beetje meer schuifelen rond.
Als u wilt, bijvoorbeeld, hebben een gesorteerd gelinkte lijst,
dan moet je soort van wegen de kosten en baten van die
want als je een gesorteerde array hebben, dat betekent dat elke keer dat u in het,
het gaat om een ​​beetje meer tijd in beslag nemen.
Echter, als je wilt later, als we vinden dat we willen,
zoeken door middel van een gekoppelde lijst, dan is het misschien makkelijker als je weet dat alles in orde is.
Dus je zou willen om de kosten en baten van die wegen.
>> Een andere manier om invoegen in een gekoppelde lijst te voegen in het begin van een lijst.
Als we hier trekken ons anker - dit is ons hoofd -
en dan hebben deze mensen daaraan gekoppeld is,
en dan een nieuwe knoop in te voegen in het begin,
dan wat zouden we willen doen?
Wat zou daar mis mee alleen maar te zeggen Ik wil de rode koppelen aan de blauwe,
want dat is de eerste?
Wat zou hier gebeuren?
Al deze drie zou verdwalen.
Dus we willen niet dat te doen.
Nogmaals, hebben we geleerd dat we nodig hebben om een ​​soort van tijdelijke pointer te hebben.
Laten we ervoor kiezen om een ​​tijdelijke punt om deze man te hebben.
Dan kunnen we de blauwe ene punt naar het tijdelijke
en dan de rode punt op de blauwe.
De reden waarom ik ben met behulp van mensen hier is omdat we echt willen visualiseren
vasthouden aan mensen en ervoor te zorgen dat we een link om ze te hebben
voordat we loslaten van een andere hand of iets dergelijks.
>> Nu we hebben een gevoel van gelinkte lijsten - hoe wij een gekoppelde lijst te maken
en creëren structuren die bestaan ​​uit het type definitie voor een knooppunt
en dan ervoor te zorgen dat we een pointer naar het hoofd van die gekoppelde lijst hebben -
keer hebben we dat en we weten hoe we doorkruisen door middel van een array,
toegang tot verschillende elementen, we weten hoe in te voegen en we weten hoe ze te bevrijden,
dan kunnen we krijgen in spelfouten.
Zoals gebruikelijk hebben we een deel van de vragen die u naar operationele gebruikt met gelinkte lijsten
en verschillende structuren zoals wachtrijen en stacks.
Dan kunnen we verhuizen naar spelfouten.
>> Spelfouten heeft in de verdeelsleutel een paar bestanden van belang.
Eerst merken we dat we deze Makefile hier hebben,
die we nog niet echt ontmoet.
Als je keek in de pset5 map, zou je merken dat je een. H-bestand,
dan heb je twee. c-bestanden.
Wat dit doet is Makefile voor, zouden we gewoon typ maken en de naam van het programma
en dan zouden we zien al deze argumenten en vlaggen doorgegeven aan de compiler.
Wat de Makefile doet is stelt ons in staat om meerdere bestanden samen te stellen in een keer
en pas in de vlaggen die we willen.
Hier hebben we gewoon zien dat er hier een header-bestand.
Dan hebben we eigenlijk twee bronbestanden.
We hebben speller.c en dictionary.c.
U bent van harte welkom om de Makefile bewerken als je wilt.
Merk op dat hier als u typt schoon, dan wat het doet is eigenlijk verwijdert alles
dat is de kern.
Als je een segmentatie fout, in principe krijg je een core dump.
Dus dit lelijke kleine bestand wordt weergegeven in uw map met de naam kern.
U wilt te verwijderen die te maken schoon te maken.
Het verwijdert alle exe-bestanden en. O bestanden.
>> Laten we eens een kijkje nemen in dictionary.h.
Dit zegt dat het een woordenboek de functionaliteit verklaart.
We hebben een maximale lengte voor elk woord in het woordenboek.
We zeggen dat dit gaat om de langst mogelijke woord. Het is van lengte 45.
Dus we gaan niet alle woorden die die lengte overschrijden hebben.
Hier hoeven we alleen maar de functie prototypes.
We hebben niet de daadwerkelijke uitvoering, want dat is wat we moeten doen voor deze PSET.
Maar wat dit doet is omdat we te maken hebben met grotere bestanden hier
en functionaliteit op een grotere schaal, is het nuttig om een. h bestand
zodat iemand anders het lezen of het gebruik van de code kan begrijpen wat er gaande is.
En misschien willen ze implementeren probeert als je dat deed hash tabellen of vice versa.
Dan zouden ze zeggen dat mijn lading functie,
de daadwerkelijke uitvoering gaat verschillen, maar dit prototype zal niet veranderen.
Hier hebben we te controleren, dat true retourneert als een bepaald woord in het woordenboek.
Dan hebben we last, die in feite neemt in een woordenboek bestand
en dan laadt het deze in sommige datastructuur.
We hebben grootte, die, als ze worden opgeroepen, de grootte van uw woordenboek terug,
hoeveel woorden worden opgeslagen,
en dan lossen, die bevrijdt van al het geheugen dat u hebt opgenomen
terwijl het maken van uw woordenboek.
>> Laten we eens een kijkje nemen op dictionary.c.
We zien dat het lijkt erg op dictionary.h, behalve nu net heeft al deze Todos in.
En dus dat is je werk. Uiteindelijk zult u het invullen van speller.c met al deze code.
Dictionary.c, wanneer deze wordt uitgevoerd, is niet echt van plan om iets te doen,
dus we kijken naar speller.c aan de daadwerkelijke uitvoering van de spellingcontrole te zien.
Zelfs al ben je niet van plan om te bewerken een van deze code,
is het belangrijk om te lezen, wanneer wordt belasting genoemd begrijpen, als ik bel cheque,
alleen maar om te begrijpen, in kaart het uit, zien hoe de functie werkt.
We zien dat het is het controleren op het juiste gebruik.
In wezen, als iemand speller loopt, geeft dit aan dat het facultatieve is
voor hen door te geven in een woordenboek bestand omdat er gaat een standaard woordenboek bestand zijn.
En dan hebben ze door te geven in de tekst te worden spell-gecontroleerd.
rusage deals met de tijd, omdat een deel van dit PSET die we later zullen behandelen
is niet alleen het krijgen van een goed functionerende spellingcontrole werkt
maar eigenlijk het krijgen van het te snel.
En dus dan is dat waar rusage gaat komen inch
Hier zien we de eerste oproep om een ​​van onze dictionary.c bestanden, die is belast.
Load geeft true of false - waar op succes, vals bij uitval.
Dus als het woordenboek is niet goed geladen, dan is de speller.c terug 1 en stoppen.
Maar als dat zo is de lading goed, dan is het gaan blijven.
We blijven, en we zien een aantal file I / O hier,
waar het gaat om te maken hebben met het openen van het tekstbestand.
Hier, wat dit doet is elk woord in de tekst spell-controles.
Dus wat speller.c wordt hier doet is itereren over elk van de woorden in het tekstbestand
en dan controleren ze in het woordenboek.
Hier hebben we een Boolean verkeerd gespeld die zal kijken of cheque geeft true of niet.
Als het woord eigenlijk in het woordenboek, dan check zal terugkeren waar.
Dat betekent dat het woord niet verkeerd is gespeld.
Dus verkeerd gespeld zou zijn vals, en dat is waarom we de knal daar de indicatie.
We blijven aan de gang, en dan houdt bij hoeveel verkeerd gespelde woorden
er in het bestand.
Het blijft op en sluit het bestand.
Dan hier, rapporteert hoeveel verkeerd gespelde woorden je had.
Het berekent hoeveel tijd die nodig was om het woordenboek te laden,
hoeveel tijd het heeft gekost om het te controleren,
hoeveel tijd die nodig was om de grootte te berekenen,
die, zoals we verder gaan, moet zeer klein zijn,
en dan hoeveel tijd die nodig was om het woordenboek te laden.
Hier boven hebben we de oproep om hier te lossen zien.
Als we hier controleren voor grootte,
dan zien we dat hier de oproep op maat wanneer bepaalt de grootte van het woordenboek.
Awesome.
>> Het is onze taak om deze PSET is het implementeren van belasting, die het woordenboek wordt geladen
datastructuur - Wat u ook kiest, of het nu een hash-tabel of een keer te proberen -
met woorden uit het woordenboek bestand.
Dan heb je grootte, die het aantal woorden terug in het woordenboek.
En als u de uitvoering van belasting op een slimme manier, dan grootte moet vrij eenvoudig.
Dan heb je te controleren, die zal controleren of een bepaald woord in het woordenboek.
Dus speller.c gaat in een string, en dan moet je de vraag of die string controleren
is opgenomen in uw woordenboek.
Merk op dat we in het algemeen standaard woordenboeken,
maar in dit PSET, eigenlijk elke woordenboek doorgegeven in in elke taal.
Dus we kunnen niet zomaar aannemen dat het woord de binnenkant is.
Het woord FOOBAR kan worden gedefinieerd in een bepaalde woordenboek dat we passeren inch
En dan hebben we lossen, die bevrijdt het woordenboek uit het geheugen.
>> Ten eerste, wil ik gaan over de hash-tabel methode
over hoe we zouden kunnen implementeren al die vier functies,
en dan ga ik over de methode probeert, hoe we die vier functies te implementeren,
en aan het eind praten over een aantal algemene tips als je het maken van de PSET
en ook hoe je zou kunnen gebruiken Valgrind om te controleren of het geheugen lekken.
>> Laten we in de hash tabel methode.
Een hash tabel bestaat uit een lijst van emmers.
Elke waarde, elk woord, zal gaan in een van deze bakken.
Een hash table ideaal verdeelt al deze waarden die je voorbij in
en gevuld ze in de emmer zodat elke emmer
heeft ongeveer een gelijk aantal waarden in.
De structuur van een hash-tabel, hebben we een reeks van gelinkte lijsten.
Wat wij doen is als we passeren in een waarde, we kijken waar die waarde moet behoren,
die emmer het behoort, en zet dan weg in de gelinkte lijst die bij die emmer.
Hier, wat ik heb is een hash-functie.
Het is een int hash-tabel.
Dus voor de eerste emmer, elke gehele getallen onder de 10 gaan in de eerste emmer.
Hele getallen boven de 10 maar onder de 20 gaan in de tweede,
en zo verder enzovoort.
Voor mij is elke emmer die deze nummers.
Maar, zeg ik zou slagen in 50, bijvoorbeeld.
Het lijkt alsof de eerste drie bevatten een reeks van tien getallen.
Maar ik wil toestaan ​​mijn hash-tabel te nemen in een soort van gehele getallen,
dus dan zou ik om te filteren op alle nummers boven de 30 in het laatste segment.
En zo dan zou dat resulteren in een soort onevenwichtige hash-tabel.
Herhalen tot, een hash-tabel is slechts een array van emmers
waar elke bak is een gelinkte lijst.
En zo te bepalen waar elke waarde gaat die bak gaat het in,
je gaat te willen wat heet een hash-functie
dat neemt een waarde vervolgens zegt deze waarde correspondeert met een bepaalde bak.
Dus boven in dit voorbeeld my hashfunctie heeft elke waarde.
Gecontroleerd of het was minder dan 10.
Zo ja, zou zet het in het eerste segment.
Het controleert of het nu minder dan 20, zet het in de tweede als het waar is,
controleert of het is minder dan 30, en dan zet het in de derde emmer,
en dan al het andere valt net op de vierde emmer.
Dus wanneer je een waarde hebben, je hash-functie
plaatst die waarde in de juiste emmer.
De hash-functie moet in principe om te weten hoeveel emmers je hebt.
Uw hash table grootte, het aantal bakken die je hebt,
dat gaat een vast nummer dat up is voor u, voor u beslist te zijn,
maar het gaat om een ​​vast nummer zijn.
Dus je hash-functie wordt een beroep op dat om te bepalen welke emmer elke toets gaat in
zodanig dat het gelijk is verdeeld.
Net als bij onze implementatie van gelinkte lijsten, nu elke node in de hash-tabel
er werkelijk gaande is om een ​​type char hebben.
Dus hebben we een char array woord en dan nog een pointer naar het volgende knooppunt,
wat logisch is, omdat het gaat om een ​​gekoppelde lijst.
Weet je nog dat we hadden gelinkte lijsten, heb ik een knoop * genaamd hoofd
wees dat het eerste knooppunt in de gekoppelde lijst.
Maar voor onze hash-tabel, want we hebben meerdere gekoppelde lijsten,
wat we willen is dat we willen dat onze hash-tabel om te zijn zoals: "Wat is een emmer?"
Een emmer is slechts een lijst van knooppunt pointers,
Dus iedere element in de emmer daadwerkelijk onder verwijzing naar de bijbehorende verbonden lijst.
Om terug te gaan naar dit schema, zie je dat de emmers zelf de pijlen,
niet de werkelijke knooppunten.
Een essentiële eigenschap van hash functies is dat ze deterministisch zijn.
Dat betekent dat wanneer u hash de nummer 2,
het moet altijd weer terug op dezelfde emmer.
Elke waarde die gaat in de hash-functie, bij herhaling,
moet krijgen dezelfde index.
Dus je hash-functie geeft de index van de array
indien deze waarde hoort.
Zoals ik al zei, is het aantal emmers vast,
en zo uw index dat je terug moet kleiner zijn dan het aantal emmers
maar groter dan 0.
De reden waarom we hash-functies in plaats van slechts een enkele gelinkte lijst
of een array is dat we in staat om naar een bepaald gedeelte snelst
Als we weten dat de eigenschap van een waarde -
in plaats van te zoeken in het volledige woordenboek,
kunnen om naar een bepaald deel daarvan.
Uw hashfunctie moet rekening worden gehouden met een ideale,
elke emmer ongeveer hetzelfde aantal sleutels.
Aangezien de hashtabel een reeks gekoppelde lijsten
dan de verbonden lijsten zelf zullen meerdere node.
In het vorige voorbeeld, twee verschillende getallen, hoewel ze niet gelijk zijn,
wanneer gehashed, zou terugkeren op dezelfde index.
Dus als je te maken hebt met woorden, een woord als hashed
zou dezelfde hash-waarde als een ander woord.
Dat is wat wij noemen een botsing, wanneer we een knooppunt dat, wanneer hashed,
de gekoppelde lijst op die emmer niet leeg is.
De techniek die we noemen er lineaire sonderen,
waar je in de gekoppelde lijst en vervolgens te zoeken waar u wilt dat knooppunt te voegen
omdat je een botsing.
Je kunt zien dat er misschien een trade-off hier te zijn, toch?
Als je een heel klein hash-tabel, een zeer klein aantal emmers,
dan zul je een hoop botsingen hebben.
Maar dan als je een zeer grote hash-tabel,
ben je waarschijnlijk gaat om de botsingen te minimaliseren,
maar het gaat om een ​​zeer grote data structuur.
Er zal trade-offs zijn met dat.
Dus wanneer u uw PSET maken, proberen te spelen rond
tussen misschien het maken van een kleinere hash-tabel
maar dan weten dat het gaat om een ​​beetje langer duren om de verschillende elementen doorkruisen
van die gelinkte lijsten.
>> Wat belasting gaat doen is itereren over elk woord in het woordenboek.
Het gaat in een verwijzing naar het woordenboek bestand.
Dus je gaat om te profiteren van het bestand I / O functies die u onder de knie in pset4
en itereren over elk woord in het woordenboek.
U wilt elk woord in het woordenboek op een nieuw knooppunt te worden,
en je gaat elk van die knooppunten te plaatsen in uw woordenboek datastructuur.
Wanneer u een nieuw woord te krijgen, weet je dat het gaat om een ​​knooppunt te worden.
U kunt dus direct gaan en malloc een knooppunt pointer voor elk nieuw woord dat je hebt.
Hier Ik bel mijn knooppunt aanwijzer new_node en ik ben mallocing wat? De grootte van een node.
Dan naar de werkelijke tekenreeks uit een bestand te lezen, omdat het woordenboek is eigenlijk opgeslagen
met een woord en vervolgens een nieuwe lijn, wat we kunnen profiteren van
is de functie fscanf,
waarbij bestand is het woordenboek bestand dat we doorgegeven in,
dus het scant het bestand op een string en plaatsen die string in het laatste argument.
Misschien herinner je je terug naar een van de lezingen, toen we gingen over
en de aard van gepelde de lagen weer op de CS50 bibliotheek,
zagen we een implementatie van fscanf daar.
Om terug te gaan naar fscanf, hebben we het bestand dat we het lezen van,
We zijn op zoek naar een string in dat bestand, en dan gaan we het plaatsen van het in
hier heb ik new_node-> woord, omdat new_node is een knooppunt pointer,
niet een echte node.
Dus dan zeg ik new_node, ik wil naar het knooppunt dat het is te wijzen op
en wijs die waarde te woord.
We willen vervolgens dat woord en in te voegen in de hash tabel.
Realiseer je dat we new_node een knooppunt pointer
want we gaan om te willen weten wat het adres van dat knooppunt is
als we invoegen in omdat de structuur van de nodes van de struct,
is dat ze een pointer naar een nieuwe node.
Dus wat is dan het adres van dat knooppunt te gaan om te verwijzen naar?
Dat adres zal worden new_node.
Is dat zinvol, waarom maken we new_node een knooppunt * in tegenstelling tot een knooppunt?
Oke.
We hebben een woord. Die waarde is new_node-> woord.
Dat bevat het woord uit het woordenboek die we willen invoeren.
Dus wat we willen doen is dat we willen onze hash-functie een beroep doen op die string
omdat onze hashfunctie neemt in een string en keert dan terug ons een geheel getal,
waar dat getal is de index waar hash op die index vertegenwoordigt die emmer.
We willen dat de index te nemen en ga dan naar die index van de hash-tabel
en gebruik die gelinkte lijst om het knooppunt te voegen op new_node.
Vergeet niet dat hoe je besluit je knooppunt invoegen,
of het nu in het midden als je wilt om het te sorteren
of aan het begin of aan het eind, maar zorg ervoor dat uw laatste knooppunt wijst altijd NULL te
want dat is de enige manier waarop we weten waar het laatste element van onze gekoppelde lijst is.
>> Als maat is een geheel getal dat het aantal woorden in een woordenboek is,
dan een manier om dit te doen is dat wanneer formaat wordt genoemd
we gaan door elk element in onze hash-tabel
en dan doorlopen om de gelinkte lijst in de hash-tabel
en berekent dan de lengte van dat, het verhogen van onze teller 1 voor 1.
Maar elke keer die grootte wordt genoemd, dat gaat lang duren
want we gaan naar lineair zijn indringende elke gelinkte lijst.
In plaats daarvan gaat het om een ​​stuk makkelijker zijn als je bijhouden hoeveel woorden worden doorgegeven inch
Dus dan kun je een teller in uw belasting-functie
dat updates indien nodig, vervolgens tegen te gaan, als u het naar een globale variabele,
kunnen worden geraadpleegd op grootte.
Dus wat omvang kon gewoon doen is in een lijn, net terug van de waarde van de teller,
de grootte van het woordenboek, die u reeds behandeld belasting.
Dat is wat ik bedoelde toen ik zei dat als je belasting te implementeren in een nuttige manier,
Vervolgens grootte gaat vrij gemakkelijk.
>> Dus nu krijgen we te controleren.
Nu we te maken hebben met woorden uit de input tekstbestand,
en dus we gaan te controleren of al die ingangswoorden
zijn eigenlijk in het woordenboek of niet.
Net als bij Scramble, willen we zorgen voor hoofdlettergevoeligheid.
U wilt er zeker van zijn dat alle woorden doorgegeven, ook al zijn ze gemengde geval is,
als ze worden opgeroepen met string vergelijken, gelijkwaardig zijn.
De woorden in het woordenboek tekstbestanden zijn eigenlijk allemaal kleine letters.
Een ander ding is dat je kunt ervan uitgaan dat elk woord doorgegeven in, elke string,
gaat worden, hetzij alfabetische of bevatten apostrof.
Apostrofs zullen geldig woorden in ons woordenboek.
Dus als je een woord met apostrof S hebben, dat is een echte legitieme woord in uw woordenboek
dat gaat als een van de knooppunten in uw hash tabel.
Controleer werkt met als het woord bestaat, dan moet wel in onze hash table.
Als het woord in het woordenboek, dan alle woorden in het woordenboek zijn in de hash tabel,
dus laten we eens kijken naar dit woord in de hash tabel.
We weten dat omdat we onze hash-functie geïmplementeerd
zodat elke unieke woord altijd gehashed op dezelfde waarde,
dan weten we dat in plaats van te zoeken in onze hele hele hash-tabel,
kunnen we eigenlijk vinden de gekoppelde lijst die dat woord moet behoren.
Als het in het woordenboek, dan zou in die emmer.
Wat we wel kunnen doen, als woord is de naam van onze string doorgegeven in,
we kunnen gewoon hash dat woord en blik op de gekoppelde lijst
op de waarde van de hash [hash (woord)].
Van daar, wat we kunnen doen is dat we hebben een kleinere subset van knooppunten om te zoeken naar dit woord,
en dus kunnen we doorkruisen de gelinkte lijst, met behulp van een voorbeeld uit eerder in de walkthrough,
en dan bellen string vergelijker op het woord waar de cursor op,
dat woord, en zien of deze te vergelijken.
Afhankelijk van de manier waarop je je hash-functie te organiseren,
als het gesorteerd, kunt u mogelijk om valse wat eerder terug te keren,
maar als het ongesorteerd, dan moet je verder wilt gaan doorkruisen via uw gekoppelde lijst
totdat u het laatste element van de lijst.
En als je nog steeds niet gevonden het woord door de tijd dat je aan het einde van de gekoppelde lijst,
dat betekent dat uw woord niet bestaat in het woordenboek,
en zo dat woord is ongeldig,
en controle moet return false.
>> Nu komen we bij lossen, waar we willen alle knooppunten die we hebben malloc'd bevrijden,
zo vrij alle knooppunten binnenkant van onze hash-tabel.
We gaan willen itereren over alle van de gelinkte lijsten en vrij van alle knooppunten in dat.
Als je kijkt boven in de walkthrough op het voorbeeld, waar we gratis een gelinkte lijst,
dan zul je om dat proces te herhalen voor elk element in de hash tabel.
En ik zal gaan over deze tegen het einde van de walkthrough,
maar Valgrind is een hulpmiddel waar je kunt zien of je op de juiste wijze bevrijd
elke knoop die u hebt malloc'd of iets anders dat u malloc'd, een andere wijzer.
Dus dat is hash tables, waar we een eindig aantal emmers
en een hash functie die een waarde toekennen en vervolgens deze waarde een bepaalde bak.
>> Nu komen we bij pogingen.
Probeert soort look als dit, en ik zal ook trekken uit een voorbeeld.
In principe heb je een heel scala aan mogelijke letters,
en dan als je de bouw van een woord,
deze brief kan worden gekoppeld om een ​​woordenboek een breed scala aan mogelijkheden.
Sommige woorden beginnen met C, maar ga dan verder met A,
maar anderen voortzetten O bijvoorbeeld.
Een trie is een manier van het visualiseren van alle mogelijke combinaties van die woorden.
Een trie gaat om bij te houden van de opeenvolging van letters die woorden bestaan,
aftakking indien nodig, wanneer een brief kan worden gevolgd door een veelvoud van letters,
en aan het eind dan op elk punt of dat woord wel of niet geldig
want als je spelling van het woord MAT, MA Ik denk niet dat een geldige woord, maar MAT is.
En zo in uw trie, zou dat betekenen dat na MAT dat is eigenlijk een geldig woord.
Elk knooppunt in onze trie daadwerkelijk zal een array van knooppunt pointers bevat,
en we gaan specifiek hebben, 27 van die knoop pointers,
een voor elke letter van het alfabet en de apostrof karakter.
Elk element in dat array zelf zal wijzen naar een ander knooppunt.
Dus als dat knooppunt is NULL, als er niets na dat,
dan weten we dat er geen verdere letters in dat woord volgorde.
Maar als dat knooppunt niet NULL is, dat betekent dat er meer letters in die brief volgorde.
En dan verder, elke node geeft aan of het is de laatste letter van een woord is of niet.
>> Laten we naar een voorbeeld van een trie.
Eerst heb ik ruimte hebben voor 27 knooppunten in deze array.
Als ik het woord BAR -
Als ik het woord BAR en ik wil dat invoegen in,
de eerste letter is B, dus als mijn trie leeg is,
B is de tweede letter van het alfabet, dus ik ga ervoor kiezen om hier zet deze op deze index.
Ik ga hier hebben B.
B gaat een knooppunt dat wijst op een andere array van alle mogelijke tekens zijn
die kunnen volgen na de letter B.
In dit geval ben ik het omgaan met het woord BAR, dus A zal hier gaan.
Na een, ik heb de letter R, dus dan A nu wijst op zijn eigen combinatie,
en dan R zal hier zijn.
BAR is een volledig woord, dus dan ga ik R-punt moeten naar een ander knooppunt
die zegt dat dat woord geldig is.
Dat knooppunt zal ook een reeks knooppunten,
maar die kan NULL.
Maar in principe kan het verder zo.
Dat zal een beetje meer duidelijk toen we naar een ander voorbeeld,
dus er gewoon geduld met mij.
Nu hebben we BAR binnenkant van ons woordenboek.
Nu zeggen dat we het woord BAZ.
We beginnen met B, en we hebben al B als een van de letters dat is in ons woordenboek.
Dat is gevolgd met A. We hebben een reeds.
Maar in plaats daarvan hebben we Z volgende.
Dus dan een element in ons aanbod zal zijn Z,
En dus dat gaat om naar een andere geldige eindtoestand van het woord.
We zien dus dat als we verder door B en dan A,
Er zijn twee opties die in ons woordenboek voor woorden die beginnen met B en A.
Stel dat we wilden het woord FOOBAR te voegen.
Dan zouden we een vermelding bij F.
F is een knooppunt dat wijst op een hele reeks.
We zouden O, gaat u naar O, O koppelt vervolgens naar een hele lijst.
We zouden B hebben en dan verder, zouden we A en vervolgens R.
Dus dan FOOBAR doorkruist helemaal naar beneden totdat FOOBAR is een juiste woord.
En dus dan zou dit een geldig woord.
Nu zeggen dat onze volgende woord in het woordenboek is eigenlijk het woord FOO.
Wij zouden zeggen F. Wat volgt F?
Ik heb eigenlijk al een ruimte voor O, dus ik ga om verder te gaan.
Ik heb geen behoefte om een ​​nieuwe te maken. Doorgaan.
FOO is een geldig woord in dit woordenboek, dus dan ga ik om aan te geven
dat geldig is.
Als ik daar te stoppen mijn volgorde, dat zou juist zijn.
Maar als we onze reeks van FOO naar B
en net FOOB had, FOOB is geen woord, en dat is niet geïndiceerd als geldig is.
In een trie, heb je elke node wordt aangegeven of het een geldig woord is of niet,
en dan elke knoop heeft ook een scala van 27 knoop pointers
die wijs knooppunten zelf.
>> Hier is een manier van hoe je zou willen om dit te definiëren.
Echter, net als in de hash tabel bijvoorbeeld, waar we een knooppunt * hoofd
aan het begin van onze verbonden lijst geven, zijn we ook zullen willen
enkele manier om te weten waar het begin van onze trie is.
Sommige mensen noemen probeert bomen, en dat is waar wortel vandaan komt.
Dus we willen dat de wortel van de boom om ervoor te zorgen dat we blijven geaard
naar de plaats waar onze trie is.
We hebben al soort van ging
de manier waarop je zou kunnen denken over het plaatsen van elk woord in het woordenboek.
In wezen, voor elk woord dat je gaat te willen doorlopen uw trie
en wetende dat elk element in de kinderen - we noemden het kind in dit geval -
komt overeen met een andere letter, je gaat te willen om die waarden te controleren
op dat index die overeenkomt met de letter.
Dus denk de hele weg terug naar Caesar en Vigenere,
wetende dat elke brief kunt u soort kaart terug naar een alfabetische index,
zeker A tot Z zal zijn vrij eenvoudig in kaart om een ​​alfabetische letter,
maar helaas, apostrofs zijn ook een geaccepteerde karakter in woorden.
Ik weet niet eens zeker wat de ASCII-waarde is,
dus voor dat als je wilt om een ​​index te beslissen of u het wilt of de eerste te zijn vinden
of de laatste, dan moet je een harde gecodeerde cheque die deel uitmaken van
en deze in index 26, bijvoorbeeld.
Zo word je dan het controleren van de waarde bij kinderen [i]
waar [i] komt overeen met wat brief je toch bezig bent.
Als dat NULL, dat betekent dat er op dit moment niet alle mogelijke letters
als gevolg van dat eerdere volgorde, dus je gaat te willen malloc
en maak een nieuw knooppunt en hebben dat kinderen [i] punt om het te
zodat u - als we ingevoegd een brief in de rechthoek -
het maken van kinderen van niet-NULL en punt in dat nieuwe knooppunt.
Maar als dat niet NULL is, zoals in ons geval van FOO
als we al FOOBAR hadden, blijven we,
en we zijn nooit het maken van een nieuw knooppunt, maar liever gewoon instellen is_word om waar te
aan het einde van dat woord.
>> Zo dan als voorheen, want hier te maken hebt met iedere letter in een tijd,
het gaat gemakkelijker voor je zijn voor de grootte, in plaats van te berekenen
en ga door de hele boom en bereken hoeveel kinderen heb ik
en aftakkingen, herinneren hoeveel zijn links en rechts
en dat soort dingen, het gaat om een ​​stuk makkelijker voor je zijn
als je gewoon bijhouden hoeveel woorden je toe te voegen in
wanneer je te maken hebt met last.
En toen op die manier omvang kan net terug van een globale variabele van grootte.
>> Nu komen we bij controleren.
Dezelfde normen als voorheen, waar we willen zorgen voor hoofdlettergevoeligheid.
Als goed, nemen we aan dat de snaren alleen alfabetische tekens of de apostrof
omdat de kinderen is een array van 27 lang,
zodat alle letters van het alfabet plus de apostrof.
Om in te checken wat je wilt doen is je wilt beginnen aan de wortel
omdat de wortel zal wijzen aan een array die bestaat uit
alle mogelijke start letters van een woord.
Je gaat daar beginnen,
en dan zul je om te controleren is deze waarde NULL of niet,
want als de waarde NULL, dat betekent dat het woordenboek geen enkele waarden
die bevatten die letter in die bepaalde volgorde.
Als het NULL, dan betekent dat dat het woord wordt meteen verkeerd gespeld.
Maar als het niet NULL is, dan kunt u blijven,
zeggen dat de eerste letter is een mogelijke eerste letter in een woord,
dus nu wil ik om te controleren of de tweede brief, die volgorde, is in mijn woordenboek.
Dus je gaat naar de index van de kinderen van het eerste knooppunt
en controleer of deze tweede brief bestaat.
Dan herhaal je dat proces om te controleren of de sequentie geldig is of niet
binnen uw trie.
Wanneer de knoop kinderen op dat indexpunten op NULL,
je weet dat die volgorde niet bestaat,
maar dan als u het einde van het woord dat u hebt ingevoerd,
dan wilt u nu controleren dat ik deze sequentie voltooid
en vond het in mijn trie, is dat woord dan niet geldig?
En dus dan wil je dat controleren, en dat is wanneer als je hebt gevonden die volgorde,
dan wilt u controleren of dat woord geldig is of niet
want herinner me terug in het vorige geval, dat trok ik waar we FOOB,
dat was een geldige sequentie die we gevonden, maar geen daadwerkelijke geldig woord zelf.
>> Ook voor lossen in de pogingen u alle van de knooppunten in uw trie lossen.
Sorry. Net als bij de hash tabellen waar in lossen we bevrijd alle knooppunten,
in de pogingen willen we ook vrij alle knooppunten.
Eigenlijk Unload werkt makkelijkst van onder naar boven
omdat deze zijn in wezen gelinkte lijsten.
Dus we willen zorgen dat we vasthouden maken op om alle waarden
en vrij allemaal expliciet.
Wat je gaat te willen doen als je werkt met een trie
is eerst naar beneden en de laagste vrije knooppunt
en ga dan naar al die kinderen en dan vrij al die,
gaan omhoog en dan vrij, enz.
Zoiets als het omgaan met de onderste laag van de trie eerste
en dan omhoog gaan top als je eenmaal hebt bevrijd alles.
Dit is een goed voorbeeld van waar recursieve functie van pas kan komen.
Als je eenmaal hebt bevrijd van de onderste laag van je trie,
dan bel je uitladen op de rest van het,
ervoor te zorgen dat u elke mini bevrijden -
U kunt dergelijke visualiseren als mini pogingen.
Dus je hier hebt je root.
Ik ben gewoon te vereenvoudigen, zodat ik niet hoeft te 26 van hen te trekken.
Dus je hebt deze, en dan zijn deze vertegenwoordigen sequenties van woorden
waar al deze kleine cirkels zijn brieven die geldig zijn sequenties van letters.
Laten we doorgaan net een beetje meer.
Wat je gaat te willen doen, is vrij de bodem hier en dan vrij deze
en dan vrij dit aan de onderkant voordat u bevrijden van de bovenste hier
want als je gratis iets in het tweede niveau hier,
dan je eigenlijk zou verliezen deze waarde hier.
Dat is waarom het belangrijk is in te lossen voor een trie om ervoor te zorgen dat u de bodem eerst vrij te maken.
Wat je zou willen is zeggen te doen voor elk knooppunt
Ik wil alle kinderen uit te laden.
>> Nu we gegaan lossen voor de hash-tabel werkwijze alsmede de trie methode,
we gaan kijken naar Valgrind.
Valgrind je met de volgende commando's.
Je hebt valgrind-v.
Je controleert alle lekken wanneer u speller gaven deze bepaalde tekst
omdat speller moet nemen in een tekstbestand.
Dus Valgrind loopt uw ​​programma, u vertellen hoeveel bytes u toegewezen,
hoeveel bytes u bevrijd, en het zal u vertellen of u net genoeg bevrijd
of dat je niet vrij genoeg,
of soms kun je zelfs over-vrij, zoals gratis een knooppunt dat is al bevrijd
en zo zal het u terug fouten.
Als u gebruik maakt Valgrind, zal het u een aantal berichten
aangeeft of u ofwel hebt minder dan genoeg bevrijd, net genoeg,
of meer dan genoeg keer.
>> Een deel van deze PSET, is het optioneel om uitdagen The Big Board.
Maar als we te maken hebben met deze datastructuren
het is wel leuk om te zien hoe snel en hoe efficiënt uw data structuren zou kunnen zijn.
Heeft uw hash-functie resulteert in een veel botsingen?
Of is uw data grootte echt groot?
Kost het veel tijd om te doorkruisen?
In het logboek van de speller, het systeem voert hoeveel tijd die u gebruikt om te laden,
om te controleren, op maat uit te voeren, en te lossen,
en dus die zijn geplaatst in The Big Board,
waar kun je het tegen je klasgenoten
en een aantal medewerkers om te zien wie heeft de snelste spellingcontrole.
Een ding dat ik zou willen om op te merken over de hash tables
is dat er een aantal vrij eenvoudig hash functies die we konden bedenken.
Bijvoorbeeld, je hebt 26 emmers, en zo elke emmer
overeenkomt met de eerste letter van een woord,
maar dat gaat resulteren in een vrij onevenwichtige hash-tabel
omdat er veel minder woorden die met X beginnen dan beginnen met M, bijvoorbeeld.
Een manier om te gaan over speller is als u alle andere functionaliteit te krijgen naar beneden,
dan gewoon gebruik maken van een eenvoudige hash-functie te kunnen om uw code die wordt uitgevoerd
en ga dan terug en wijzig de grootte van uw hash tabel en de definitie.
Er zijn heel wat middelen op het internet voor hash-functies,
en dus voor deze PSET je mag hashfuncties onderzoek op het internet
voor wat tips en inspiratie, zolang je ervoor zorgen om te verwijzen waar heb je het uit.
Je bent van harte welkom om te kijken en te interpreteren wat hash-functie die u vindt op het internet.
Terug naar dat, zou je in staat zijn om te zien of iemand gebruik gemaakt van een trie
of de uitvoering ervan is sneller dan je hash-tabel of niet.
U kunt indienen bij het grote bord meerdere keren.
Het zal opnemen van uw meest recente item.
Dus misschien heb je je hashing-functie en dan beseffen dat het eigenlijk een stuk sneller
of een stuk langzamer dan voorheen.
Dat is een beetje een leuke manier.
Er is altijd 1 of 2 medewerkers die proberen om een ​​zo laag mogelijk woordenboek te maken,
dus dat is altijd leuk om naar te kijken.
>> Het gebruik van de PSET is dat je speller loopt met een optionele woordenboek
en dan een verplichte tekstbestand.
Standaard wanneer u speller met slechts een tekstbestand en niet specificeren een woordenboek,
het gaat om het woordenboek tekstbestand, de grote men gebruik maken van
in de cs50/pset5/dictionaries map.
Die ene heeft meer dan 100.000 woorden.
Ze hebben ook een kleine woordenboek dat aanzienlijk minder woorden heeft
dat CS50 heeft voor u gemaakt.
Echter, kunt u heel eenvoudig gewoon uw eigen woordenboek
als je gewoon wilt om te werken in kleine voorbeelden -
bijvoorbeeld, als u wilt gdb gebruiken en je weet de specifieke waarden
dat u wilt dat uw hash-tabel in kaart te.
Zo kunt u uw eigen tekst bestand gewoon alleen met BAR, BAZ, FOO, en FOOBAR,
maken dat in een tekstbestand, gescheiden mensen elk met 1 regel,
en maak uw eigen tekst bestand dat alleen letterlijk bevat misschien 1 of 2 woorden
zodat u precies weet wat de output zou moeten zijn.
Een deel van het monster tekstbestandjes die in The Big Board als je uitdaging loopt zal controleren
zijn Oorlog en Vrede en een roman van Jane Austen of iets dergelijks.
Dus als je begint, is het een stuk gemakkelijker om uw eigen tekst bestanden
die bevatten slechts een paar woorden of misschien 10
zodat u kunt voorspellen wat de uitkomst zou moeten zijn
en controleer vervolgens het tegen dat, dus meer van een gecontroleerde voorbeeld.
En dus, omdat we te maken hebben met het voorspellen van en tekenen dingen rond,
nogmaals, ik wil u aanmoedigen om pen en papier te gebruiken
omdat het echt gaat om u te helpen met deze -
het tekenen van de pijlen, hoe de hash-tabel of hoe je eruit ziet trie,
als je het vrijmaken van iets waar de pijlen gaan,
je vasthouden aan genoeg, zie je alle links verdwijnen
en vallen in de afgrond van gelekte geheugen.
Dus alsjeblieft, probeer om dingen te tekenen, zelfs voordat je bij het schrijven van code beneden.
Teken dingen uit, zodat u weet hoe de dingen gaan aan de slag
want dan garandeer ik je daar tegenkomen minder pointer warboel.
>> Oke.
Ik wens u het allerbeste van geluk met deze PSET.
Het is waarschijnlijk de moeilijkste.
Dus probeer te vroeg beginnen, trekken dingen uit, trekken dingen uit, en veel geluk.
Dit was Walkthrough 5.
>> [CS50.TV]