[Powered by Google Translate] [Walkthrough - Set Problema 5]
[Zamyla Chan - Universitatea Harvard]
[Acest lucru este CS50. - CS50.TV]
>> Bine. Bună ziua, tuturor, si bun venit la Walkthrough 5.
>> Pset5 este Scriere, in care vom face o vraja-checker.
Spell-dame sunt extrem de importante.
Sa această ți sa întâmplat vreodată?
Tu lucrezi foarte, foarte acumulează pe o hârtie de o ciocnire
și apoi ajunge în continuare obținerea unei Rade strălucire foarte ca un D sau o = D
și tot pentru că sunteți leberwurst spoilerul din cuvântul balena larg.
Da, corectura ardei dvs. este o chestiune de, impotenta cea mai mare măsură.
Aceasta este o problemă care afectează elevii masculine, bărbătești.
Am fost o dată spus de către călăul meu clasa sith că n-ar intra într-o bun coleg.
Și asta e tot ce mi-am dorit, asta-i tot orice copil vrea la vârsta mea,
doar pentru a obține într-un bun coleg.
Și nu orice fel de coleg. Nu, am vrut să merg la un coleg juridic de Fildeș.
Așa că, dacă nu am făcut îmbunătățiri, ar fi dus visele mele de a merge la Harvard,
Jale, sau Prison - Știi, în închisoare, New Jersey.
Așa că am luat eu o verificatorul ortografic.
Asta e un fragment mic de la unul din artiștii mei favoriți sugerate vorbite, Taylor Mali.
Oricum, după cum spune el, importanța de a avea o vraja-pul este foarte importantă.
>> Deci, bun venit la Walkthrough 5, în care vom vorbi despre pset5: greșeli de ortografie,
în care vom fi a face propriile noastre foarte verificatorul ortografic.
Setul de instrumente pentru această săptămână, codul de distribuție, va fi important să se uite la
doar pentru a înțelege diferitele funcții pe care dicționarul dvs. este de gând să aibă.
Suntem de fapt de gând să fi având mai multe fișiere. C, care fac împreună PSET nostru.
Și astfel în căutarea prin diferitele aspecte, chiar dacă nu suntem de fapt, editare
unul dintre fișierele, speller.c, știind cum funcționează cu privire la dictionary.c,
care vom fi scris, va fi destul de important.
Spec. PSET conține, de asemenea, o mulțime de informații utile
în ceea ce privește lucrurile pe care le poate asuma, reguli și lucruri de genul asta,
astfel încât să fie sigur de a citi cu atenție spec. PSET pentru sfaturi.
Și când în dubiu de o regula sau ceva de genul asta, atunci se referă întotdeauna la spec. PSET
Discutați sau.
Acest PSET este de gând să se bazeze foarte mult pe indicii,
așa că doriți să vă asigurați că înțelegem diferența dintre stele adăugarea
în fața numelui pointer și ampersand, cum să le elibereze, etc
Deci, fiind un maestru al pointeri va fi de mare ajutor în acest set de probleme.
Ne vom uita în liste legate de un pic mai mult,
în cazul în care avem elemente pe care le numim noduri, care au atât o valoare, precum și un indicator
la nodul următor, și așa mai departe, în esență care leagă diferitele elemente, una după alta.
Există câteva opțiuni diferite de punere în aplicare dicționarul dvs. real.
Ne vom uita în două metode principale, care este tabele de dispersie și apoi încearcă.
În ambele acestea, ele implică un fel de noțiunii de listă legată
în cazul în care v-ați elemente legate una de alta.
Și așa am de gând să se uite peste modul în care ar putea fi în măsură să opereze în jurul valorii de liste legate,
creați-le, navigați în ceea ce privește modul de a, de exemplu, se introduce un nod în ea
sau gratuit, toate nodurile, precum și.
În ceea ce privește noduri furtună, asta e foarte important
că ori de câte ori am de memorie malloc, după care l-am elibera.
Deci, vrem să ne asigurăm că nu merge indicatorul unfreed, că nu avem nici o scurgere de memorie.
Vom introduce un instrument numit Valgrind care execută programul tău
și verifică dacă toate de memorie pe care le alocată este apoi eliberat.
PSET este completă doar atunci când aceasta funcționează și are funcționalitate completă,
dar, de asemenea, Valgrind vă spune că nu ați găsit nici o scurgere de memorie.
În cele din urmă, pentru acest PSET, chiar vreau să subliniez -
Adică, ca de obicei, eu sunt cu siguranta un suporter de a folosi creion și hârtie pentru seturi de problema ta,
dar pentru asta, cred că stilou și hârtie va fi deosebit de important
atunci când doriți să fie desen săgețile pentru a înțelege lucrurile și cum funcționează lucrurile.
Deci, încercați cu siguranta pentru a utiliza un stilou și hârtie pentru a trage lucrurile înainte de a te codificare
deoarece ar putea obține un pic murdar.
>> În primul rând, hai să mergem în liste legate de un pic.
Lista de preturi legate constau din noduri, unde fiecare nod are o valoare asociată cu acesta,
precum și un pointer la nodul următor după el.
Un tânăr de lucruri importante cu listele legate sunt că avem nevoie să ne amintim
în cazul în care primul nostru este nod, și apoi o dată știm unde este primul nod,
în acest fel putem accesa nodul care primele puncte de nod la
și apoi una după care și una după asta.
Si apoi ultimul element din lista dvs. de legat este indicatorul care nodului
este întotdeauna de gând să indice NULL.
Atunci când un nod de puncte la NULL, atunci știi că ai ajuns la sfârșitul listei,
că nodul este ultima, că nu e nimic după aceea.
Aici, în acest schematică, veți vedea că săgețile sunt indicii,
și secțiunea albastră este în cazul în care valoarea este stocată,
și apoi caseta de culoare roșie, cu indicatorul la aceasta este indicatorul nodului
arătând spre nodul următor după el.
Și așa te văd aici, nodul D ar indica NULL, deoarece acesta este ultimul element din listă.
>> Să ne uităm la modul în care am putea defini o struct pentru un nod.
Si din moment ce dorim să avem mai multe noduri,
acest lucru se întâmplă pentru a deveni un typedef struct
în care vom avea mai multe instanțe diferite de noduri.
Și așa l-am defini ca un nou tip de date.
Aici, avem un nod typedef struct.
În acest exemplu, avem de-a face cu noduri întregi,
așa că avem o valoare de tip întreg numit și apoi avem un alt indicator,
și, în acest caz, este un pointer la un nod, așa că avem un nod struct * numit următoare.
Și apoi ne suni acest nod totul.
Asigurați-vă că urmați această sintaxă.
Observați că nodul este de fapt face referire la mai sus, precum și sub acolade.
Apoi, pentru a ține evidența în cazul în care nod prima mea este în această listă legată,
atunci am un pointer nodul numit cap, si am spatiu suficient pentru malloc dimensiunea unui nod.
Comunicarea, cu toate acestea, faptul că șeful este de fapt un pointer nod, spre deosebire de un nod în sine.
Deci, de fapt, capul nu conține nici o valoare,
doar arată spre oricare dintre primul nod din lista mea legată este.
>> Pentru a obține un sentiment mai bună a listelor legate, pentru că e foarte important
pentru a urmări asigurându-vă că vă menține lanțul,
Îmi place să mă gândesc la ea ca oamenii dintr-o linie de tinutul de mana,
în cazul în care fiecare persoană este tinutul de mana cu următoarea.
Nu puteți vedea în acest desen, dar în esență ei indică spre următoarea persoană
care este în lanțul lor.
Și așa că, dacă vrei să traverseze o listă legat în cazul în care acești oameni -
imagina toate aceste persoane au valori asociate cu acestea
și, de asemenea, punctul următoarea persoană în linie -
dacă doriți să traverseze lista de legat, de exemplu, pentru a edita fie valorilor
sau căutați pentru o valoare sau ceva de genul asta,
atunci veți dori să aibă un pointer la anumite persoane.
Deci, vom avea un nod de date pointer de tip.
Pentru acest exemplu, să-i spunem cursorul.
Un alt mod comun pentru a numi acest lucru ar fi iterator sau ceva de genul asta
deoarece este iterarea peste si de fapt se deplasează pe care nodul este îndreptat spre.
Acest lucru va fi aici cursorul noastră.
Cursorul nostru va indica primul primul element din lista noastră.
Și astfel ceea ce dorim să facem este ne-ar fi continuarea practic cursorul,
deplasându-l dintr-o parte în alta.
În acest caz, vrem să-l mutați la următorul element din listă.
Cu matrice, ceea ce ne-ar face este să ne spunem doar că creșterea indicelui de 1.
În acest caz, ceea ce trebuie să facem este să găsească de fapt pe care persoana această persoană curent este îndreptat spre,
și că va fi următoarea valoare.
Deci, în cazul în care cursorul este doar un pointer nod, atunci ceea ce vrem să facem
este vrem să ajungem la valoarea pe care cursorul se indică spre.
Dorim să ajungem la acel nod și apoi, odată ce suntem la acel nod, că în cazul în care este îndreptat spre.
Pentru a ajunge la nodul real pe care cursorul este îndreptat spre,
de obicei, vom indica aceasta prin (* cursor).
Asta ar da nodul real pe care cursorul se indică spre.
Și apoi după aceea, ceea ce vrem sa facem este vrem să acceseze
indiferent de faptul că valoarea nodului urmator este.
Pentru a face acest lucru, pentru a accesa valorile din interiorul struct, avem operator de punct.
Deci, atunci ar fi (* cursor). Următor.
Dar acest lucru este un pic dezordonat din punct de vedere având paranteze în jurul valorii de cursorului *,
și astfel vom înlocui această declarație întregi, cu cursorul->.
Aceasta este o liniuță și apoi un semn mai mare decât, făcând astfel o săgeată.
cursorul-> urmator.
Care va primi de fapt, vă nodul care punctele de la cursorul. Această valoare este de viitor.
Deci, în loc de a avea stele și punct, esti înlocuind asta cu o săgeată.
Fii foarte atent pentru a asigurați-vă că încercați să utilizați această sintaxă.
>> Acum, că avem cursorul noastre, dacă vrem să acceseze valoarea,
înainte, am avut cursorul-> urmator,
dar pentru a accesa valoarea de la nodul care cursorul este orientată spre, ne-am spus pur și simplu
nod-> valoare.
De acolo, e de tipul de date tot ce ne-am definit valorile și noduri de a fi.
Dacă e un nod int, atunci cursorul-> valoare este doar de gând să fie un număr întreg.
Astfel încât să putem face operații pe care, verificați egalități, aloca valori diferite, etc
Deci, atunci ceea ce vrei să faci în cazul în care doriți să mutați cursorul la următoarea persoană,
ai schimba de fapt valoarea cursorului.
Deoarece cursorul este un pointer nod, vă schimbați adresa de indicatorul reală
la adresa nodului următor din lista ta.
Acesta este doar un cod în cazul în care ai putea repeta.
În cazul în care am comentariu facă ceva,
asta e în cazul în care probabil te duci pentru a accesa valoarea
sau de a face ceva de-a face cu acel nod specific.
Pentru a începe, am spune că cursorul meu inițial
se va indica primul element din listă legată.
Și astfel în față, l-am definit ca șef al nodului.
>> Așa cum am menționat mai înainte, eliberând este foarte important.
Doriți să vă asigurați că ați elibera fiecare element în listă, odată ce ați terminat cu ea.
Când nu trebuie să facă referire la oricare dintre aceste indicii mai,
doriți să vă asigurați că vă elibera toate aceste indicii.
Dar vrei să fim foarte atenți aici, în care doriți, pentru a evita orice scurgeri de memorie.
Dacă aveți o singură persoană liber prematur, atunci toate indicii că această punctele de nod la
vor fi pierdute.
Revenind la exemplul persoana pentru a face un pic mai mari mize,
să aibă acești oameni, cu excepția cazului în acest caz, ei sunt deasupra unui lac cu un monstru.
Dorim să vă asigurați că ori de câte ori ne eliberăm, să nu pierdem
și să mergem la orice noduri înainte de a-am de fapt, le-a eliberat.
De exemplu, dacă ați fost de a apela pur și simplu gratuit pe tipul ăsta aici,
atunci el va fi eliberat, dar apoi toate aceste baieti ar fi pierdut
și le-ar adormiți și cad jos.
Deci, vrem să ne asigurăm că, în loc, dorim să mențină o legătură restul.
Indicatorul nostru central, care indică primul element din listă.
E ca un fel de frânghie de ancorare prima persoană.
Ce ar putea să doriți să faceți atunci când vă elibera o listă se avea -
Dacă doriți să eliberați primul element în primul rând, atunci puteți avea un pointer temporar
faptul că punctele de la orice Primul element este.
Deci, aveți indicatorul temporară îndreptat aici.
În acest fel, avem o așteptare de primul nod.
Și apoi, din moment ce știm că primul nod va fi eliberat,
atunci ne putem muta acest frânghie, această ancoră, capul nostru,
pentru a indica de fapt, la orice primul indică spre.
Deci, acest cap de fapt indică al doilea element acum.
Acum ne este permis pentru a elibera tot ceea ce este stocat în temp,
și astfel încât să putem șterge că fără ea pune în pericol toate celelalte noduri din lista noastră.
Un alt mod pe care le-ar putea face acest lucru ar putea fi
de fiecare dată când tocmai elibera ultimul element din listă
deoarece acestea sunt garantate de a nu fi indicat nimic.
Deci, ai putea elibera doar pe asta, atunci gratuită aceasta, atunci fără aceasta.
Asta cu siguranta funcționează, dar este un pic mai lent, deoarece prin natura listelor legate,
nu putem pur și simplu sări imediat la ultima.
Trebuie să traverseze fiecare element din listă legată
și verificați dacă unul este faptul că indică spre NULL, verificați de fiecare dată,
și apoi, odată ce vom ajunge la sfârșitul anului, atunci gratuit care.
Dacă ar fi să faci acest proces, v-ar fi de fapt de verificare aici,
verificarea aici, apoi verificând aici, eliberându-l,
apoi merge înapoi, verificarea aici, verificarea aici, eliberându-l,
verificarea aici, și apoi eliberarea.
Care ia un pic mai mult timp. Da.
>> [Elev] Ar fi posibil să se facă o listă legată care stochează un pointer ieșire la sfârșit?
Asta ar fi cu siguranta posibil.
Pentru a repeta întrebarea, este posibil să aibă o structură listă legată
astfel că aveți un pointer ce indică spre sfârșitul listei legate?
Aș spune că e posibil, și de fiecare dată când introduceți ceva în lista de legat
va trebui să actualizeze că indicatorul și lucruri de genul asta.
Tu ar trebui o coada * nod, de exemplu.
Dar când ești punerea în aplicare a acestei funcții, va trebui să se gândească la compromisuri,
place cum de multe ori am de gând să fie iterarea peste acest lucru,
Cat de greu este de gând să fie de a ține evidența coada, precum și capul
precum și iterator meu, si lucruri de genul asta.
Face asta -? >> [Elev] Da.
E posibil, dar în ceea ce privește deciziile de proiectare, va trebui să cântărească opțiunile.
>> Aici este un schelet de cod care să vă permită să elibereze orice element într-o listă legată.
Din nou, deoarece am iterarea peste o listă legat, am de gând să doriți să aveți un fel de cursorului
sau iterator.
Suntem iterarea până când cursorul este NULL.
Tu nu vrei să itera atunci când cursorul este NULL
pentru că înseamnă că nu există nimic în listă.
Deci, atunci aici am face un nod * temporar
arătând spre ceea ce eu sunt în considerare este prima lista mea,
si apoi mi-am muta cursorul meu înainte 1 și apoi gratuit orice am avut-o în depozitare temporară.
>> Acum am ajuns la inserarea în liste legate.
Am trei noduri din lista mea de legat, și să mergem cu cazul simplu
în cazul în care dorim să inserați un alt nod la sfârșitul listei noastre legate.
Pentru a face asta, tot ne-ar face este să ne traverseze
pentru a găsi în cazul în care la sfârșitul curentă a listei este legată, atât de oricare nod indică spre NULL -
asta e aceasta -
și apoi spun, de fapt, acesta nu va fi ultimul nod;
de fapt, vom avea o alta.
Deci, am avea acest curent la un punct la tot ce ne introduce.
Deci, acum, această persoană devine roșu aici, ultimul nod în listă legată.
Și astfel caracteristica de ultimul nod în lista de legat este că arată la NULL.
Deci, atunci ce ne-ar trebui să faceți este să setați indicatorul acest tip roșu la NULL. Acolo.
>> Dar dacă ne-am dorit pentru a insera un nod între al doilea și al treilea?
Asta nu este chiar atat de simplu, pentru că vrem să ne asigurăm
că noi nu da drumul la orice nod din lista noastră legată.
Ceea ce ne-ar trebui să faceți este să vă asigurați că ne ancora la fiecare dintre ele.
De exemplu, să numim această doilea.
Dacă ai spus cel de al doilea arată acum la acest nou
și ai făcut doar un pointer acolo, atunci care ar duce la acest tip se pierde
pentru că nu există nici o legătură cu el.
În schimb - Voi desena acest lucru din nou. Scuză-abilitățile mele artistice.
Noi știm că nu putem pur și simplu link direct 2 la unul nou.
Trebuie să ne asigurăm că vom ține pe ultima.
Ce am putea dori să faceți este să aibă un pointer temporar
la elementul care va fi anexată la.
Deci, atunci avem un pointer temporar acolo.
Din moment ce știm că această treime este ținut evidența,
2 poate lega acum la o noua noastră.
Și dacă acest nou tip roșu va fi între 2 și 3,
atunci ceea ce este indicatorul care tipului de gând să indice? >> [Elev] Temp.
Temp. Da.
Deci, atunci valoarea acestui tip de culoare roșie de pe lângă va fi temp.
Când sunteți introducerea în liste legate, am văzut că am putut
adăuga cu ușurință ceva la capăt, prin crearea unei matrice temporară,
sau în cazul în care am vrut să adauge ceva în mijlocul nostru matrice,
atunci ar fi nevoie de un pic mai mult în jurul valorii de amestecare.
Dacă doriți, de exemplu, au o listă sortată legat,
atunci va trebui să cântărească fel de costurile și beneficiile pe care
pentru că, dacă doriți să aveți o matrice sortate, ceea ce înseamnă că de fiecare dată când introduceți în ea,
este de gând să ia un pic mai mult timp.
Cu toate acestea, dacă doriți să mai târziu, după cum vom găsi, vom dori să,
căutare printr-o listă legată, atunci ar putea fi mai ușor dacă știți că totul este în ordine.
Deci, este posibil să doriți să cântărească costurile și beneficiile de care.
>> Un alt mod de a introduce într-o listă legată este de a insera în începutul unei liste.
Dacă tragem ancora noastră aici - acest lucru este capul nostru -
și apoi au acești oameni legate de acesta,
si apoi avem un nou nod care urmează să fie introdus în început,
atunci ceea ce ar putea vrem să facem?
Ce-ar fi greșit cu doar că vreau să legați roșu la albastru,
pentru că e primul?
Ce s-ar întâmpla aici?
Toate acestea trei ar fi pierdut.
Așa că nu vreau să fac asta.
Din nou, am învățat că trebuie să avem un fel de indicator temporar.
Să aleg să aibă un punct de temporar pentru acest tip.
Atunci putem avea un punct albastru spre temporar
și apoi punct rosu la albastru.
Motivul pentru care am Sunt folosind oamenii de aici este pentru că ne dorim cu adevărat să vizualizeze
tinandu-se de oameni și asigurându-vă că avem un link pentru a le
înainte de a ne da drumul de alta parte sau ceva de genul asta.
>> Acum, că avem un sentiment de preturi legate de - cum putem să creați o listă de legat
și de a crea structurile de care constă în definiția de tip pentru un nod
și apoi asigurându-vă că avem un pointer la capul acestei liste legate -
o dată că avem și știm cum să traverseze printr-o matrice,
accesa diverse elemente, știm cum să inserați și știm cum să le elibereze,
atunci putem intra în greșeli de ortografie.
Ca de obicei, avem și o secțiune de întrebări care vor fi folosite pentru a vă operare cu liste legate
și structuri diferite, cum ar fi cozile și stive.
Apoi, ne putem muta în greșeli de ortografie.
>> Greșeli de ortografie are în codul de distribuție o serie de fișiere de importanță.
În primul rând observăm că avem această Makefile aici,
care nu ne-am întâlnit cu adevărat înainte.
Dacă te-ai uitat în interiorul folderul pset5, vei observa că aveți un fișier ore.,
atunci aveți două fișiere. c..
Ce face acest Makefile este înainte, ne-ar face doar de tip și apoi numele programului
și apoi ne-ar vedea toate aceste argumente și steaguri trecut in pentru a compilatorului.
Ce face Makefile este ne permite să compileze mai multe fișiere în același timp
și treci în pavilioanele pe care ne-o dorim.
Aici vom vedea acolo este un fișier header aici.
Apoi, avem de fapt două fișiere sursă.
Avem speller.c și dictionary.c.
Sunteți bineveniți să editați Makefile, dacă doriți.
Observați că aici dacă tastați curat, atunci ceea ce face este de fapt elimină orice
care este nucleul.
Dacă ai o eroare de segmentare, practic veți obține o groapa de bază.
Deci acest fișier mică și urâtă va apărea în directorul dvs. numit miez.
Veți dori să eliminați că pentru a face curat.
Se elimină toate fișierele exe și. Fișiere o.
>> Să aruncăm o privire în dictionary.h.
Aceasta spune că funcționalitatea declară un dicționar.
Avem o lungime maximă pentru orice cuvânt în dicționar.
Noi spunem că acest lucru va fi cel mai lung cuvânt posibil. Este de lungime 45.
Deci, nu vom avea nici cuvintele pe care depășesc această lungime.
Aici avem doar prototipuri funcționale.
Noi nu avem punerea în aplicare efectivă pentru că este ceea ce vom face pentru acest PSET.
Dar ce face asta este de când am de-a face cu fișiere mai mari aici
și funcționalitatea pe o scară mai largă, e util să aveți un fișier h..
astfel că altcineva a citi sau de a folosi codul poate înțelege ce se întâmplă.
Și poate că vor să pună în aplicare încearcă, dacă ai făcut tabele de dispersie sau invers.
Atunci s-ar spune funcția mea de încărcare,
punerea în aplicare efectivă este de gând să difere, dar acest prototip nu se va schimba.
Aici ne-am verifica, care returnează adevărat dacă un cuvânt dat este în dicționar.
Apoi, avem de încărcare, care, practic, ia într-un fișier dicționar
și apoi se încarcă în unele structuri de date.
Avem dimensiune, care, atunci când numit, returnează dimensiunea dicționarul,
câte cuvinte sunt stocate în ea,
și descărcare, apoi, care eliberează toată memoria pe care este posibil să fi preluat
în timp ce face dicționarul.
>> Să aruncăm o privire la dictionary.c.
Vedem că se pare foarte asemănător cu dictionary.h, cu excepția acum are doar toate aceste Todos în ea.
Și așa că e treaba ta. În cele din urmă, veți fi completarea speller.c cu toate acest cod.
Dictionary.c, atunci când alerga, nu este cu adevărat de gând să faci nimic,
asa ne uităm spre speller.c pentru a vedea punerea în aplicare efectivă a verificatorul ortografic.
Chiar dacă nu sunteți de gând să fie editarea oricare din acest cod,
este important să citească, să înțeleagă atunci când este chemat de sarcină, când mă apel cec,
doar pentru a intelege, harta l, a se vedea cum funcționează funcția.
Vedem că este de verificare pentru utilizarea corectă.
În esență, atunci când cineva se execută abecedar, acest lucru indică faptul că este opțională
pentru ei să treacă într-un fișier dicționar pentru că nu va fi un dicționar de fișier implicit.
Și atunci ei trebuie să treacă în text pentru a fi vraja verificate.
Oferte rusage cu timp deoarece o parte a acestui PSET pe care ne vom ocupa de mai târziu
este nu numai obtinerea unei funcționări verificatorul ortografic de lucru
dar de fapt, obtinerea-l să fie rapid.
Și astfel, atunci asta e în cazul în care rusage este de gând să vină inch
Aici, vom vedea primul apel la unul din fișierele noastre dictionary.c, care este sarcina.
Încărcați returneaza true sau false - adevarat la succes, fals la eșec.
Deci, dacă dicționarul nu este încărcată în mod corespunzător, atunci se va întoarce speller.c 1 și demisia.
Dar dacă o face în mod corespunzător de sarcină, apoi se va continua.
Vom continua, și vom vedea un fisier I / O aici,
în cazul în care se va face cu deschiderea fișier text.
Aici, ce face asta este vraja locului, fiecare cuvânt în text.
Deci, ce speller.c face chiar aici este iterarea peste fiecare dintre cuvintele din fișierul text
și apoi le verificare în dicționar.
Aici, avem un Boolean scris gresit, care va vedea dacă cecul returneaza true sau nu.
În cazul în care cuvântul este, de fapt, în dicționar, atunci verificarea se va întoarce adevărat.
Asta înseamnă că cuvântul nu este scris greșit.
Deci, ar fi greșit fals, si de aceea avem acolo bang-ului, indicația.
Vom continua să mergi, și apoi ține evidența de cât de multe cuvinte scrise greșit
există în dosar.
Acesta continuă pe și închide fișierul.
Atunci aici, acesta raportează câte cuvinte ortografiate greșit ai avut.
Se calculează cât de mult timp a luat pentru a încărca dicționarul,
cât de mult timp a luat să-l verifice,
cât de mult timp a luat pentru a calcula dimensiunea,
care, așa cum vom merge mai departe, ar trebui să fie foarte mici,
și apoi cât de mult timp a luat pentru a descărca dicționarul.
Aici deasupra vom vedea apelul pentru a descărca aici.
Dacă vom verifica pentru dimensiune aici,
apoi vom vedea că aici este apelul la dimensiunea care determină mărimea dicționarului.
Minunat.
>> Sarcina noastră pentru acest PSET este de a pune în aplicare de sarcină, care se va încărca dicționarul
structura de date - Orice variantă ați alege, fie că este vorba un tabel hash sau un try -
cu cuvinte din dicționarul fișierul.
Apoi, aveți dimensiune, care va returna numărul de cuvinte în dicționar.
Și dacă ai pune în aplicare de încărcare într-un mod inteligent, apoi dimensiunea ar trebui sa fie destul de usor.
Atunci ai verifica, care va verifica dacă un anumit cuvânt este în dicționar.
Deci, speller.c trece într-un șir, iar apoi va trebui să verificați dacă această șir
este conținută în dicționarul.
Observați că avem, în general, dicționare standard,
dar în acest PSET, practic orice dicționarul trecut în în orice limbă.
Deci, nu putem presupune doar că cuvântul este în interiorul.
Foobar Cuvântul ar putea fi definită într-un dicționar sigur că vom trece inch
Și atunci ne-am descarce, care eliberează dicționarul din memorie.
>> În primul rând, aș vrea să merg pe metoda de tabel hash
despre cum putem să pună în aplicare toate aceste patru funcții,
si apoi voi trece peste încearcă metoda, cum putem pune în aplicare aceste patru funcții,
iar la sfârșitul vorbesc despre unele sfaturi generale atunci când faci PSET
și, de asemenea, modul în care s-ar putea fi capabil de a utiliza Valgrind pentru a verifica dacă există scurgeri de memorie.
>> Să intrăm în metoda de tabel hash.
Un tabel hash constă dintr-o listă de galeti.
Fiecare valoare, fiecare cuvânt, este de gând să meargă într-una din aceste galeti.
Un tabel hash ideal uniform distribuie toate aceste valori pe care îl trece în
și apoi le populează în găleată, astfel încât fiecare cupă pentru excavat
are aproximativ un număr egal de valori în ea.
Structura pentru un tabel hash, avem o serie de liste legate.
Ceea ce facem este atunci când vom trece într-o valoare, vom verifica în cazul în care valoarea ar trebui să aparțină,
care cupă îi aparține, și apoi puneți-l în lista de legat asociat cu acea cupă.
Aici, ceea ce am este o funcție hash.
E un tabel hash int.
Deci, pentru prima găleată, orice numere naturale mai mici de 10 intra in primul compartiment.
Orice întregi de peste 10, dar sub 20 Du-te în altă parte,
și apoi așa mai departe și așa mai departe.
Pentru mine, fiecare compartiment reprezintă aceste numere.
Cu toate acestea, spun că am fost să treacă în 50, de exemplu.
Se pare ca în cazul în primele trei conțin o serie de zece numere.
Dar eu vreau să permită masa mea hash pentru a lua în orice fel de numere întregi,
da, atunci mi-ar fi de a filtra toate numerele de peste 30 în ultimul compartiment.
Și așa, atunci care ar duce la un fel de tabel hash dezechilibrat.
Pentru a reitera, un tabel hash este doar o serie de cupe
în cazul în care fiecare cupă este o listă legat.
Și astfel pentru a determina în cazul în care fiecare valoare se duce, care merge în cupă,
ai de gând să doriți ceea ce se numește o funcție hash
care ia o valoare și apoi spune această valoare corespunde unei anumite găleată.
Deci, sus, în acest exemplu, funcția mea de distribuire a luat fiecare valoare.
Se verifică dacă aceasta a fost mai mic de 10.
Dacă ar fi fost, l-ar pune în găleată primul.
Se verifică dacă este mai mic de 20, pune-l în două dacă este adevărat,
verifică dacă acesta e mai mic de 30, iar apoi pune în găleată treia,
și apoi toate celelalte doar cade la găleată patra.
Deci, ori de câte ori aveți o valoare, dvs hash funcție
va plasa ca valoarea în găleată corespunzătoare.
Funcția hash practic trebuie să știe cât de multe galeti aveți.
Dimensiunea tabel hash, numărul de compartimente care le aveți,
care va fi un număr fix, care este de până la tine, pentru tine de a decide,
dar o să fie un număr fix.
Deci, funcția de distribuire va fi bazându-se pe faptul că pentru a determina care cupă pentru excavat fiecare tasta merge în
astfel că este uniform distribuită.
Similar cu punerea în aplicare a listelor noastre legate, acum fiecare nod în tabel hash
este, de fapt de gând să aibă un caracter de tip.
Deci, avem un tablou char numit cuvant si apoi un alt pointer la nodul următor,
care are sens, pentru că va fi o listă legată.
Amintiți-vă atunci când ne-am legat de preturi, am facut un nod * cap numit
care a fost îndreptat la primul nod din listă legată.
Dar pentru masa noastră hash, pentru că avem mai multe liste legate,
ceea ce ne dorim este vrem masa noastră de distribuire a fi ca, "Ce este o galeata?"
O galeata este doar o lista de pointeri nod,
și astfel fiecare element în găleată este, de fapt indică sale listă corespunzătoare legate.
Pentru a reveni la acest schematică, veți vedea că ei înșiși sunt gălețile de săgeți,
nu noduri reale.
O proprietate esențială a funcțiilor hash este că acestea sunt deterministe.
Asta înseamnă că ori de câte ori ați hash numărul 2,
ar trebui să revină întotdeauna aceeași găleată.
Fiecare valoare unică, care merge în funcția de hash, dacă se repetă,
are pentru a obține același indice.
Deci, funcția hash returnează indicele de matrice
în cazul în care valoarea aparține.
Așa cum am menționat mai înainte, numărul de compartimente este fix,
și astfel indexul dumneavoastră că vă veți întoarce trebuie să fie mai mică decât numărul de compartimente
dar mai mare decât 0.
Motivul pentru care am avea funcții de dispersie în loc de doar una singură listă legată
sau unul singur array este că ne dorim să fie în măsură pentru a sări la o anumită secțiune cel mai usor
dacă știm caracteristică a unei valori -
în loc de a căuta prin dicționarul întregului,
fiind capabil pentru a sări la o anumită secțiune a acestuia.
Funcția hash ar trebui să țină cont de faptul că în mod ideal,
fiecare compartiment are aproximativ același număr de taste.
Deoarece tabel hash este o serie de liste legate,
apoi listele legate de sine sunt de gând să aibă mai mult de un nod.
În exemplul anterior, două numere de telefon diferite, chiar dacă acestea nu au fost egale,
atunci când trunchiată, se va întoarce același indice.
Deci, atunci când se face cu cuvinte, un cuvânt atunci când trunchiată
ar fi aceeași valoare hash ca un alt cuvânt.
Asta e ceea ce noi numim o coliziune, atunci când avem un nod care, atunci când trunchiată,
lista legat la acea cupă nu este gol.
Tehnica pe care o numim există liniară sondare,
în cazul în care te duci în lista de legat și apoi găsiți în cazul în care doriți să inserați acel nod
pentru că aveți o coliziune.
Puteți vedea că ar putea exista un compromis aici, nu?
Dacă aveți un tabel hash foarte mic, un număr foarte mic de compartimente,
atunci ai de gând să aibă o mulțime de coliziuni.
Dar apoi, dacă faci o masă foarte mare hash,
esti, probabil, de gând să minimizeze coliziunile,
dar o să fie o foarte mare structură de date.
Acolo va fi compromisuri cu asta.
Așa că atunci când faci PSET dumneavoastră, încercați să joace în jurul valorii de
între a face un tabel poate mai mic hash
dar apoi știind că aceasta va dura un pic mai mult pentru a traversa diferitele elemente
din aceste liste legate.
>> Ceea ce sarcina este de gând să faceți este să itera peste fiecare cuvânt în dicționar.
Ea trece într-un pointer la fișierul dicționar.
Deci, ai de gând să profite de fișier I / O, functii pe care le stăpânesc, în pset4
si repeta peste fiecare cuvânt în dicționar.
Vrei fiecare cuvânt în dicționar pentru a deveni un nod nou,
și ai de gând să plaseze fiecare dintre aceste noduri in interiorul tau dicționarul structură de date.
Ori de câte ori veți obține un cuvânt nou, știi că o să devină un nod.
Deci, poti sa te duci imediat și malloc un pointer nod pentru fiecare cuvânt nou pe care aveți.
Aici am sunat new_node mea indicatorul nod și eu mallocing ce? Dimensiunea unui nod.
Apoi, pentru a citi șir real dintr-un fișier, pentru că dicționarul este, de fapt stocate
printr-un cuvânt și apoi o linie nouă, ceea ce putem profita de
este funcția fscanf,
care fisier este fișierul dicționarul că suntem în trecut,
așa că scanează fișierul pentru un șir și locuri care șir în ultimul argument.
Dacă vă reamintesc din nou la una din prelegerile, atunci când ne-am dus peste
și tipul de cojit straturilor înapoi pe biblioteca CS50,
am văzut o punere în aplicare a fscanf acolo.
Pentru a reveni la fscanf, avem fișierul care ne citesc din,
suntem în căutarea pentru un șir de caractere în acel fișier, iar apoi ne-l plasarea în
aici am new_node-> cuvânt, deoarece new_node este un pointer nod,
Nu o reală nod.
Deci, atunci eu spun new_node, vreau să merg la nodul care este îndreptat spre
apoi atribuiți acea valoare la cuvânt.
Dorim să ia apoi acest cuvânt și introduceți-l în tabel hash.
Dau seama că am făcut new_node un pointer nod
pentru că am de gând să vreau să știu ce adresa de acel nod este
atunci când l-am introduce în cauza structura a nodurilor în sine, de struct,
este faptul că acestea au un pointer la un nod nou.
Deci, atunci ce e adresa pe care nod de gând să indice?
Această adresă va fi new_node.
Asta face sens, de ce facem new_node un nod *, spre deosebire de un nod?
Bine.
Avem un cuvânt. Această valoare este new_node-> cuvânt.
Care conține cuvântul din dicționar care ne-o dorim la intrare.
Deci, ceea ce dorim să facem este să vrem numim funcția noastră de distribuire pe care șir
deoarece funcția de distribuire noastră are într-un șir și apoi returnează un întreg ne,
în cazul în care este întreg în cazul în care indicele hashtable la care indicele reprezintă acea cupă.
Dorim să indice faptul că și apoi du-te la faptul că indicele de tabel hash
și de a folosi apoi că lista legat pentru a insera nodul de la new_node.
Amintiți-vă că toate acestea vă decideți să inserați nodul dumneavoastră,
dacă e în mijloc, dacă doriți să-l sortați
sau la începutul sau la sfârșitul, asigurați-vă doar că nod ultima ta întotdeauna arată la NULL
pentru că e singurul mod în care știm unde ultimul element al listei noastre legate este.
>> Dacă dimensiunea este un număr întreg care reprezintă numărul de cuvinte într-un dicționar,
apoi o modalitate de a face acest lucru este faptul că ori de câte ori este chemat dimensiune
trecem prin fiecare element în tabelul nostru de dispersie
si apoi repeta prin fiecare listă legată în tabel hash
și se calculează apoi lungimea de faptul că, creșterea noastră contra 1 cu 1.
Dar de fiecare dată că mărimea este numit, care este de gând să ia o lungă perioadă de timp
pentru că am de gând să fie liniar probeze fiecare listă unică legată.
În schimb, acesta va fi mult mai ușor dacă țineți evidența cât de multe cuvinte sunt transmise inch
Deci dacă includeți un contor în funcție de încărcare dvs.
că actualizările este necesar, apoi contra, dacă l-ați setat la o variabilă globală,
vor putea fi accesate de dimensiunea.
Deci, ce dimensiune ar putea face pur și simplu se află în o singură linie, întoarce doar valoarea contorului,
dimensiunea dicționarului, care deja tratate în sarcină.
Asta e ceea ce am vrut să spun când am spus că, dacă punerea în aplicare a sarcinii într-un mod util,
apoi dimensiunea va fi destul de ușor.
>> Deci, acum ajungem să verifice.
Acum avem de-a face cu cuvinte din fișierul text de intrare,
și astfel vom fi verifica dacă toate aceste cuvinte de intrare
sunt de fapt în dicționarul sau nu.
Similar cu Scramble, dorim pentru a permite insensibilitate caz.
Doriți să vă asigurați că toate cuvintele au trecut în, chiar dacă ele sunt regim mixt,
când este apelat cu șir de comparare, sunt echivalente.
Cuvintele din dicționar fișiere text sunt de fapt toate cu litere mici.
Un alt lucru este că puteți presupune că fiecare cuvânt din trecut, fiecare șir,
este de gând să fie alfabetică sau conțin apostrofuri.
Apostroful vor fi valabile în cuvinte dicționarul nostru.
Deci, dacă aveți un cuvânt cu apostrof S, care este un cuvânt real legitim în dicționarul
care va fi unul dintre nodurile din tabel hash.
Verificați dacă funcționează cu cuvântul există, atunci trebuie sa fie in masa noastră hash.
În cazul în care cuvântul este în dicționar, atunci toate cuvintele din dicționar sunt în tabelul hash,
așa că hai să ne uităm pentru acest cuvânt în tabel hash.
Noi știm că de când am implementat functia noastra de distribuire
astfel încât fiecare cuvânt unic este întotdeauna trunchiată la aceeași valoare,
atunci știm că, în loc de a căuta prin intermediul nostru intreaga întregul tabel hash,
putem găsi de fapt, lista legată că acest cuvânt ar trebui să aparțină.
Dacă ar fi fost în dicționar, atunci acesta ar fi în acea găleată.
Ce putem face, în cazul în care cuvântul este numele nostru a trecut în șir,
putem doar hash acest cuvânt și gasiti lista de legat
la valoarea de Hashtable [hash (cuvânt)].
De acolo, ceea ce putem face este, avem un subset mic de noduri pentru a căuta acest cuvânt,
și astfel încât să putem traversa lista de legat, folosind un exemplu din mai devreme în walkthrough,
și apoi apel șir compara pe cuvântul ori de câte ori este cursorul indică spre,
acest cuvânt, și a vedea dacă cele comparare.
În funcție de modul în care vă organizați funcția hash,
în cazul în care este sortat, ați putea fi în măsură să se întoarcă fals un pic mai devreme,
dar dacă e nesortate, apoi doriți să continuați traversarea prin lista dvs. de legat
până când găsiți ultimul element al listei.
Și dacă încă nu ați găsit cuvântul de timp ați ajuns la sfârșitul listei legate,
ceea ce înseamnă că cuvântul tău nu există în dicționar,
și astfel încât cuvântul este nevalid,
și verificare ar trebui să returneze fals.
>> Acum am ajuns la descărcarea, în cazul în care vrem să eliberăm toate nodurile pe care le-am malloc'd,
atât de liber toate nodurile din interiorul masa noastră hash.
Am de gând să doriți să itera peste toate listele legate și libere toate nodurile din asta.
Daca te uiti mai sus, în pas cu pas pentru exemplul care ne eliberăm o listă legat,
atunci veți dori să repetați acest proces pentru fiecare element în tabelul hash.
Și eu voi trece peste acest spre sfârșitul walkthrough,
dar Valgrind este un instrument în cazul în care puteți vedea dacă ați eliberat în mod corespunzător
fiecare nod pe care le-ați malloc'd sau orice altceva pe care le-ați malloc'd, orice alt indicator.
Deci asta e tabele de dispersie, în cazul în care avem un număr finit de compartimente
și o funcție hash care va avea o valoare și apoi atribui acea valoare într-o găleată anume.
>> Acum am ajuns la incercari.
Incearca un fel de look asa, si eu voi trage de asemenea un exemplu.
Practic, aveți o gamă întreagă de scrisori potențiali,
și apoi ori de câte ori sunteți construirea unui cuvânt,
această scrisoare poate fi legat de un dicționar pentru o gamă largă de posibilități.
Câteva cuvinte încep cu C, dar apoi continua cu A,
dar altele continua cu O, de exemplu.
Un trie este un mod de vizualizare toate combinațiile posibile ale acestor cuvinte.
Un trie este de gând să țină evidența succesiune de litere, care cuprind cuvinte,
ramificatie atunci când este necesar, atunci când o singură literă poate fi urmat de un multiplu de scrisori,
și la sfârșitul indica la fiecare punct, dacă acel cuvânt este valabil sau nu
pentru că dacă sunteți de ortografie cuvântul MAT, MA nu cred că este un cuvânt valid, dar este MAT.
Și astfel, în trie dvs., ar indica faptul că, după MAT, că e de fapt un cuvânt valabil.
Fiecare nod în trie nostru este, de fapt de gând să conțină o serie de indicii nod,
și am de gând să aibă, în mod special, 27 din aceste indicii nod,
unul pentru fiecare literă din alfabet, precum și caracterul apostrof.
Fiecare element din matrice, care este ea însăși va pentru a indica un alt nod.
Deci, în cazul în care nodul este NULL, dacă nu există nimic după aceea,
atunci știm că nu e nici o scrisoare în continuare în această secvență cuvânt.
Dar, în cazul în care nodul nu este NULL, ceea ce înseamnă că există mai multe scrisori în care secvența de scrisoare.
Și apoi în plus, fiecare nod indică dacă este ultimul caracter al unui cuvânt sau nu.
>> Să mergem într-un exemplu de trie.
În primul rând am camera de 27 de noduri în această matrice.
Dacă am BAR cuvântul -
Dacă am BAR cuvântul și vreau să inserați că, în,
prima scrisoare este B, deci, dacă trie meu este gol,
B este a doua literă a alfabetului, așa că am de gând să aleagă pentru a pune asta aici, la acest indice.
Am de gând să aibă B aici.
B va fi un nod care indică un alt tablou al tuturor caracterelor posibile
care poate urma după litera B.
În acest caz, am de-a face cu BAR cuvântul, deci A va merge aici.
După o, am litera R, astfel încât atunci A punctele acum la combinația proprie,
și apoi R va fi aici.
Bar este un cuvânt complet, deci atunci am de gând să aibă R punct la un alt nod
care spune că acest cuvânt este valabil.
Această nod este, de asemenea, va avea o serie de noduri,
dar ar putea fi cele NULL.
Dar în esență, se poate continua așa.
Care va deveni un pic mai clar atunci când vom merge la un alt exemplu,
astfel încât să poarte cu mine acolo.
Acum avem BAR interiorul dicționarul nostru.
Acum spune ca avem BAZ cuvântul.
Vom începe cu B, și avem deja B, ca fiind unul dintre cele scrisori pe care e în dicționarul nostru.
Asta a urmat cu A. Avem o deja.
Dar apoi în schimb, avem Z text.
Deci, atunci un element în gama noastră va fi Z,
și așa mai apoi că unul este de gând să indice către un alt valabilă a cuvântului.
Deci, vom vedea că, atunci când vom continua prin B și apoi A,
există două opțiuni diferite în prezent în dicționarul nostru pentru cuvinte care încep cu B și A.
Spune-am dorit pentru a introduce cuvântul foobar.
Apoi, ne-ar face o intrare la F.
F este un nod care indică o gamă întreagă.
Ne-ar găsi O, du-te la O, O apoi link-uri într-o listă întreagă.
Am avea B și apoi să continue, vom avea A și apoi R.
Deci, atunci traverseaza foobar tot drumul în jos până când foobar este un cuvânt corect.
Și așa, atunci acest lucru ar fi un cuvânt validă.
Acum spune cuvântul nostru următor în dicționarul este de fapt cuvântul FOO.
Ne-ar spune F. Ceea ce urmează F?
De fapt am deja un spațiu pentru O, așa că am de gând să continue.
Nu am nevoie pentru a face unul nou. Continuare.
FOO este un cuvânt valabil în acest dicționar, așa că atunci am de gând să indice
că este validă.
Dacă mă opresc secvența mea acolo, care ar fi corect.
Dar dacă ne-am continuat secvența noastră de la FOO în jos la B
și a avut doar FOOB, FOOB nu este un cuvânt, și că nu este indicat ca unul valid.
Într-un trie, ai fiecare nod indicând dacă este un cuvânt valid sau nu,
și apoi la fiecare nod are, de asemenea, o serie de 27 de noduri pointeri
care apoi indicați spre nodurile ei înșiși.
>> Aici este o modalitate de modul în care ați putea dori să definiți asta.
Cu toate acestea, la fel ca în exemplul de tabel hash, unde am avut un cap * nod
pentru a indica începutul lista noastră legată, de asemenea, suntem de gând să doriți
un mod de a ști unde începutul trie nostru este.
Unii oameni încearcă apel copaci, și că, în cazul în care este rădăcina vine de la.
Deci, vrem rădăcina arborelui nostru pentru a ne asigura că rămâne la pământ
către orice destinație trie nostru este.
Am deja un fel de trecut peste
modul în care ar putea gândi despre încărcarea fiecare cuvânt în dicționar.
În esență, pentru fiecare cuvânt ai de gând să doriți să itera prin trie dvs.
și știind că fiecare element din copiii - am numit-o copiii în acest caz -
corespunde o literă diferită, ai de gând să doriți să verificați aceste valori
la faptul că indicele special, care corespunde literei.
Deci gândesc tot drumul înapoi la Cezar și Vigenere,
știind că fiecare literă poți fel de hartă înapoi la un index alfabetic,
cu siguranta de la A la Z va fi destul de ușor pentru a mapa o scrisoare alfabetică,
dar, din păcate, apostroful, de asemenea, un caracter acceptat în cuvinte.
Nici măcar nu sunt sigur ce valoarea ASCII este,
astfel pentru că, dacă doriți să găsiți un index pentru a decide dacă doriți să fie primul
sau ultima, veți avea de a face o verificare greu codificate pentru că
și a pus apoi că în indexul 26, de exemplu.
Deci, atunci se verifica valoarea la copii [i]
în cazul în care [i] corespunde la orice scrisoare ești.
Dacă e NULL, ceea ce înseamnă că nu există în prezent nici o scrisoare posibile
decurge din faptul că secvența anterioară, astfel încât ai de gând să doriți să malloc
și să facă un nod nou și să aibă copii ca [i] punctul să-l
astfel încât să creați - atunci când am introdus-o scrisoare în dreptunghi -
a face copii non-NULL și cu punctul în care nod nou.
Dar în cazul în care nu este NULL, ca și în cazul nostru de FOO
când am avut deja foobar, vom continua,
iar noi nu facem niciodata un nod nou, ci mai degrabă doar setarea pe true is_word
la sfârșitul acestui cuvânt.
>> Deci la fel ca înainte, pentru că aici ai de a face cu fiecare literă la un moment dat,
că va fi mai ușor pentru tine pentru a dimensiune, in loc de a avea pentru a calcula
și du-te prin copac întreg și calculeze câți copii am eu
și apoi ramificațiile, amintindu-și cum mulți sunt pe partea stângă și pe partea dreaptă
și lucruri de genul asta, o să fie mult mai ușor pentru tine
dacă vă păstrați doar evidența numărului de cuvintele pe care le adăugați în
atunci când ai de a face cu sarcina.
Și astfel, atunci dimensiunea fel se poate returna doar o variabilă globală de mărime.
>> Acum ajungem pentru a verifica.
Aceleași standarde ca și până acum, în cazul în care dorim să permită insensibilitate caz.
De asemenea, vom presupune că șirurile sunt doar caractere alfabetice sau apostrofuri
deoarece copiii este o matrice de 27 lung,
astfel încât toate literele din alfabet, plus apostrof.
Pentru verificați ceea ce veți dori să faceți este să vă veți dori să înceapă de la rădăcină
deoarece radacina va indica o matrice care conține
toate literele posibile minime orientative ale unui cuvânt.
Ai de gând să înceapă acolo,
si apoi ai de gând să verificați este această valoare NULL sau nu,
pentru că dacă valoarea este NULL, ceea ce înseamnă că dicționarul nu are nici o valoare
care conțin această scrisoare, în care o ordine anume.
Dacă e NULL, atunci înseamnă că cuvântul este greșit imediat.
Dar dacă nu e NULL, atunci puteți continua,
spun că prima literă este o scrisoare de prim posibil într-un cuvânt,
asa ca acum vreau pentru a verifica dacă a doua scrisoare, că secvența, este în dicționarul meu.
Deci, ai de gând să mergi la index al copiilor din primul nod
și verificați dacă această scrisoare există două.
Apoi, repetați acest proces pentru a verifica dacă această secvență este valabil sau nu
în cadrul trie dumneavoastră.
Ori de câte ori copiii nodului de la faptul că punctele de index pentru a NULL,
știți că secvența nu există,
dar apoi, dacă ați ajunge la sfârșitul cuvântul pe care le-ați introduse,
apoi doriți să verificați acum că am terminat această secvență
și a găsit în trie mea, este acel cuvânt valabil sau nu?
Și da, atunci vă doriți pentru a verifica dacă, și atunci, dacă ați constatat că secvența,
apoi doriți să verificați dacă acel cuvânt este valabil sau nu
deoarece amintesc înapoi în cazul anterior pe care am desenat în cazul în care am avut FOOB,
că a fost o secvență validă pe care am găsit, dar nu a fost un cuvânt real valabile în sine.
>> În mod similar, pentru descarce în încercări pe care doriți să descărcați toate nodurile din trie ta.
Scuze. Similar cu tabelele de dispersie în cazul în care, în descarca am freed toate nodurile,
în încercările pe care dorim să eliberăm de asemenea, toate nodurile.
Unload va lucra de fapt, cea mai simplă de jos în sus
deoarece acestea sunt în esență de preturi legate.
Așa că vrem să ne asigurăm că țineți pe toate valorile
și fără toate acestea în mod explicit.
Ce ai de gând să doriți să faceți în cazul în care lucrați cu un trie
este de a călători în partea de jos și gratuit nodul cel mai mic posibil primul
și apoi du-te până la toate aceste copii și apoi gratuit tuturor celor,
du-te în sus și apoi liber, etc
Un fel de a face cu stratul de jos al primului trie
si apoi merge până sus, odată ce am eliberat totul.
Acesta este un exemplu bun de unde ar putea veni funcție recursivă la îndemână.
Odată ce v-ați eliberat pe stratul de jos a trie dumneavoastră,
atunci suna descărcați pe restul,
asigurându-vă că vă gratuit în fiecare mini -
Puteți vizualiza un fel de mini-l ca incercari.
Deci, aveți rădăcină aici.
Sunt doar simplificarea așa că nu trebuie să atragă 26 dintre ele.
Deci ai astea, iar apoi acestea reprezintă secvențe de cuvinte
în cazul în care toate aceste cercuri mici sunt litere care sunt valabile secvențe de litere.
Să continuăm doar un pic mai mult.
Ce ai de gând să doriți să faceți este gratuit partea de jos aici și apoi gratuit aceasta
și apoi gratuit o una în partea de jos înainte de a vă elibera cea de sus aici
pentru că dacă ceva gratuită în al doilea nivel aici,
atunci tu de fapt ar pierde această valoare aici.
De aceea e important în descărcarea pentru un trie pentru a vă asigura că vă elibera de jos primul.
Ce ar putea să doriți să faceți este să spunem pentru fiecare nod
Vreau să descarce toți copiii.
>> Acum, că am trecut peste descarce pentru metoda de tabel hash, precum și metoda de trie,
am de gând să doriți să se uite la Valgrind.
Valgrind aveți cu următoarele comenzi.
Ai Valgrind-V.
Ești de verificare pentru toate scurgeri atunci când rulați descifrează dat acest text anumită
deoarece descifrează trebuie să ia într-un fișier text.
Deci, Valgrind va rula programul tău, vă spun cât de multe bytes tine alocat,
cati bytes te-a eliberat, și vă va spune dacă te-a eliberat suficient
sau dacă nu liber suficient,
sau, uneori, puteți chiar peste-free, cum ar fi gratuit un nod care a fost eliberat deja
și așa va veți reveni erori.
Dacă utilizați Valgrind, aceasta vă va da unele mesaje
indicând dacă ați eliberat fie mai mult decât suficient, suficient,
sau mai mult de suficient de multe ori.
>> O parte a acestui PSET, este opțională pentru a contesta Consiliul de mare.
Dar când avem de-a face cu aceste structuri de date
e un fel de distractiv pentru a vedea cât de repede și cât de eficient structurile de date ar putea fi.
Are rezultatul funcției hash într-o mulțime de coliziuni?
Sau este dimensiunea foarte mare de date?
Are ea lua o mulțime de timp pentru a traversa?
În jurnalul de abecedar, să emită cât de mult timp le utilizați pentru a încărca,
pentru a verifica, pentru a efectua dimensiuni, și de a descărca,
și astfel acestea sunt postate în Consiliul de Big,
în cazul în care aveți posibilitatea să concureze cu colegii dvs.
și unii membri ai personalului pentru a vedea cine are cel mai rapid verificatorul ortografic.
Un lucru pe care aș vrea să rețineți despre tabelele de dispersie
este faptul că există unele funcții destul de simple, pe care le-ar putea hash gândi.
De exemplu, aveți 26 găleți, și așa în fiecare cupă
corespunde primei litere într-un cuvânt,
dar asta va duce într-un tabel hash destul de dezechilibrată
pentru că există o mulțime cuvinte care încep cu mai puțin decât X începe cu M, de exemplu.
Un mod de a merge despre abecedar este dacă doriți să obțineți toate alte funcționalități în jos,
apoi utilizați doar o simplă funcție hash pentru a putea pentru a obține codul de alergare
și apoi du-te înapoi și modifica dimensiunea tabelului hash și definiția.
Există o mulțime de resurse de pe Internet pentru funcțiile hash,
și astfel pentru acest PSET vă este permis să cerceteze funcțiile hash pe internet
pentru unele sugestii și inspirație, atâta timp cât vă asigurați-vă pentru a cita în cazul în care l-ați primit de la.
Ești binevenit să te uiți și să interpreteze o funcție de distribuire pe care le găsiți pe Internet.
Înapoi la care, ați putea fi capabil de a vedea dacă cineva a folosit un trie
dacă punerea în aplicare a acestora este mai rapidă decât masa ta hash sau nu.
Puteți să prezinte consiliului Big de mai multe ori.
Acesta va înregistra intrarea cea mai recentă.
Deci, poate că vă schimbați funcția hash și apoi dau seama că este de fapt mult mai repede
sau mult mai lent decât înainte.
Asta e un pic de un mod distractiv.
Nu e întotdeauna 1 sau 2 membri ai personalului care încearcă să facă mai lent dicționarul posibil,
asa ca asta e intotdeauna distractiv sa se uite la.
>> De utilizare pentru PSET este aveți o pronuntie cu un dicționar opțional
și apoi un fișier text obligatoriu.
În mod implicit, atunci când rulați abecedar, cu doar un fișier text și nu specificați un dicționar,
se va folosi fișierul text dicționarul, una mare
în dosarul cs50/pset5/dictionaries.
Pe care o are peste 100.000 de cuvinte.
Ei au, de asemenea, un mic dictionar care are cuvinte considerabil mai puține
că CS50-a făcut pentru tine.
Cu toate acestea, puteți foarte ușor face doar dicționarul ta
dacă doriți doar să fie de lucru în exemple mici -
de exemplu, dacă doriți să utilizați gdb si stii valorile specifice
pe care doriți tabel hash pentru a mapa pentru a.
Deci, tu chiar pot face fișierul text propriul doar cu bar, BAZ, FOO, și foobar,
face că într-un fișier text, fiecare separa pe cei cu 1 linie,
și să facă apoi fișierul text propriu, care conține numai literalmente poate 1 sau 2 cuvinte
astfel încât să știți exact ce ar trebui să fie de ieșire.
Unele dintre fișierele de text eșantion care Consiliul de mare atunci când executați provocare va verifica
sunt Război și pace și o Jane Austen roman sau ceva de genul asta.
Deci, atunci când sunteți la început, e mult mai usor sa-ti faci propriile fișiere de text
care conțin doar câteva cuvinte sau poate 10
astfel încât să puteți anticipa ce rezultatul ar trebui să fie
și apoi verificați-l împotriva acestei, deci mai mult de un exemplu controlat.
Și așa, deoarece avem de a face cu prezicerea și desen lucruri în jurul valorii de,
din nou, vreau să vă încurajez să utilizați stilou și hârtie
pentru că se întâmplă cu adevărat să te ajute cu asta -
desen săgețile, cum tabel hash sau cum va arata trie,
atunci când sunteți eliberarea ceva în cazul în care săgețile merg,
te descurci pe suficient, nu vezi orice link-uri dispariție
și care se încadrează în abisul memoriei scurs.
Asa ca te rog, vă rugăm să încercați pentru a trage lucruri, chiar înainte de a ajunge la scrierea de cod în jos.
Egal lucrurile în așa fel încât să înțelegeți modul în care lucrurile sunt de gând să lucreze
pentru că atunci îți garantez că vei rula în muddles indicatorului mai puțin acolo.
>> Bine.
Vreau să vă urez cele mai bune foarte mult noroc cu acest PSET.
Este, probabil, cel mai dificil.
Deci, încercați să înceapă devreme, trage lucruri, trage lucruri, și mult noroc.
Acest lucru a fost Walkthrough 5.
>> [CS50.TV]