[FILMAS RULIS]
[MŪZIKA ATSKAŅOTĀS]
DEIVIDS MALANS: Labi, šis ir CS50.
Un šī jau ir 3. nedēļa, kurā mēs atskatīsimies faktiski uz 0. nedēļu,
kurā mēs pirmo reizi sākām.
Un 0. nedēļā atcerieties, ka savā ziņā viss bija ļoti intuitīvi.
Mēs runājām ne tikai par informācijas attēlojumu, bet arī par
algoritmiem.
Un mēs atkal un atkal runājām par tālruņu grāmatas saplēšanu.
Un tas mums kaut kā noveda pie labāka risinājuma.
Bet šodien mēs mēģināsim sākt formalizēt dažas no šīm idejām un tvert
dažas no tām pašām idejām vēl nevis pseidokodā, bet arī faktiskā
kodā.
Bet mēs arī apsvērsim šo algoritmu efektivitāti, piemēram, cik labi
un cik labi izstrādāti patiesībā ir mūsu algoritmi.
Un, ja atceraties, kad mēs veidojām tālruņu kataloga piemēru, kur man
vispirms bija algoritms, kas meklēja pa vienai lapai, pēc tam otrreiz
pa divām lappusēm, un pēc tam, treškārt, sāku pārraut lietu uz pusēm,
atcerieties, ka mēs, ar rokas mājienu, to analizēja šādi.
Mēs ierosinājām, ja x ass šeit ir problēmas lielums, piemēram,
lappušu skaits tālruņu grāmatā, un y ass ir laiks, kas nepieciešams
problēmas atrisināšanai sekundēs, minūtēs, lapas plīsumos neatkarīgi
no jūsu vienības. mērs ir, atcerieties, ka pirmais algoritms, kas ir
taisna līnija, piemēram, ja jums būtu n lapas tālruņu grāmatā, tas
varētu būt šāds slīpums n — un pastāv šī viena pret vienu saistība
starp lapām un asarām.
Divas lappuses vienlaikus, protams, bija divreiz ātrāks, bet joprojām
ir tāda pati forma, dzeltenā līnija šeit norāda, ka jā, tas ir n virs
2, varbūt plus 1, ja jums ir jāpalielina atpakaļ, kā mēs apspriedām.
Bet patiesībā tas joprojām ir viens un tas pats algoritms vienā vai
divās lapās vienlaikus.
Bet trešais algoritms, atcerieties, bija šis šeit zaļā krāsā, kur mēs
to saucām par logaritmisko attiecībā uz to, cik ātri vai cik lēni tas
bija.
Un patiešām, šī algoritma rezultāts bija tāds, ka mēs varētu pat
dubultot tālruņu kataloga izmēru, un tas nav nekas liels — viens
papildu lapas plīsums, un mēs no tālruņu kataloga izņemam vēl 1000
lappuses.
Tāpēc šodien mēs pārskatīsim dažas no šīm idejām, nedaudz
formalizēsim tās, bet galu galā arī pārtulkosim dažas no tām, lai
kodētu.
Un tas viss tagad ir iespējams, jo mums, iespējams, ir zemāka līmeņa
izpratne par to, kas patiesībā atrodas jūsu datorā.
Tā, protams, ir jūsu datora RAM vai atmiņa.
Un atcerieties, ka, ja mēs sākam to abstrahēt, jūsu datora atmiņa
patiešām ir tikai baitu režģis.
Patiesībā mums vairs nav jāskatās uz aparatūru.
Un mēs apskatījām šādu baitu režģi, kurā katrs no šiem baitiem var
tikt izmantots, lai saglabātu char, int, garu vai pat veselu virkni.
Bet koncentrēsimies varbūt tikai uz šī apakškopu, jo pagājušajā
nedēļā mēs, protams, uzsvērām masīvus, lietu glabāšanu masīvos.
Un tas ļāva mums sākt saglabāt veselas virknes, rakstzīmju secības un
pat veselu skaitļu masīvus, ja vēlējāmies, lai būtu vairāki, nevis
tikai vairāki mainīgie.
Bet galvenais ir tas, ka, ieskatoties masīvā datora atmiņā — un,
piemēram, pieņemsim, ka šie veselie skaitļi šeit ir saglabāti —,
mums, cilvēkiem, ir diezgan viegli uzlūkot to un uzreiz atrast
skaitli 50.
Jums ir šāds skats no putna lidojuma, no kurienes jūs sēžat uz visu
ekrānā redzamo.
Un tāpēc ir diezgan skaidrs, kā jūs nonākat pie skaitļa 50.
Bet datoru pasaulē, protams, izrādās, ka tā ir aparatūra.
Un datori mūsdienu vajadzībām vienlaikus var veikt tikai vienu lietu.
Viņi nevar vienkārši uztvert visu un uzreiz atrast kādu skaitli,
piemēram, 50.
Tāpēc, iespējams, piemērota metafora ir uzskatīt, ka datora atmiņas
masīvs patiešām ir slēgtu durvju secība.
Un, ja dators vēlas atrast kādu vērtību masīvā, tam ir jādara
digitālais ekvivalents, atverot visas šīs durvis pa vienai.
Tagad kā kods to var izdarīt?
Protams, pagājušajā nedēļā mēs ieviesām indeksus vai indeksus,
saskaņā ar kuriem mēs parasti saucam masīva pirmo elementu atrašanās
vietu 0, otro atrašanās vietu 1, trešo vietu 2 un tā tālāk - tā
saukto 0 indeksētu.
Un tas ļāva mums tagad savienot šo atmiņā notiekošo konceptuālo
pasauli ar faktisko kodu, jo tagad mums bija šī kvadrātiekavas
sintakse, ar kuras palīdzību mēs varētu meklēt kaut ko, ja tā
vēlamies.
Un izrādās, ja es tagad krāsošu šīs sarkanās, nevis dzeltenās, šķiet,
ka mums šeit ir diezgan laba fiziskā metafora, kas ir paredzēta
datora atmiņas masīvam, ja, piemēram, jūs glabājat kādu septiņi šādi
skaitļi.
Un tāpēc šodien mēs sākam ar noteikta veida algoritma izskatu.
Tas ir meklēšanai.
Meklēšana notiek visur.
Mēs visi, iespējams, jau vairākas reizes dienā esam apmeklējuši
vietni google.com vai kādu līdzvērtīgu vietni.
Tādi uzņēmumi kā Google patiešām spēj ātri saņemt atbildes.
Tātad, kā viņi to dara?
Kā viņi uzglabā informāciju datoru atmiņā?
Nu, padomāsim, kas tas īsti ir.
Tā patiešām ir tikai problēma, kāda tā bija 0. nedēļā.
Tomēr problēmas ievade pašlaik varētu būt septiņu skapīšu masīvs.
Tā ir problēmas ievade, kuras iekšpusē ir skaitlis.
Un varbūt vienkāršības labad mēs vēlamies tikai jā/nē,
patiesu/nepatiesu atbildi — tas ir, jēga — par to, vai šajā masīvā ir
vai nav kāds skaitlis, piemēram, 50.
Tas nav tik izdomāts kā Google.
Tas ne tikai saka, ka jā, mums ir meklēšanas rezultāti.
Tas faktiski sniedz jums meklēšanas rezultātus.
Bet tagad mēs saglabāsim to vienkāršu un tikai izvadīsim kā daļu no
šīs problēmas, jā vai nē, patiess vai nepatiess, mēs esam atraduši
meklēto numuru, ņemot vērā tādu ievadi kā šis masīvs.
Bet izrādās, ka šīs melnās kastes iekšpusē, pie kuras mēs pastāvīgi
atgriežamies, ir dažādi iespējamie algoritmi.
Un mēs par to augstā līmenī konceptuāli runājām 0. nedēļā ar tālruņu
katalogu.
Bet šodien aplūkosim to nedaudz konkrētāk, izmantojot spēli, ar kuru
daži no jums varētu būt uzauguši, proti, Monopols.
Un tā aiz šīm durvīm, izrādās, slēpsies kaut kādas monopola naudas
nominālvērtības.
Bet šim nolūkam mums tagad ir divi brīvprātīgie.
Ja vēlaties apsveikt pasauli?
DŽEKSONS: Sveiki, es esmu Džeksons.
STEFĀNIJA: Sveiki, mani sauc Stefānija.
DEIVIDS MALANS: Un vai vēlaties kaut ko pastāstīt par sevi — gadiem,
māju, kopmītni?
STEFĀNIJA: Es pirmo gadu dzīvoju Metjūsā.
DEIVIDS MALANS: Jauki.
DŽEKSONS: Un es pirmo gadu esmu Kanādā.
DEIVIDS MALANS: Jauki.
Labi, laipni lūdzam mūsu abos brīvprātīgajos.
Tātad, kāpēc mēs to nedarītu?
Vai kāds no jums vēlētos brīvprātīgi pieteikt otru, lai dotos pirmais?
STEFĀNIJA: Es iešu.
DEIVIDS MALANS: Labi.
Labi, Stefānija ir augšā pirmā.
Un aiz vienām no šīm durvīm mēs esam paslēpuši monopola naudu 50.
Un tāpēc mēs vēlamies, lai jūs atrastu 50.
Mēs jums neko vairāk nestāstīsim par skapīšiem.
Bet mēs vēlamies, lai jūs izpildītu noteiktu algoritmu.
Un patiesībā es jums iedošu pseidokodu šim nolūkam.
Un es jums došu tam nosaukumu.
To sauc par lineāro meklēšanu.
Un, kā norāda nosaukums, jūs diezgan daudz beigsit staigāt pa taisnu
līniju.
Bet kā tu to darīsi?
Ļaujiet man ierosināt, ka pēc brīža jūsu pirmais solis būs domāt kā
cilpa.
Ko mēs vēlamies, lai jūs darītu katrā iterācijā katrā durvīm no
kreisās uz labo pusi?
Nu, ja aiz šīm durvīm ir 50, tad mēs vēlamies iet uz priekšu, lai jūs
atgrieztos patiesi.
Un, ja vēlaties, lepni paceliet 50 grupas labā.
Pretējā gadījumā, ja jūs izietat visu šo cilpu un neesat atradis
skaitli 50, jūs varat vienkārši sarūgtināt ar rokām.
Nepatiesi — jūs neesat atradis skaitli 50.
Tātad, lai būtu skaidrs, pirmais solis būs katrām durvīm no kreisās
uz labo pusi.
Kā jūs vēlētos sākt?
Jā.
Ak, un tad - jā.
Tur mēs ejam.
Jā.
Un, ja vēlaties vismaz pateikt, labi, labi aktierspēli šeit.
Ko jūs tā vietā atradāt?
STEFĀNIJA: Nav 50, bet 20.
DEIVIDS MALANS: Ak, labi.
Tātad pirmais solis bija neveiksmīgs.
Tātad, pāriesim uz otro soli.
Ko jūs plānojat darīt tālāk šajā cilpā?
STEFĀNIJA: Es pārvācos uz blakus durvīm.
DEIVIDS MALANS: Labi.
STEFĀNIJA: Gandrīz.
DEIVIDS MALANS: Labi, gandrīz.
Sava veida.
Tā vietā 500.
Nākamais skapītis?
STEFĀNIJA: Es labprātāk ņemtu to.
Nē.
DEIVIDS MALANS: Labi, mēs nerunājam auditorijai?
STEFĀNIJA: Tas bija 10.
DEIVIDS MALANS: Labi, tā turpini.
Šis tagad ir trešais solis.
STEFĀNIJA: Ak, cilvēk.
DEIVIDS MALANS: Pieci, labi.
Pārbaudāmi vēl daži skapīši.
STEFĀNIJA: Mazliet skumji, puiši.
DEIVIDS MALANS: Labi, no otras puses līdz pēdējam.
STEFĀNIJA: Ir 1.
Kaut kā tuvu.
DEIVIDS MALANS: Labi.
Un visbeidzot pēdējais solis.
Ir skaidrs, ka jūs, iespējams, esat šeit iekārtojies.
STEFĀNIJA: Ejam!
DEIVIDS MALANS: Labi, tātad skaitlis 50.
Un Stefānija, ja drīkst, ļaujiet man šeit uzdot jums jautājumu.
Tātad ekrānā šis ir tikko izpildītais pseidokods.
Pieņemsim, ka es tomēr esmu izdarījis to, ko daudzi no mums ir
ieraduši darīt, ja jums ir ja stāvoklis.
Jums bieži ir arī cita filiāle.
Pieņemsim, ka es to būtu izdarījis tagad.
Un es to atzīmēju sarkanā krāsā, lai būtu skaidrs, ka tas ir
nepareizi.
Bet kas būtu bijis slikts šajā kodā, izmantojot if un else, vai jūs
varētu teikt?
Vai ir kādi instinkti?
STEFĀNIJA: Tad jūs varētu atcelt kodu, pirms atrodat 50.
DEIVIDS MALANS: Jā, tieši tā.
STEFĀNIJA: Es domāju, ka tu būtu mūžīgi skumja.
DEIVIDS MALANS: Patiešām.
Kad Stefānija bija atvērusi pirmo skapīti, viņa būtu atradusi 20.
20, protams, nav 50.
Viņa būtu lēmusi par nepatiesu.
Bet, protams, viņa nebija pārbaudījusi visus pārējos skapīšus.
Šķiet, ka tā ir galvenā detaļa, kurai, ieviešot pseidokodu, mēs
faktiski izejam cauri — tāpat kā mēs to darījām — un tikai atgriežam
false, pat ne ar citu, bet tieši cilpas beigās. mēs sasniedzam šo
līniju tikai tad, ja neatgriežam patiesību agrāk.
Nu, ejam uz priekšu un darīsim to.
Ļaujiet man paņemt no jums mikrofonu.
Ja vēlaties apsēsties blakus Džeksonam?
Un Džekson, pēc mirkļa mēs liksim tev nākt klāt.
Kārter, ja jūs neiebilstat pārkārtot mūsu skapīšus.
Bet tikmēr ļaujiet man norādīt, kā mēs tagad varētu pārvērst to pašu
ideju kodā.
Diezgan augsts līmenis, diezgan orientēts uz angļu valodu ar šo
pseidokodu — bet patiesībā tagad, kopš pagājušās nedēļas, mums ir
sintakse, ar kuras palīdzību Stefānija un drīzumā Džeksons varētu
uzskatīt šo skapīti, šo skapīšu komplektu, kā patiešām masīvu,
izmantojot iekavas. apzīmējums.
Tātad tagad mēs varam nedaudz pietuvināt mūsu pseidokodu faktiskajam
kodam.
Un veids, piemēram, datorzinātnieks tulkotu diezgan augsta līmeņa
angļu pseidokodu, piemēram, šo, kaut ko, kas ir nedaudz tuvāks C vai
jebkurai valodai, kas atbalsta masīvus, būtu nedaudz slēptāks.
Taču tuvākajās dienās jūs redzēsiet vairāk šīs sintakses.
i no 0 līdz n mīnus 1 — tas joprojām ir pseidokods.
Bet tas ir angļu valodai līdzīgais veids, kā izteikt to, ko mēs zinām
kā for cilpu.
Ja 50 ir aiz durvīm iekavas i, es diskusiju labad pieņemu, ka durvis
tagad ir mana mainīgā, šī septiņu durvju masīva, nosaukums.
Bet tad pārējā loģika, pārējais pseidokods patiešām ir tāds pats.
Un tā jūs ar laiku atklāsiet, ka programmētāji, datorzinātnieki
vispār, kad jūs sākat izteikt idejas, algoritmus kādam citam, tā
vietā, lai varbūt darbotos šajā līmenī šeit, jums tagad ir jauns
vārdu krājums, patiešām jauna sintakse, ko varat esiet nedaudz
precīzāks, neiedziļinoties faktiskā C koda rakstīšanas nezālēs, bet
vismaz tagad darot kaut ko tādu, kas ir nedaudz tuvāk manipulēšanai
ar šādu masīvu.
Tātad Džekson, vai jūs vēlētos piecelties?
Labi.
jā, jā.
Šeit arī atbalsts Džeksonam.
Jauki.
Un tagad es atļaušos jums pieņemt, ka Stefānijai nebija.
Stefānija noteikti darīja visu iespējamo, meklējot no kreisās puses
uz labo, izmantojot lineāro meklēšanu, kā mēs to tagad sauksim.
Bet tie bija diezgan nejaušā secībā, vai ne?
Tur bija 20, tur bija 1 un tad 50.
Tāpēc mēs apzināti sajaucām lietas un nesakārtojām skaitļus viņas
vietā.
Bet Kārters tikko laipni nāca klajā, lai jūs, Džekson, sakārtotu
skaitļus iepriekš.
Un mēs vēlētos, lai jūs šoreiz, līdzīgi kā 0. nedēļā, kaut ko darītu
atkal un atkal, bet šoreiz izmantojot to, ko mēs tagad saucam par
bināro meklēšanu.
Konceptuāli tas ir tieši tāds pats algoritms kā 0. nedēļā.
Bet, ja mēs to tulkojam šī masīva kontekstā, mēs tagad varētu teikt
kaut ko līdzīgu šim.
Pirmais solis Džeksonam varētu būt uzdot jautājumu — ja 50 atrodas
aiz vidējām durvīm, kur, iespējams, viņš ir veicis prāta aprēķinus,
lai noskaidrotu, kas ir vidus, tad viņš vienkārši atgriezīsies
patiesi.
Un cerams, ka mums veiksies un 50 būs uzreiz.
Protams, ir vēl vismaz divas citas iespējas, kura būtu kas?
50 ir attiecībā uz šīm durvīm?
Jā, pa kreisi vai pa labi, alternatīvi.
Tātad, ja 50 ir mazāks par vidējām durvīm, tad, domājams, Džeksons
vēlēsies iet pa kreisi.
Citādi, ja 50 ir lielāks par vidējām durvīm, viņš gribēs iet pa labi,
līdzīgi kā es fiziski to darīju pagājušajā nedēļā ar tālruņu
katalogu, sadalot un iekarojot no kreisās uz labo pusi.
Bet patiesībā ir ceturtais gadījums.
Vispirms uzliksim to uz tāfeles.
Kas vēl šeit varētu notikt, kas Džeksonam būtu jāapsver?
Jā.
Ak, tā tur nav.
Tāpēc ļaujiet man atgriezties un labot savu pseidokodu šeit un
vienkārši pateikt Džeksons: ja mēs jums nedosim durvis vispār, vai
galu galā, kad viņš sadala un iekaro, ja viņam vairs nav durvju, mums
tas ir jārīkojas. situāciju, lai uzvedība būtu definēta.
Labi, tātad ar to teikto: Džekson, vai vēlaties atrast mums numuru 50
un mutiski pastāstīt par to, ko jūs darāt un atrodat?
DŽEKSONS: Labi, tāpēc izskatās, ka šīs ir vidējās durvis.
Tāpēc es to atvēršu.
Bet tas ir 20, nevis 50.
DEIVIDS MALANS: Ak!
Kas tev tagad darās galvā?
DŽEKSONS: Tāpēc tagad es meklēju, jo 50 ir augstāks par 20, es vēlos
skatīties pa labi.
DEIVIDS MALANS: Labi.
DŽEKSONS: Un meklējiet jaunās vidējās durvis, kas būtu šeit.
DEIVIDS MALANS: Jauki.
DŽEKSONS: Un tas ir 100 — slikti.
Bet 50 ir mazāks par 100.
Tāpēc tagad jāskatās pa kreisi, kas būtu šeit.
Un ta-da.
DEIVIDS MALANS: Jauki.
Ļoti labi paveikts arī šoreiz.
Tāpēc paldies, pirmkārt, mūsu brīvprātīgajiem.
Un patiesībā, tā kā jūs esat Monopola cienītājs, kā mēs esam tik
informēti, mums ir Kembridžas Monopola izdevums ar visiem jūsu
Hārvardas izlases veidiem.
DŽEKSONS: Nekādā gadījumā.
DEIVIDS MALANS: Lūk.
STEFĀNIJA: Paldies.
DŽEKSONS: Liels paldies.
DEIVIDS MALANS: Paldies mūsu brīvprātīgajiem, ka viņi atrada mūs 50
gadus vecus.
Tātad - tas bija populārāks, nekā mēs gaidījām.
Tātad, šeit mēs varam to vēl vienu reizi pārvērst par kaut ko mazliet
tuvāku kodam.
Un atkal, joprojām pseidokods — bet šeit, tagad, varētu būt vēl viens
formulējums tieši tam, ko Džeksons tikko izdarīja, vienkārši
izmantojot masīvu nomenklatūru, kur jūs varat būt nedaudz precīzāks
ar saviem norādījumiem un atstāt to kāda cita ziņā. visbeidzot
tulkojiet to kodā.
Bet šeit mums ir tāds pats jautājums sākumā.
Ja durvis nav atstātas, atgrieziet nepatiesu.
Ja 50 ir aiz durvīm, iekavējiet vidējo, tāpēc es šeit pieņemu, jo tas
ir pseidokods, ka kaut kur esmu veicis garīgo vai faktisko
matemātiku, lai noskaidrotu, kas ir vidējā rādītājs.
Piemēram, ja masīvā ir septiņas durvis, tā būtu vieta 0, 1, 2, 3, 4,
5, 6.
Tātad kaut kā esmu paņēmis kopējo durvju skaitu, 7, dalījis ar 2, lai
atrastu vidu.
Tas ir 3 un 1/2.
Mums jātiek galā ar noapaļošanu.
Bet pietiek pateikt, ka vidējā indeksa atrašanai ir labi definēta
formula.
Ņemot vērā kopējo skapīšu skaitu, sadaliet to ar 2 un pēc tam
attiecīgi noapaļojiet.
Tātad, domājams, tas ir tas, ko Džeksons izdarīja, vienkārši skaitot
vai savā galvā, lai atrastu mūs ar 3. durvīm.
Nevis trešās durvis, ceturtās durvis, bet durvju kronšteins 3.
Tātad tas ir tikai sakāms, ja 50 ir aiz durvīm iekavas vidū,
atgriezieties patiesi.
Tas tā nebija.
Tā vietā viņš atrada 20 dolāru banknoti.
Citādi, ja 50 ir mazāks par durvju kronšteinu vidū, turpiniet — un
tagad tas kļūst interesanti — meklējiet durvis no 0 caur durvīm no
vidus mīnus 1.
Tāpēc tagad tas kļūst mazliet vairāk par nezālēm.
Bet, ja vidējais ir 3, šis šeit, ko mēs tagad vēlamies, lai Džeksons
meklētu, ja būtu bijis 50 — ja skaitlis būtu bijis mazāks, mēs
vēlamies sākt ar 0 iekava un turpināt šo.
Un mēs apzināti atņemam 1, jo kāda jēga atkal skatīties tajā pašā
skapī?
Tikpat labi mēs varētu izdarīt no 0 līdz vidum mīnus 1.
Ja 50 ir lielāks par durvju kronšteinu vidējo, kas tas bija, ko mēs
tad darījām?
Tātad Džeksons intuitīvi meklēja durvis vidus plus 1 caur durvīm n
mīnus 1.
Un godīgi sakot, tas kļūst nedaudz kaitinoši, ja šeit ir plusi un
mīnusi.
Bet tikai padomājiet, ko tas nozīmē.
Šīs ir vidējās durvis.
Un pēc tam Džeksons turpināja meklēt caur durvīm, kas ir plus 1, jo
nav jēgas meklēt šo vēlreiz.
Un tad pēdējais elements jebkurā masīvā ar izmēru n, kur n ir tikai
mūsu sākuma skaitlis izmēram, vienmēr būs n mīnus 1.
Tas nebūs n.
Tas būs n mīnus 1, jo mēs vienmēr sākam skaitīt masīvus no 0.
Šeit mums ir šīs tieši tādas pašas idejas tulkojums pseidokodā, kas
ir nedaudz tuvāks C.
Un šeit mēs nonākam pilnā aplī līdz 0. nedēļai.
0. nedēļā bija diezgan intuitīvi iedomāties šādas problēmas
sadalīšanu un pārvarēšanu.
Bet, ja tagad, kad veicat automātisko pabeigšanu un meklējat
sarakstu, pārdomājat savu iPhone, Android tālruni vai tamlīdzīgu
informāciju, iespējams, ja tālrunī nav daudz draugu, ģimenes vai
kolēģu, zini ko?
Lineārā meklēšana, vienkārši pārbaudot katru meklētās personas vārdu,
varētu būt pilnīgi piemērota.
Taču pastāv iespēja, ka jūsu tālrunis būs gudrāks par to, it īpaši,
ja gadu gaitā jūsu kontaktpersonu sarakstā ir vairāki desmiti, simti,
tūkstoši.
Kas būtu labāks par lineāro meklēšanu?
Nu, iespējams, binārā meklēšana.
Bet, bet, bet-- ir pieņēmums, prasība, kas ir kas?
Kāpēc Džeksons, piemēram, Stefānija, varēja atrast 50 tikai trīs
soļos, nevis pilnos septiņos?
Jo masīvs bija sakārtots.
Un tāpēc šī ir sava veida teaser par to, pie kā mums šodien būs
jāatgriežas vēlāk.
Nu, cik daudz pūļu tas prasīja tādam kā Kārters?
Cik daudz pūļu jūsu tālrunim ir nepieciešams, lai iepriekš sakārtotu
visus šos vārdus un numurus?
Jo varbūt patiesībā tas nav tā laika vērts.
Tagad kāds, piemēram, Google, iespējams, kaut kādā veidā kārto
tīmekļa lapu datubāzi.
Varat iedomāties, ka tas ir ļoti lēns, ja vietnē google.com ierakstāt
kaķus vai kaut ko citu, ja viņi lineāri meklēja visā datu kopā.
Ideālā gadījumā viņi dara kaut ko nedaudz gudrāku.
Tāpēc mēs tagad formalizēsim tieši šāda veida analīzi.
Un tas nebūs tik daudz matemātisks, jo tas joprojām būs intuitīvs.
Bet mēs jūs iepazīstināsim ar kādu žargonu, kādu terminoloģiju, ko
vairums programmētāju vai datorzinātnieku varētu izmantot, analizējot
savus algoritmus.
Tagad formalizēsim, kas ir šāda veida analīze.
Tāpēc šobrīd es apgalvoju, ka binārā meklēšana ir labāka nekā lineārā
meklēšana.
Bet cik labāk un kāpēc tieši tā?
Nu, tas viss atgriežas pie šāda veida grafika.
Tātad, atcerieties, šādi mēs analizējām tālruņu katalogu 0. nedēļā.
Un atcerieties, ka mums patiešām bija šīs formulas, aptuvenas
formulas, kas aprakstīja šo trīs algoritmu darbības laiku — pa vienai
lapai, pa divām lappusēm un pēc tam atkal un atkal saplēšot uz pusēm.
Un precīzi, ja jūs saskaitāt lapu skaitu, kurām es pieskāros, vai
lapu skaitu, kurām es saplēstu, ir godīgi teikt, ka pirmais
algoritms, sliktākajā gadījumā, kopā varēja aizņemt n lapas.
Tas nenotika, jo es tajā laikā meklēju Džonu Hārvardu, kas ir
alfabēta sākumā.
Bet, ja es meklētu kādu ar uzvārdu Z, man būtu bijis jāturpina iet un
iet, sliktākajā gadījumā cauri visām n lapām.
Nav tik slikti otrajam algoritmam, un tāpēc mēs darām n dalītu ar 2.
Un pat tie ir mazliet balti meli.
Tas, iespējams, ir n dalīts ar 2 plus 1, ja man nāksies dubultot.
Bet atkal es to daru vispārīgāk, lai aptvertu šo lietu būtību.
Un tad mēs patiešām nokļuvām nezālē ar līdzīgu log base 2 notikumu
šim trešajam un pēdējam algoritmam.
Un tajā laikā mēs apgalvojām, ka ikreiz, kad jūs dalāt kaut ko uz
pusēm, uz pusēm, uz pusēm, pastāv iespēja, ka tiks izmantots kaut
kāds logaritms.
Un mēs to redzēsim šodien.
Bet šodien mēs faktiski sāksim lietot datorzinātņu terminoloģiju.
Un mēs noformēsim šo neprecizitāti, ja vēlaties.
Parasti mums būs vienalga, cik soļus veic kāds algoritms, jo tas
nebūs tik izglītojoši, it īpaši, ja varbūt rīt jums būs ātrāks dators
nekā šodien.
Nebūtu godīgi salīdzināt skaitļus pārāk precīzi.
Mēs patiešām vēlamies ar rokas mājienu tikai iegūt priekšstatu par
to, cik lēns vai ātrs ir algoritms.
Tātad apzīmējums šeit ir apzināts.
Tas burtiski ir lielais O, bieži slīprakstā un tiek dēvēts par lielo
O.
Tātad pirmais algoritms ir lielajā O no n.
Otrais algoritms ir lielajā O no n, kas dalīts ar 2.
Trešais algoritms ir lielajā O no log bāzes 2 no n.
Bet pat tā ir sava veida nevajadzīga detaļa.
Lietojot lielo O apzīmējumu, jums tiešām ir vienalga, redzēsim,
mazākie pasūtījuma nosacījumi.
Mēs nerūpēsimies par dalītu ar 2, jo jūs zināt ko?
Šo algoritmu forma ir gandrīz vienāda.
Un patiešām ideja — pats algoritms būtībā ir tāds pats.
Vienu lapu vietā es daru divas.
Bet, ja jūs man izmetat miljoniem lapu, miljardiem lappušu, šie
algoritmi patiešām darbosies tāpat kā n kļūst ļoti liels, virzās uz
bezgalību.
Un tas pats attiecas uz logaritmiem.
Pat ja esat nedaudz sarūsējis, izrādās, ka neatkarīgi no tā, vai
veicat aprēķinu ar baļķa bāzi 2, baļķu bāzi 3, baļķa pamatni 10,
varat vienkārši reizināt vienu ar otru, lai patiešām iegūtu to pašu
formulu.
Tas nozīmē tikai teikt, ka datorzinātnieks parasti teiktu, ka pirmie
divi algoritmi ir n soļu secībā.
Trešais algoritms ir log n soļu secībā.
Un mums nav īsti vienalga, ko mēs domājam ārpus tā.
Un šis lielais O apzīmējums, kā mēs redzēsim, un patiesībā ļaujiet
man tālināt.
Ja varat iedomāties, ka pēkšņi padarīsit x asi daudz garāku — tātad
vairāk lappušu ekrānā vienlaikus —, patiešām svarīgas būs šo līkņu
formas, jo iztēlojieties, kā tālināt, tālummaināt. tālināt, tālināt,
tālināt, un, tā kā n kļūst daudz, daudz, daudz lielāks uz x ass,
sarkanā un dzeltenā līnija būtībā izskatīsies vienādi, tiklīdz n ir
pietiekami liela.
Bet zaļā līnija nekad neizskatīsies tāpat.
Tā būs principiāli atšķirīga forma.
Un tā ir lielā O intuīcija, lai gūtu priekšstatu par šādiem
veiktspējas rādītājiem.
Tātad šeit ir lielais O.
Šeit, iespējams, ir izplatīta formula, ko datorzinātnieks, noteikti
ievada kontekstā, varētu izmantot, analizējot algoritmus.
Un uz brīdi apsvērsim, kurš no mūsu pirmajiem diviem algoritmiem —
lineārā meklēšana un binārā meklēšana — ietilpst šajās kategorijās.
Tāpēc es tos sakārtoju no lēnākā uz ātrāko, tāpēc secība n kvadrātā.
Mēs to vēl neesam redzējuši, taču tas mēdz būt lēns, jo tas ir
kvadrātisks.
Jūs darāt n reizes n.
Tam ir jāsaskaita daudzas darbības.
Labāk šodien būs n log n.
Vēl labāk būs n.
Pat labāk par to ir log n.
Un vislabākā ir tā sauktā secība 1, piemēram, viens solis vai varbūt
divi soļi, varbūt pat 1000 soļi, bet fiksēts, ierobežots soļu skaits,
kas nekad nemainās neatkarīgi no tā, cik liels ir n.
Tāpēc, ņemot vērā šo diagrammu, lai būtu skaidrs, lineāra meklēšana —
apsvērsim sliktāko gadījumu.
Sliktākajā gadījumā, cik soļu bija jāveic kādam, piemēram,
Stefānijai, lai atrastu problēmas risinājumu, pieņemot, ka ir nevis
septiņas durvis, bet gan n durvis?
Jā?
Tātad pēc n.
Un šajā gadījumā tas ir tieši n.
Bet ziniet ko, iespējams, ka tas ir 2n, jo Stefānijai tas prasīja
pāris soļus.
Viņai vajadzēja pacelt fiksatoru.
Viņai bija jāatver durvis.
Varbūt tas ir trīs soļi.
Viņai bija jāuzrāda nauda.
Tātad tagad ir 3n, 2n.
Bet mums nerūp šis precizitātes līmenis.
Mēs patiešām rūpējamies tikai par fundamentālo operāciju skaitu.
Tāpēc mēs teiksim jā, pēc kārtas n.
Tā varētu būt augšējā robeža, mēs to sauksim par lineāro meklēšanu.
Un kā ar bināro meklēšanu?
Džeksona gadījumā vai vispār es 0. nedēļā, ja ir n durvis, cik soļus
vajadzēja Džeksonam vai man, izmantojot bināro meklēšanu?
Šajā gadījumā tie bija burtiski trīs.
Bet tā nav formula.
Jā, tātad tas ir žurnāla n secībā.
Un patiešām, ja ir septiņas durvis, tas ir gandrīz astoņas, ja jūs
tikai nedaudz noapaļojat.
Patiešām, ja ņemat baļķu bāzi 2 no 8, tas faktiski dod mums 3.
Tātad matemātika faktiski tiek pārbaudīta.
Un, ja jūs neesat apmierināts ar logaritmiem, nekas.
Vienkārši padomājiet par to intuitīvi.
2. bāzes logaritms tikai atkal un atkal kaut ko sadala.
Tātad šajā diagrammā, ja mēs uzskatām lielo O, kas ir skaidrs, tas
ļauj aprakstīt algoritma darbības laika secību — piemēram, tā
lielumu —, bet tas arī apraksta, precīzāk, augšējo robežu.
Tātad, piemēram, sliktākajā gadījumā šie ir diezgan labi rādītāji,
kas parāda, cik labi – vai drīzāk, cik slikti – varētu būt lineārā
meklēšana un binārā meklēšana.
Kāpēc?
Pieņemsim, ka meklējat 1000 lappušu tālruņu grāmatā un personas vārds
sākas ar Z.
Algoritms joprojām būs n soļu secībā.
Kāpēc?
Jo, lai to atrastu, var būt jāveic tikpat daudz kā visas n darbības.
Tagad tas ne vienmēr notiks praksē.
Ja es izmantoju lielo O kā augšējo robežu, būtu jauki, ja būtu
atbilstoša apakšējā robeža, it īpaši, ja vēlaties ņemt vērā ne tikai
sliktākos, bet varbūt arī labākos gadījumus.
Tātad, ko mēs šeit varētu izmantot?
Nu, tas ir lielais Grieķijas omega simbols.
Tātad omega ir simbols, ko datorzinātnieks parasti izmanto, lai
aprakstītu algoritma zemāko robežu, bieži vien labākā gadījuma
kontekstā, lai gan ne obligāti.
Tātad apakšējā robeža nozīmē, cik maz soļu var veikt algoritms?
Un arī šeit tās pašas formulas.
Un mēs laika gaitā aizpildīsim šīs tukšās vietas.
Daži algoritmi vienmēr var veikt vismaz n soļus kvadrātā vai n soļu
secībā.
Dažiem var būt tikai n log n vai n, vai log n, vai 1.
Tātad kaut kas līdzīgs lineārajiem meklējumiem — kad Stefānija sāka
ar lineāro meklēšanu, viņai šoreiz uz skatuves nepaveicās.
Bet kā būtu, ja viņa būtu darījusi, un pirmās durvis, ko viņa atvēra,
būtu 50?
Kā jūs varētu aprakstīt lineārās meklēšanas apakšējo robežu šajā tā
dēvētajā labākajā gadījumā, izmantojot šo iespējamo atbilžu sarakstu?
Jā?
Jā, tātad omega no 1.
Tāpēc labākajā gadījumā apakšējā robeža, cik soļus var veikt lineārai
meklēšanai, lai kaut ko atrastu, varētu būt tikai viens solis.
Kāpēc?
Jo varbūt, ja Stefānijai būtu paveicies un mēs būtu aizpildījuši šos
skapīšus ar numuriem citā secībā, lai viņa varētu būt atvērusi pirmo
skapīti, un var, skaitlis 50 varētu būt tur, tāpēc zemākā robeža,
iespējams, varētu būt omega. no 1 lineārajai meklēšanai.
Un kā tagad ar Džeksonu?
Viņš izmantoja bināro meklēšanu.
Tāpēc viņš ienira problēmas vidū.
Bet kāda būtu zemākā robeža binārajai meklēšanai, izmantojot šo
loģiku?
Jā?
Jā, tātad atkal, omega no 1.
Kāpēc?
Jo varbūt viņam vienkārši paveicas.
Un tiešām, skapīšu vidū varēja būt skaitlis 50.
Tā nebija.
Un tāpēc Džeksona faktiskajā praksē nozīmīgāka būtu bijusi lielā O
diskusija.
Bet lielais O un omega, augšējā un apakšējā robeža ļauj
datorzinātniekam pacīnīties par to, kas varētu notikt sliktākajā
gadījumā, kas var notikt labākajā gadījumā?
Un jūs pat varat iegūt vēl precīzāku, piemēram, vidējo korpusu vai
tamlīdzīgu.
Un tas patiešām ir tas, ko inženieri varētu darīt pie tāfeles
uzņēmumā, universitātē, izstrādājot algoritmu un mēģinot argumentēt,
kāpēc viņu algoritms ir labāks par kādu citu, izmantojot šāda veida
analīzi.
Un, lai jūs to redzētu, izrādās, ka, ja kādam algoritmam ir identiska
augšējā un apakšējā robeža, jūs faktiski varat izmantot arī lielo
grieķu teta.
Un tas ir pēdējais no grieķu simboliem šodien.
Bet grieķu teta norāda uz augšējās un apakšējās robežas sakritību.
Tas ir, tie ir viens un tas pats.
Tas nebija gadījums mūsu diskusijai pirms sekundes par lineāro
meklēšanu, nevis bināro meklēšanu.
Bet jūs varētu izmantot viena veida formulas, ja izrādās, ka jūsu
augšējā un apakšējā robeža ir vienāda.
Piemēram, ja es burtiski saskaitītu visus, kas atrodas šajā telpā —
viens, divi, trīs, četri, pieci, seši un tā tālāk, jūs faktiski
varētu teikt, ka skaitīšana šādā veidā ir n teta, jo labākajā
gadījumā. gadījumā, tas prasīs man n punktus, cilvēkus auditorijā.
Sliktākajā gadījumā tas mani aizvedīs n.
Tas vienmēr prasīs n soļus, ja es vēlos saskaitīt visus istabā.
Jūs nevarat darīt labāk par to, ja vien neizlaižat cilvēkus.
Tas būtu piemērs aprocei kaut kam, kur teta vietā ir ģermāni.
Vai tagad ir kādi jautājumi par lielo O, omega vai teta, kas tagad ir
tikai formālāki rīki rīku komplektā, lai runātu par mūsu algoritmu
dizainu?
Vai ir kādi jautājumi?
Nē?
Neredzot nevienu.
Ak, vai tas ir... jā?
Nē?
Labi, mēs esam labi.
Tātad, iesim uz priekšu un pārtulkosim to, iespējams, par kādu
faktisku kodu.
Ļaujiet man pāriet uz VS Code šeit.
Un paskatīsimies, vai mēs tagad nevaram tulkot dažas no šīm idejām
faktiskā kodā, ne tik daudz izmantojot jaunu sintaksi.
Mēs joprojām darbosimies šajā masīvu pasaulē tāpat kā pagājušajā
nedēļā.
Tāpēc ļaujiet man iet uz priekšu un izveidot programmu ar nosaukumu
search.c, izpildot koda vietu search.c manā terminālī.
Un tad šeit augšā, iesim uz priekšu un iekļaujam mūsu parasto, tāpēc
iekļaujiet cs50.h, lai es varētu saņemt informāciju.
Iekļaujiet standarta io.h, lai es varētu izdrukāt kādu rezultātu.
Mēs izdarīsim int main void, kuras nozīmi mēs sākām ķircināt
pagājušajā nedēļā.
Tas, ka tas šodien atkal ir spēkā neesošs, nozīmē, ka nav
komandrindas argumentu.
Un ļaujiet man iet uz priekšu un darīt to.
Ļaujiet man iet uz priekšu un diskusiju labad paziņot par statisku
masīvu, piemēram, masīvu, kas nekad nemainās.
Un sintakse tam būs dot man masīvu, ko sauc par cipariem, izmantojot
kvadrātiekavās.
Un es tūlīt to inicializēšu uz 20, 500, 10, 5, 100, 1 un 50, kas
atgādina tās pašas nominālvērtības kā iepriekš.
Tātad šī ir nedaudz jauna sintakse, ko mēs, iespējams, neesam
redzējuši.
Un šeit esošās cirtainās lencēs, kas atšķiras no cilpām un cilpām un
funkcijām, vienkārši sakiet kompilatoram, lūdzu, iedodiet man jebkura
izmēra masīvu, kurā ir šie skaitļi no kreisās uz labo pusi.
Es varētu arī izmantot pagājušās nedēļas sintaksi, lai pateiktu kaut
ko līdzīgu šim.
Apskatīsim, 1, 2, 3, 4, 5, 6, 7 nominālvērtības.
Alternatīvi es varētu darīt to.
Un tad es varētu teikt, ka skaitļu iekava 0 ir vienāda ar 20, skaitļu
iekava 1 ir vienāda ar 500.
Un es varētu to darīt vēl piecas reizes.
Tas ir tikai nedaudz garlaicīgi.
Ja jūs zināt skaitļus iepriekš, jums nav jāstāsta sastādītājam, cik
to ir.
Varat vienkārši ļaut tam izdomāt, ka jūsu skaitļi būs 10, 500, 10, 5,
100, 1 un 50.
Tātad, šādi jūs statiski definējat masīvu.
Labi, ļaujiet man vienkārši pajautāt lietotājam numuru.
Mēs to nosauksim par n, izmantojot get_int un pieprasot ievadīt
numuru — tātad nekā jauna.
Un tagad ļaujiet man iet uz priekšu un ieviest lineāro meklēšanu.
Un pseidokodā, kas mums bija šim iepriekš, tika izmantots kāds
masīvam līdzīgs apzīmējums.
Ļaujiet man iet uz priekšu un sākt līdzīgi.
Attiecībā uz int i — un jūs gandrīz vienmēr sākat skaitīt ar i pēc
vienošanās.
Tātad tas, iespējams, ir labs sākumpunkts.
Es to darīšu tik ilgi, kamēr man būs mazāks par 7.
Nav labākais dizains, lai kodētu 7, bet tas ir tikai demonstrācijas
nolūkos, jo es zinu, cik skaitļus es tur ievietoju.
Un tad es dodos uz i++.
Tāpēc tagad man ir cilpas sākums, kas tikai ļaus man atkārtot visu
masīvu.
Un ļaujiet man pajautāt šo.
Ja pašreizējais skaitlis vietā i ir vienāds ar n, kas ir cilvēka
ievadītais skaitlis, tad ejam uz priekšu un darīsim kaut ko
vienkāršu, piemēram, printf, citāts un citāts, atrasts, slīpsvītra n.
Un pēc mūsu diskusijas pagājušajā nedēļā, lai norādītu, ka tas ir
veiksmīgs, es atgriezīšu 0, ja es to atradīšu.
Un, ja es to neatradīšu, es vienkārši došos šeit un pēc noklusējuma
saku, ka nav atrasts, ar slīpsvītru n.
Un tikai konvencijas labad — ak, tikai labam pasākumam katrai
konvencijai es atgriezīšu 1 vai, tiešām, jebkuru vērtību, kas nav 0.
0, atsaukšana, nozīmē panākumus.
Un jebkurš cits vesels skaitlis mēdz nozīmēt sava veida kļūdu,
neatkarīgi no skaitļa, kuru meklēju.
Tātad, lai pārskatītu, vienīgais, kas šeit ir jauns, ir sintakse.
Mēs veidojam septiņu skaitļu masīvu, šos skaitļus.
Un pēc tam mēs šeit patiešām esam izcēluši lineārās meklēšanas
ieviešanu.
Es domāju, ka šī ir C versija, ko Stefānija darīja uz tāfeles,
turpretim tagad masīvu sauc par cipariem, nevis durvīm.
Bet es domāju, ka tas ir gandrīz tas pats.
Ļaujiet man iet uz priekšu, atvērt savu termināļa logu un palaist
veikt meklēšanu.
Šķiet, ka apkopo, ./search.
Un ejam uz priekšu un meklēsim numuru.
Sāksim ar to, ko darījām iepriekš, 50.
Un tas ir atrasts.
Dosimies uz priekšu un palaidīsim to vēlreiz, ./search.
Pameklēsim sākumā varbūt 20.
Tas arī ir atrasts.
Palaidīsim to vēl vienu reizi, meklējot līdzīgus 1000, kas nav starp
nomināliem.
Un tas patiešām nav atrasts.
Tāpēc mēs esam pārņēmuši ideju no 0. nedēļas, kas tagad ir
formalizēta 3. nedēļā, un tagad to pārtulkojām kodā.
Vai jums ir jautājumi par šo lineārās meklēšanas ieviešanu?
Lineārā meklēšana.
Nekas.
Ak, šodien tik veiksmīgi.
Tātad, paskatīsimies, vai mēs nevaram padarīt šo nedaudz
interesantāku un redzēsim, vai mēs nevaram paklupt aiz detaļas, kas
būs svarīgas C.
Un tā vietā, lai veiktu skaitļus, ļaujiet man iet uz priekšu un darīt
to.
Mēs paliksim pie Monopola tēmas.
Un es nokļuvu truša bedrē, lasot Wikipedia rakstu par monopolu.
Un oriģinālie gabali vai žetoni, kas tika piegādāti kopā ar Monopolu,
un izrādās, ka mēs varam attēlot tos ar stīgām.
Tāpēc es izveidošu masīvu, ko sauc par virknēm, daudzskaitlī,
neatkarīgi no šeit norādītā izmēra.
Un pašas pirmās monopola daļas tajā laikā bija kaujas kuģis, ar kuru
varēja spēlēt, zābaks, lielgabals, gludeklis, uzpirkste un cilindrs,
no kuriem daži mūsdienās varētu būt no spēles.
Izrādās, viņi tos ir mainījuši — nebija ne jausmas — gadu gaitā.
Tātad, tagad ir virkņu masīvs.
Ļaujiet man iet uz priekšu un piedāvāt lietotājam tagad, nevis veselu
skaitli.
Es tagad vēlos meklēt kādu no šīm virknēm, joprojām izmantojot
lineāro meklēšanu.
Tāpēc ļaujiet man izveidot virkni s, iestatiet to vienādu ar
get_string, pamudiniet lietotāju meklēt virkni.
Un tad es domāju, ka mans kods šeit ir gandrīz vienāds, izņemot vienu
detaļu.
Tagad man ir masīvs, ko sauc par virknēm.
Man tagad ir mainīgais ar nosaukumu s.
Taču izrādās, ka šo koda rindiņu nedarbosies iemeslu dēļ, kurus
nākamnedēļ izpētīsim sīkāk.
Un izrādās, ka iemesls ir saistīts ar to, ko mēs pagājušajā nedēļā
apspriedām par to, kas īsti ir virkne.
Un kas atkal ir virkne?
Virkne ir masīvs.
Tomēr izrādās, ka vienāds ar vienāds nevarēs dāsni salīdzināt visas
masīvā esošās rakstzīmes tikai tāpēc, ka izmantojat vienlīdzīgus.
Izrādās, ka nesalīdzinās katru burtu.
Par laimi, virkņu bibliotēkā, ko ieviesām pagājušajā nedēļā, ir šīs
problēmas risinājums.
Problēmas iemeslu mēs sīkāk izpētīsim nākamnedēļ.
Bet pagaidām ziniet, ka, ja vēlaties salīdzināt virknes C — it īpaši,
ja esat ienācis klasē, zinot mazliet Java vai Python vai kādu citu
valodu, jūs nevarat izmantot vienlīdzību vienāds.
Pat ja jūs varētu izmantot Scratch, jūs nevarat izmantot C.
Tātad tas, kas man šeit ir jādara, ir šis.
Man ir jāuzdod jautājums, vai funkcijas str salīdzināt vai strcomp
atgriešanas vērtība ir vienāda ar 0, kad tā tiek nodota pašreizējā
virknē, un tā ir lietotāja ievade?
Tātad, ja izlasīsit šīs funkcijas, ko sauc par str salīdzināt,
dokumentāciju, redzēsit, ka tai ir vajadzīgas divas virknes kā
ievade, pirmā un otrā.
Pēc tam kāds pirms vairākiem gadu desmitiem uzrakstīja kodu, kurā,
iespējams, tiek izmantota cilpa for vai cilpa, lai salīdzinātu katru
rakstzīmi katrā no šīm virknēm.
Un izrādās, ka tas atgriež 0, ja tie faktiski ir vienādi.
Izrādās, arī citās situācijās tas atgriezīs pozitīvu skaitli vai
negatīvu skaitli.
Vai ir kāda intuīcija, kāpēc varētu būt noderīgi izmantot funkciju,
kas ļauj pārbaudīt, vai divas virknes ir vienādas?
Ja tie nav vienādi, kas vēl varētu būt interesanti uzzināt,
salīdzinot divas virknes?
Ja noteiktas vērtības ir?
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Labi, iespējams.
Varbūt vēlaties uzzināt, cik viņi ir līdzīgi.
Un tas patiešām ir algoritms pats par sevi.
Bet str salīdzināt ir nedaudz vienkāršāk nekā tas.
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Tieši tā, ja jūs mēģināt sakārtot visu virkņu
sarakstu alfabēta secībā, tāpat kā tālrunis, iespējams, ir paredzēts
jūsu kontaktpersonām vai adrešu grāmatai.
Izrādās, ka str salīdzināt faktiski atgriezīs pozitīvu skaitli vai
negatīvu skaitli vai 0, pamatojoties uz to, vai tas vispirms ir
alfabēta secībā vai vēlāk, vai faktiski vienāds.
Tātad tā var būt noderīga lieta.
Un tas ir tikai teaser zemāka līmeņa skaidrojumam, ko mēs redzēsim
nākamnedēļ.
Tāpēc tagad ļaujiet man šķērsot pirkstus un redzēt, vai es sapratu
pareizi.
Ļaujiet man iet uz priekšu un veikt meklēšanu.
Kompilēja, lai gan lēni.
Meklējiet ar punktu ar slīpsvītru un meklēsim kaut ko līdzīgu
uzpirkstenei.
Un mēs redzam, ka tas patiešām ir atrasts.
Citādi meklēsim kaut ko tādu, kā es zinu, ka tur nav, piemēram,
sacīkšu mašīnu, kas tur bija, kad es uzaugu.
Bet nu, segmentācijas vaina, kodols izmests.
Un patiesībā daži no jums jau iepriekš ir paklupuši šo kļūdu.
Vai kāds vēlas atzīties, ka to redzējis?
Tātad, jā, ne tas, par ko mēs esam runājuši, un, godīgi sakot, ne
tas, ko es tikko gribēju.
Bet arī to redzēsim nākamnedēļ.
Jebkura intuīcija, kāpēc mana programma tikko sabojājās.
Loģiku īsti nemainīju.
Tā joprojām ir lineāra meklēšana.
Ļaujiet man paslēpt termināli, lai jūs varētu redzēt visu kodu uzreiz.
Vienīgais, ko es izdarīju, bija pārslēgšana no veseliem skaitļiem uz
virknēm.
Un es pārgāju uz str salīdzināt šeit.
Bet notika segmentācijas kļūda.
Interesanti, ka tas kaut kā ir saistīts ar datora atmiņu.
Jā.
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Jā, un tas ir smalks, bet precīzs.
Tātad šajā masīvā kopā ir viens, divi, trīs, četri, pieci, seši
elementi, salīdzinot ar septiņiem monopola nominālvērtību skaitļiem,
kas mums bija iepriekš.
Un šī ir vieta, redzi?
Sava veida gadījums, tas atgriezās man iekost.
Fakts, ka es iekodēju šo vērtību, nevis varbūt atdalīju to kā
konstanti vai deklarēju augstāku, kaut kā mani satrauca, jo tagad es
atkārtoju 6. izmēra masīvu.
Bet skaidrs, ka es eju vienu soli par tālu, jo es burtiski atkārtošu
septiņas, nevis sešas reizes.
Tāpēc šķiet, ka es skatos uz atmiņu, kas ir šeit.
Un tiešām, nākamnedēļ mēs koncentrēsimies uz atmiņu.
Un tā ir tikai slikta lieta.
Tātad izredzes ir tādas, ka pat neredzot jūsu šīs pagājušās nedēļas
kodu, ja kādam no jums ir bijušas segmentācijas kļūdas, iespējams,
jūs aizskārāt atmiņu, kurai jums nevajadzētu būt.
Jūs, iespējams, cilpājāt pārāk daudz reižu.
Iespējams, esat izmantojis negatīvu skaitli, lai iekļūtu masīvā.
Kopumā jūs aizskārāt atmiņu, kurai jums nevajadzētu būt.
Un jūs pieskārāties atmiņas segmentam, kam jums nevajadzētu būt.
Tomēr labojums, vismaz manā gadījumā, ir vienkāršs.
Vienkārši nedari tā.
Tāpēc ļaujiet man to pārkompilēt.
Veiciet meklēšanu ar slīpsvītru.
Un es atkal meklēšu sacīkšu automašīnu, Enter.
Un tagad tas nesakrīt.
Bet tas man saka, ka tas nav atrasts.
Tik smalks, bet kaut kas tāds, aiz kura jūs, iespējams, jau esat
paklupis.
Tad jautājumi par to, ko es tikko izdarīju, tīši vai citādi.
Jā, priekšā.
STUDENTS: Viena lieta ir tāda, ka programma joprojām darbojas, ja
atgriežat — ja neatgriežat 0, atgrieziet 1.
darīt [NEdzirdams]?
DEIVIDS MALANS: Tiešām labs jautājums.
Tātad programma joprojām darbosies, pat ja es neatgriezīšu 0 vai 1.
Patiesībā ļaujiet man to darīt un uz sekundi paslēpt savu termināļa
logu.
Atbrīvosimies no atdeves šeit.
Tomēr skatieties, kas šeit notiek.
Ļaujiet man to pārkompilēt, veikt meklēšanu.
Ļaujiet man ritināt manu kodu šeit.
Ļaujiet man turpināt meklēšanu ar slīpsvītru.
Un ļaujiet man iet uz priekšu un meklēt pirmo lietu sarakstā, kaujas
kuģi, tāpēc es zinu, ka tas ir jāatrod.
Nospiedu Enter.
Huh, interesanti.
Tātad teikts, ka atrasts nav atrasts.
Bet vai jūs saprotat, kāpēc, loģiski, šajā gadījumā?
STUDENTS: Vai cilpa joprojām darbojas?
DEIVIDS MALANS: Tieši tā.
Tātad cilpa joprojām darbojas.
Tāpēc šim jautājumam ir daži risinājumi.
Es, piemēram, varētu kaut kā izlauzties no koda šeit.
Bet tas joprojām izraisīs 18. rindas izpildi.
Tā vietā es varētu vienkārši atgriezties šeit.
Man nav noteikti jāatgriež 1 apakšā.
Taču pagājušajā nedēļā es izteicu šo apgalvojumu, ka tas mēdz būt
noderīgi, jo jūsu programmas kļūst arvien sarežģītākas, lai vismaz
norādītu, gluži kā īsts programmētājs, kļūdu kodus, ja kaut kas noiet
greizi.
Tātad 0 atgriešana galvenajā ir vienkāršākais veids, kā norādīt, ka
mans kods ir pabeigts.
Esmu gatavs veiksmīgi iziet, tas arī viss.
Bet šeit es noteikti varētu atgriezt 0, jo tas nav liels darījums.
Tā patiesībā nav kļūda, kas būtu pelnījusi kaitināt lietotāju ar kaut
kādu uznirstošo logu, ka kaut kas nogāja greizi.
Bet atgriešanās 1 ir tikai zemāka līmeņa signalizācijas veids, eh, tā
īsti neatrada to, ko meklēju.
Un atcerieties, ka no pagājušās nedēļas jūs to varat redzēt šādi.
Ja es to vēlreiz kompilēju, tagad, kad esmu atsaucis šīs izmaiņas,
veiciet meklēšanu.
Un, ja es veicu punktveida slīpsvītras meklēšanu un meklēju kaujas
kuģi, kas patiešām ir atrasts, atcerieties, ka es varu izpildīt šo
maģisko komandu, atbalss dolāra zīmes jautājuma zīmi, kuru jūs bieži
neizpildīsit.
Bet tas parāda, kas galvenais atgriezās.
Ja es vēlreiz palaistu meklēšanu un meklēju sacīkšu automašīnu, kas
nav atrasta, es redzu, ka nav atrasta, bet es varu arī palaist šo
komandu vēlreiz un redzēt, ka, ak, tā atgrieza 1.
Tāpēc tagad, ja jūs pārsteidzat dažus mēnešus, dažus gadus, kad
faktiski rakstāt kodu uzņēmumā vai lielākiem projektiem, iespējams,
vēlēsities automatizēt programmatūru.
Jūs, iespējams, nevēlaties, lai cilvēks to obligāti palaistu manuāli.
Jūs varētu vēlēties, lai kods tiktu automatizēts ar kādu nakts
procesu vai kaut ko tamlīdzīgu.
Izmantojot šos izejas kodus, programma var noteikt jā vai nē, ka cits
kods ir izdevies vai neizdevās.
Citi jautājumi par lineāro meklēšanu šādā veidā.
Nē?
Labi, labi, pārtulkosim to par vienu citu C iezīmi, tagad iekļaujot
šīs divas idejas vienā citā programmā.
Tāpēc es izveidošu tālruņu grāmatu programmā C, veicot koda telpas
tālruņu grāmatas punktu C.
Apvienosim dažas no šīm idejām un īstenosim šo ideju par īstā vārda
meklēšanu tālruņu grāmatā un numura atgūšanu.
Tāpēc es iešu uz priekšu un ātri iekļaušu dažas no tām pašām lietām,
cs50.h, lai mēs varētu saņemt ievadi.
standarta io dot h, lai mēs varētu izdrukāt izvadi.
Un es iepriekš iekļaušu string.h gadījumam, ja mums tas ir vajadzīgs.
int main void, šodien nav nepieciešami komandrindas argumenti.
Un tagad ļaujiet man dot sev vārdu masīvu šai tālruņu grāmatai.
Tātad virkņu nosaukumi ir vienādi.
Un tad cirtainajās lencēs, kā būtu, ja Kārters būs viena persona
tālruņu katalogā, bet es pats Deivids – otrs.
Tāpēc mēs to saīsināsim, lai mums nebūtu jāievada pārāk daudz
nosaukumu.
Bet šī ir tālruņu grāmata ar diviem cilvēkiem.
Pieņemsim, ka mēs vēlamies paturēt prātā arī Kārtera tālruņa numuru.
Tātad tas nav tikai teikšana atrasts vai neatrasts.
Tā burtiski meklē mūsu tālruņu numurus kā pareizu tālruņu grāmatu.
Šobrīd īsti nav iespējas to izdarīt.
Es varētu darīt kaut ko dīvainu, piemēram, pēc Kārtera likt skaitli,
piemēram, 617-495-1000.
Es varbūt varētu darīt kaut ko līdzīgu 949-468-2750 pēc manis.
Bet tagad jūs kaut kā darāt visu ābolu un apelsīnu lietu.
Tagad tas nav stīgas.
Tā ir virkne int, string int.
Labi, varbūt es varētu vienkārši izveidot visas šīs virknes.
Bet tagad tā ir tikai konceptuāla ābolu un apelsīnu sajaukšana.
Tāpat kā jā, tas ir četru virkņu masīvs.
Bet tagad jūs izmantojat goda sistēmu, lai zinātu, ka pirmā virkne ir
vārds, otrā virkne ir skaitlis, trešā virkne ir — jūs varat to
izdarīt.
Bet tas ir mazliet kapāt, ja tā var teikt.
Tātad, kas varētu būt tīrāks par šo?
Tā vietā, lai apvienotu savus tālruņu numurus vienā masīvā ar mūsu
vārdiem, ko vēl mēs varētu darīt, kas, iespējams, ir nedaudz labāks?
Sakiet to nedaudz skaļāk.
2D masīvs, iespējams, kaut kas, ko mēs varētu darīt.
Es tagad padarīšu to vēl vienkāršāku, jo mēs tos neesam izmantojuši
pēc nosaukuma, lai gan tas ir, mēs redzējām pagājušajā nedēļā,
tehniski, kas ir argv.
Ko vēl es varu darīt, ja vēlos saglabāt vārdus un numurus?
Jā.
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Jā, ļaujiet man iet ar šo ieteikumu.
Tas ir nedaudz vienkāršāk.
Tā vietā, lai sarežģītu lietas burtiski dažādās dimensijās, ļaujiet
man iet uz priekšu un veikt virkni.
Nu, es varētu darīt int skaitļus.
Bet zini ko?
Lai mēs varētu atbalstīt pieturzīmes, piemēram, domuzīmes vai pat
iekavas vai valstu kodus, es to darīšu.
Es izveidošu virknes skaitļus, lai varētu attēlot Kārtera numuru kā
citātu un 1 ASV, 617-495-1000, komplektā ar defisēm, kā tas ir ASV
pieņemts.
Un tad es iešu uz priekšu un rakstīšu +1-949-468-2750 semikolu.
Un tagad, zemāk, ļausim lietotājam meklēt šajā tālruņu katalogā,
tāpat kā 0. nedēļā.
Virknes nosaukums ir vienāds ar iegūt virkni.
Un pajautāsim lietotājam vārdu, iespējams, Deivids vai Kārters vai
kāds cits.
Un tagad no jauna ieviesīsim lineāro meklēšanu.
Tātad 4, es saņemu 0.
es esmu mazāks par 2 Un dari, kā es saku, nevis kā es daru.
Es domāju, ka mums vajadzētu piesargāties no šīs stingrās kodēšanas,
taču pagaidām mēs to padarīsim vienkārši.
i++.
Un tad šajā for cilpā es domāju, ka mums ir visas sastāvdaļas, lai to
atrisinātu.
Tātad, ja str atgriešanās vērtību salīdzina visu vārdu iekavas i,
salīdzinot ar vārdu, ko ievadījis cilvēks, ja tas viss ir vienāds ar
0, tas ir, visas rakstzīmes šajās divās virknēs ir vienādas, tad es
domāju mēs varam iet uz priekšu un teikt, ka atrasts, tāpat kā
pagājušajā reizē.
Bet zini ko?
Izdrukāsim Kārtera vai manu tālruņa numuru.
Tātad tika atrasti procenti s, un mēs pievienosim skaitļus, iekava i.
Un konsekvences labad es atgriezīšu šeit 0.
Un, lai būtu skaidrs, es pateikšu kaut ko līdzīgu, piemēram, printf
not found.
Un tad es atgriezīšu arī 1.
Atgādinot, šeit ir viss kods.
Tas ir gandrīz tāds pats kā iepriekš, tikai tagad tas ir noderīgi.
Es nesaku tikai atrasts vai neatrasts.
Es atradu numuru monopolā, vai es atradu gabalu monopolā.
Es meklēju vienā masīvā, vienā no virknēm.
Un tad es drukāju no otra masīva, atbildi.
Ļaujiet man iet uz priekšu un palaist kompilatoru, izveidot tālruņu
katalogu, Enter.
Labi, tas ir daudzsološi, bez kļūdām.
Punktu slīpsvītra tālruņu grāmata tagad.
Un meklēsim, piemēram, Kārters Enter.
Labi, mēs atradām Kārtera numuru.
Labi, ļaujiet man to izdarīt vēlreiz.
Tālruņu grāmata, meklēsim Deividu.
Labi, šķiet, esam atraduši Deivida numuru.
Labi, darīsim to pēdējo reizi.
Tālruņu grāmata, ievadiet.
Un tagad mēs meklēsim Džonu Hārvardu.
Ievadiet, nav atrasts.
Labi, tāpēc es uzdrošinos teikt, lai arī ar minimālu testēšanu, šis
kods ir pareizs.
Vai kāds tagad vēlētos kritizēt dizainu?
Vai kaut kas jūs, iespējams, neapmierina šo pieeju?
Un kā vienmēr, padomājiet par to, kā, ja programma kļūst garāka,
sarežģītāka, kā varētu izvērsties šādi lēmumi.
Jā.
STUDENTS: Ja i ir mazāks par 2.
DAVID MALAN: Labi, ja i ir mazāks par 2, tātad tehniski, ja es
mainīšu cilvēku skaitu šajā tālruņu grāmatā, man būs jāatjaunina i.
Un mēs jau esam redzējuši, ka es sevi ievedu nepatikšanās.
Tātad tas ir slikts dizains.
Labi.
STUDENTS: Pieņemsim, ka tālruņu grāmatai pievienojat kādas personas
vārdu, bet jums nav atbilstošā numura.
tas [dzirdams] kāda cilvēka numurs.
DEIVIDS MALANS: Jā.
Tāpēc es atkal paļaujos uz sevi, lai nesabojātos.
Ja es pievienoju Džonu vai kādu citu pirmajam masīvam, bet aizmirstu
pievienot viņu numuru otrajam masīvam, galu galā lietas mainīsies un
būs nekonsekventas.
Un tad kods tajā brīdī būs nepareizs.
Tātad slikts dizains, kas mani sagatavo nākotnes neveiksmēm, ja
vēlaties.
Citas domas?
Jā.
STUDENTS: [NEdzirdams] tātad, ja jūs būtu
bet ne galvenais [NEdzirdams]
DEIVIDS MALANS: Jā, tiešām labi.
Mēs pieņemam tādu pašu secību.
No kreisās uz labo pusi virzās vārdi, bet no kreisās uz labo - cipari.
Bet tā ir tikai goda sistēma.
Piemēram, kodā burtiski nekas neliedz man mainīt secību kāda iemesla
dēļ vai varbūt kārtot nosaukumus.
Piemēram, tie tagad ir sakārtoti, un varbūt tas ir apzināti, bet
varbūt tā nav.
Tātad arī šī goda sistēma šeit vienkārši nav laba.
Es varētu šeit ievietot komentāru, lai atgādinātu sev, piezīmi sev,
vienmēr atjaunināt masīvus tādā pašā veidā.
Bet kaut kas galu galā notiks, it īpaši, ja mums ir nevis divi, bet
trīs, bet 30 300 vārdi un skaitļi.
Būtu jauki glabāt visus saistītos datus kopā.
Un tāpēc faktiski viena jaunā C funkcija, ko mēs šodien ieviesīsim,
ir tāda, kas faktiski ļauj mums ieviest mūsu pašu datu struktūras.
Masīvus var uzskatīt par ļoti vieglu datu struktūru, jo tā ļauj
grupēt saistītus datus aizmugures pret aizmuguri.
Un šādi tiek īstenotas stīgas.
Tie ir datu struktūra, kas efektīvi ieviesta ar masīvu.
Taču ar C un citām valodām jūs varat izgudrot savus datu tipus
neatkarīgi no tā, vai tie ir viendimensijas, pat divdimensiju vai ne
tikai.
Un ar C, vai varat īpaši izveidot savus tipus, kuriem ir savi
nosaukumi?
Tā, piemēram, vai nebūtu bijis jauki, ja C nāktu ar, nevis tikai char
un int un floats un long un citi.
Vai nebūtu jauki, ja C nāktu ar datu tipu ar nosaukumu persona?
Un ideālā gadījumā cilvēkam būtu vārds un numurs.
Tagad tas ir nedaudz naivi un nereāli.
Piemēram, kāpēc viņi definētu personu, kurai ir tikai šie divi lauki.
Protams, cilvēki varēja nepiekrist tam, kas ir cilvēks.
Tāpēc viņi to atstāj mums.
C autori mums iedeva visus šos primitīvus, ints un pludiņus, stīgas
un tā tālāk.
Bet tagad mūsu ziņā ir tos izmantot interesantākā veidā, lai mēs
varētu izveidot personu mainīgo masīvu, ja vēlaties, masīvā, ko sauc
par cilvēkiem, lai to šeit daudzkārt.
Tātad, kā mēs to darīsim?
Nu, pagaidām tikai noteiksim, ka cilvēkam pasaulē būs vārds un
numurs, par ko mēs varētu visu dienu strīdēties, kam vēl cilvēkam
vajadzētu būt.
Un tas ir labi.
Galu galā jūs varat izdomāt savu cilvēku.
Pašlaik es izmantoju tikai divus mainīgos, lai definētu personas
vārdu un numuru.
Bet vai nebūtu jauki iekapsulēt, tas ir, apvienot šos divus datu
tipus jaunā un uzlabotā datu tipā, ko sauc par personu.
Un sintakse tam būs šāda.
Tātad tas ir mazliet kumoss.
Bet jūs, iespējams, varat secināt, ko daži no tiem šeit dara.
Tātad izrādās, ka C ir atslēgvārds typedef.
Kā norāda nosaukums, tas ļauj jums noteikt savu veidu.
Struktūra ir norāde, ka tā ir struktūra.
Tā ir kā struktūra, kurā ir vairākas vērtības, kuras jūs mēģināt
definēt.
Un tad pašā apakšā, ārpus cirtainajām lencēm, ir tā veida nosaukums,
kuru vēlaties izveidot.
Tāpēc šajā konkrētajā gadījumā jums nav rīcības brīvības izvēlēties
typedef vai struct.
Bet jūs varat nosaukt lietu, kā vien vēlaties.
Un jūs varat ievietot visu, ko vēlaties, kā arī.
Un, tiklīdz koda apakšā tiek izpildīts semikolu, katrai rindai pēc
tam tagad var būt piekļuve personas datu tipam kā vienam mainīgajam
vai kā visam masīvam.
Tātad, ja es vēlos to turpināt, ļaujiet man iet uz priekšu un darīt
to.
Ļaujiet man atgriezties pie sava C koda šeit.
Un es iešu uz priekšu un mainīšu tikai dažas lietas.
Dosimies uz priekšu un darīsim to.
Es iešu uz priekšu un, pirmkārt, atbrīvošos no šiem diviem kodētajiem
masīviem.
Un ļaujiet man iet uz priekšu un mana faila augšdaļā izgudrot šo
tipu, tātad typedef struct.
Tā iekšpusē būs virknes nosaukums un pēc tam virknes numurs.
Un tad struktūras nosaukums būs persona.
Un paraugprakse liek man to definēt faila pašā augšdaļā, lai faktiski
to varētu izmantot jebkura mana funkcija, lai gan šajā gadījumā man
ir tikai galvenā.
Tagad, ja es gribētu, es varētu to izdarīt.
Persona P1 un persona P2.
Bet mēs zinām no pagājušās nedēļas, ka tas jau ir slikts dizains.
Ja vēlaties, lai viena veida mainīgajam būtu vairāki gadījumi, ko tā
vietā vajadzētu izmantot?
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Un... STUDENTS: Masīvs.
DEIVIDS MALANS: Jā, masīvs.
Tāpēc ļaujiet man pat neiet pa šo ceļu.
Tā vietā ļaujiet man to izdarīt.
Persona būs masīva veids.
Bet es to nosaukšu... es to varētu saukt par personām.
Bet angļu valodā mēs parasti sakām cilvēki.
Tāpēc es piezvanīšu masīva cilvēkiem.
Un es vēlos, lai šajā masīvā pastāvētu divi cilvēki, lai gan es
noteikti varētu mainīt šo numuru, lai tas būtu jebko, ko vēlos.
Kā tagad ievietot personas vārdu un pēc tam ievietot numuru tās pašas
personas iekšpusē?
Nu, šodien mazliet jauna sintakse.
Es iešu uz priekšu un pateikšu to.
Personu iekava 0 tikai dod man pirmo personu masīvā.
Tas nav jaunums.
Bet, ja vēlaties iedziļināties šīs personas atmiņā, izmantojiet
punktu.
Un tad jūs vienkārši norādiet tajā esošā atribūta nosaukumu.
Tātad, ja es vēlos iestatīt pirmās personas vārdu Kārters, es
vienkārši izmantoju tā saukto punktu apzīmējumu.
Un tad, ja es vēlos iestatīt Kārtera numuru, izmantojot punktu
apzīmējumu, es darītu šādi: +1-617-495-1000.
Un tad, ja es vēlos darīt to pašu ar sevi, es tagad dotu cilvēkiem,
kas iekava 1 punkts vārds ir vienāds ar citātu un citātu Deividu.
Un tad cilvēki 1. iekavas nekustīga punkta skaitlis ir vienāds ar
citātu +1-949-468-2750.
Un tagad, mana faila apakšā, es domāju, ka mana loģika var palikt
nemainīga.
Es joprojām varu šajā rindiņā pieprasīt lietotājam tās personas
vārdu, kuru viņš vēlas meklēt.
Pagaidām, lai gan es atzīstu, ka tas nav labākais dizains, es to daru
tikai demonstrācijas dēļ, es atstāšu abus tur, jo es zinu, ka man ir
divi cilvēki.
Bet šeit tas būs jāmaina.
Es vairs nevēlos salīdzināt nosaukumus i.
Ko es vēlos šeit ierakstīt kā pirmo argumentu str salīdzināšanai?
Ko es gribu šeit darīt?
Jā.
STUDENTS: Cilvēku vārds.
DEIVIDS MALANS: Tātad cilvēki, kurus es nosaucu, jā.
Tāpēc es vēlos iedziļināties cilvēku masīvā i-tajā vietā, jo tieši to
dara mana cilpa.
Tas atjaunina i atkal un atkal.
Un tad paskaties uz vārdu, un tas ir labi.
Es domāju, ka tagad man arī tas ir jāmaina.
Ko es vēlos izdrukāt, ja persona ir atrasta?
Kāds cits?
Ko es te gribu drukāt, ja atradu personas vārdu?
Jā.
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Sakiet to nedaudz skaļāk.
STUDENTS: Cilvēki, kuriem ir skaitlis.
DEIVIDS MALANS: Lieliski.
Tātad cilvēki iekavās i dot skaitli, ja tiešām es vēlos izdrukāt
atbilstošo numuru šai personai.
Un tad es domāju, ka pārējais mans kods var palikt nemainīgs.
Ļaujiet man turpināt un atkārtoti palaist tālruņu kataloga izveidi,
lai atkārtoti kompilētu šo versiju.
Līdz šim viss ir labi.
Punktu slīpsvītra tālruņu grāmata.
Iesim uz priekšu un ierakstīsim Kārtera vārdu, atrasts.
Labi, ejam uz priekšu un palaidīsim to vēlreiz.
Deivida vārds, atrasts.
Dosimies uz priekšu un izpildīsim to vēl vienu reizi.
Šajā gadījumā ierakstiet, piemēram, John Harvard, nav atrasts.
Tātad būtībā kods nav tik atšķirīgs.
Lineārā meklēšana joprojām darbojas tāpat.
Un es atzīstu, ka tas izskatās neglīts.
Tagad mēs esam izveidojuši divu rindiņu risinājumu ar piecām koda
rindiņām.
Bet, ja mēs pārtīsim nedēļu vai divas, kad sākam saglabāt informāciju
failos, mēs jūs iepazīstināsim ar tādiem failiem kā csv faili,
komatatdalītas vērtības vai izklājlapu faili, kurus noteikti kādā
brīdī esat atvēris savā Mac vai personālajā datorā. pagātnē.
Pietiek ar to, ka mēs drīz apgūsim paņēmienus informācijas, piemēram,
vārdu un numuru, glabāšanai failos.
Un tajā brīdī mēs nedarīsim neko tādu, kas ir kaut kas tāds uzmācīgā
skaitļa 2 kodēšana un manuāli mana un Kārtera vārda un numura
ierakstīšana mūsu programmā.
Mēs dinamiski nolasīsim informāciju no faila.
Un pēc dažām nedēļām mēs to dinamiski nolasīsim no datu bāzes.
Bet pagaidām tas ir tikai sintaktisks veids, kā mēs varam izveidot
2. izmēra masīvu, kurā katrā ir viena persona.
Mēs varam atjaunināt pirmās personas vārdu un numuru, atjaunināt
otrās personas vārdu un numuru, un pēc tam vēlāk meklēt šos vārdus un
izdrukāt atbilstošos numurus.
Un šajā ziņā tas ir labāks dizains.
Kāpēc?
Jo mans personas datu tips tagad ietver visu, ko nozīmē būt personai,
vismaz šajā šaurajā pasaulē.
Un, ja es vēlos kaut ko pievienot, piemēram, jēdzienam par personu,
es varētu iet līdz savam tipam def, un rīt pievienot katram cilvēkam
adresi un sākt to arī lasīt.
Un tagad tā nav goda sistēma.
Tas nav vārdu masīvs, skaitļu masīvs, adrešu masīvs un viss pārējais,
ko jūs varētu iedomāties saistībā ar personu.
Tas viss ir iekapsulēts, kas ir tāda paša veida mākslas termins.
Ja daži no jums ir iepriekš programmējuši, tas atgādina kaut ko, ko
sauc par objektorientētu programmēšanu.
Bet mēs vēl neesam tur.
C nav tas.
Jautājumi par šo struktūras izmantošanu vai šo jauno sintakse, kur
punktu operators šeit patiešām ir sulīgs.
Vai ir kādi jautājumi?
Jā.
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Kurā līnijas numurā?
STUDENTS: 16.
DEIVIDS Malans: 16?
Tātad, jā, tik sintaktiski mēs pagājušajā nedēļā ieviesām
kvadrātiekavas.
Tātad, ja cilvēki iekava 0, tas nozīmē, ka pāriet uz pirmo personu
masīvā.
Tas bija kā tad, kad Stefānija burtiski atvēra šīs durvis.
Tas ir durvju kronšteins 0.
Bet tas, protams, ir 0 iekava.
Šodien punkts ir jauna sintakse.
Tas nozīmē, ka ieejiet šajā cilvēkā atmiņā un paskatieties uz vārdu,
kurā viņi atrodas, un iestatiet to kā Kārters un dariet to pašu ar
numuru.
Tātad tas arī viss.
Tas ir tāpat kā: atveriet skapīša durvis, ieejiet tajās un pārbaudiet
vai iestatiet vārdu un numuru.
Jā.
STUDENTS: Vai varat iestatīt noklusējumu [NESAKAMS]
DEIVIDS MALANS: Ar īpašībām viss ir kārtībā.
Labs jautājums.
Vai struktūrā var iestatīt noklusējuma vērtības?
Īsa atbilde, nē.
Un šeit C kļūst mazāk spējīgs izmantot nekā modernākas valodas,
piemēram, Python un Java un citas, kurās jūs faktiski to varat
izdarīt.
Tātad, pārejot uz Python pēc dažām nedēļām, mēs redzēsim, kā mēs
varam sākt risināt šādas problēmas.
Bet pagaidām jūsu ziņā ir inicializēt vārdu un numuru.
Jā.
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Tiešām labs jautājums.
Kā mēs varam pielāgot vai kritizēt to, ko es daru?
Šī ir viena no retajām situācijām, kad es liekulīgi teiktu, dari, kā
es saku, nevis kā es daru.
Es izmantoju diezgan neglītas līnijas, piemēram, šī, tikai lai
ieviestu sintaksi.
Bet mana šodienas pedagoģiskā prasība ir tāda, ka galu galā, kad mēs
sāksim glabāt vārdus un numurus vai citas lietas failos vai datu
bāzēs, jums nebūs šīs atlaišanas.
Jums būs viena koda rindiņa vai divas koda rindas, kas nolasa
informāciju no faila vai datu bāzes un pēc tam aizpilda visu masīvu
ar šiem datiem.
Pagaidām es to daru tikai manuāli, lai koncentrētos tikai uz jauno
sintaksi, bet tas arī viss.
Tāpēc piedodiet par sliktu dizainu jau šodien.
Citi jautājumi par šo?
Labi, tas jau ir bijis daudz.
Kāpēc gan mums vispirms paņemt 10 minūšu pārtraukumu ar uzkodām.
Vestibilā ir daži apburoši cepumi.
Labi, esam atpakaļ.
Un līdz šim acīmredzami ir labi, ja jūsu dati ir sakārtoti, jo varat
izmantot bināro meklēšanu.
Jūs zināt nedaudz vairāk par datiem.
Bet izrādās, ka šķirošana pati par sevi ir arī problēma, kas
jāatrisina.
Un jūs varētu domāt, labi, ja šķirošana būs diezgan ātra, mums tas
noteikti jādara pirms meklēšanas sākšanas, jo tas tikai paātrinās
visu mūsu meklēšanu.
Bet, ja kārtošana ir lēna, rodas jautājums, vai mums ir jāmācās
kārtot savus datus, ja meklēsim datus tikai vienu, varbūt divas
reizes?
Un tāpēc šeit, iespējams, būs kompromiss.
Tāpēc apskatīsim, ko īsti nozīmē kārtot datus.
Mūsu gadījumā tas būs vienkārši un tiks izmantoti skaitļi.
Bet pasaules Google gadījumā tās var būt faktiskas tīmekļa lapas,
personas vai tamlīdzīgi.
Tātad, šeit ir mūsu tipiskais attēls šķirošanai, jebkuras problēmas
risināšanai.
Ieeja kreisajā pusē un izvade labajā pusē.
Mūsu kārtošanas problēmas ievade būs kāda nešķirota vērtību kopa.
Ideālā gadījumā izvade būs tāda pati sakārtoto vērtību kopa.
Un, ja mēs to darām konkrēti, pieņemsim, ka mēs vēlamies kārtot šo
skaitļu sarakstu, 7, 2, 5, 4, 1, 6, 0, tātad visi skaitļi ir no 0
līdz 7.
Bet tie ir kaut kā nejauši sajaukti.
Tas būs problēmas ievads.
Un tagad mērķis ir tos sakārtot tā, lai jūs patiešām iegūtu 0, 1, 2,
3, 4, 5, 6, 7.
Tātad izrādās, ka ir daudz dažādu veidu, kā mēs faktiski varam kārtot
šādus skaitļus šeit.
Un patiesībā, lai papildinātu mūsu agrāko meklēšanas piemēru, vai
mēs, iespējams, varētu ātri panākt, lai kādi astoņi brīvprātīgie nāk
pie darba, ja jums patīk parādīties internetā?
Ja vēlaties izdarīt 1, 2, 3, 4, 5, 6, 7, 8, kā būtu?
Labi, nāc lejā.
Labi.
Nāciet šurp, un es jums katram iedošu numuru.
Un, ja vēlaties sākt sakārtot sevi tādā pašā secībā, jūs redzat
skaitļus uz tāfeles.
Tāpēc skatieties virs galvas un sakārtojiet sevi no kreisās puses uz
labo tādā pašā secībā.
Un lai ir pirmais no jums — ideāls.
Ja vēlaties nākt tieši šeit, kā būtu tieši saskaņā ar šo?
Labi, un vēl daži cipari.
Labi.
Numurs 2, 6 un ideāls.
Tikai pareizais numurs, labi.
Ak, ak.
Labi, mēs ejam, numur trīs.
Labi.
Tāpēc veiksim ātru pārbaudi.
Mums ir 7, 2, 5, 4, 1, 6, 0, 3, pagaidām ļoti labi.
Vai vēlaties tikai nedaudz pagriezties šādā veidā, lai atbrīvotu
mazliet vairāk vietas?
Labi, un tagad padomāsim, kas mums ir uz skatuves.
Vai vēlaties katrs ātri sasveicināties ar auditoriju?
RAJANS: Sveiki, mani sauc Raiens.
Esmu pirmo gadu no Pennypacker.
ITSELLE: Sveiki, mani sauc Itselle.
Strādāju pirmo gadu.
LŪSIJA: Sveiki, mani sauc Lūsija.
Un es esmu pirmo gadu no Greenough.
ŠILOHS: Sveiki, mani sauc Šilo.
Es esmu pirmo gadu Viglsvortā.
DŽEKS: Sveiki, mani sauc Džeks.
Un es esmu pirmo gadu Štrausā.
KETRINA: Sveiki, mani sauc Katrīna.
Strādāju pirmo gadu.
MAIKLS: Sveiki, mani sauc Maikls.
Es strādāju pirmo gadu Pennypacker.
MUHAMMAD: Sveiki, mani sauc Muhameds.
Es mācos Metjūsā pirmo gadu.
DEIVIDS MALANS: Sveiki, jauki, laipni lūdzam uz klāja.
Labi.
Tāpēc tagad apsvērsim, kā mēs varētu kārtot savus laipnos
brīvprātīgos šeit, lai tos sakārtotu no mazākajiem līdz lielākajiem,
lai, iespējams, mēs varētu izmantot kaut ko gudrāku nekā tikai
lineāro meklēšanu.
Mēs faktiski varam izmantot bināro meklēšanu, pieņemot, ka tie jau ir
sakārtoti.
Tāpēc ļaujiet man ierosināt vispirms apsvērt algoritmu, kuram
faktiski ir nosaukums, ko sauc par atlases kārtošanu.
Un atlases kārtošana būs tāda, kurā burtiski es vai tiešām jūs kā
programmētājs atkal un atkal atlasa mazāko elementu un pēc tam
ievieto tos attiecīgajā vietā.
Tāpēc ļaujiet man iet uz priekšu un sākt to šeit, sākot ar numuru 7.
Šobrīd 7 ir mazākais skaitlis, ko esmu atradis.
Tāpēc es to ņemšu vērā ar garīgo mainīgo, ja vēlaties.
Es tagad iešu tālāk.
Skaitlis 2 acīmredzami ir mazāks, tāpēc es tikai atjaunināšu savu
garīgo atgādinājumu, ka 2 tagad ir mazākais, faktiski aizmirstot par
7. numuru.
5, ne mazāks.
4, ne mazāks.
1, mazāks.
Un es to pieminēšu garīgi.
6, ne mazāks.
0, pat mazāks.
Es to pieminēšu, jo tagad esmu aizmirsis visu pārējo.
Un tagad numurs 3 nav mazāks.
Nu kā tevi atkal sauc?
MIKELS: Maikls.
DEIVIDS MALANS: Tātad Maikls ir 0. numurs.
Viņš, protams, pieder tur lejā.
Bet diemžēl... tu esi... RAJANS: Raiens.
DEIVIDS MALANS: Raiens ir ceļā.
Tātad, kas mums jādara?
Kā mums vajadzētu sākt kārtot šo sarakstu?
Kur jāiet ciparam 0?
Jā.
Vai vēlaties to pateikt skaļāk?
STUDENTS: Es domāju, ka apmainīšu.
DEIVIDS MALANS: Jā, ejam uz priekšu un apmainīsimies.
Tātad, ja vēlaties iet uz priekšu un 0, turpiniet, kur ir 7.
Mums jāatbrīvo vieta 7. numuram.
Tā būtu krāpšanās, ja varbūt visi pieklājīgi pakāptos uz sāniem.
Kāpēc?
Jo, ja mēs iedomājamies visus mūsu brīvprātīgos kā masīvu, piemēram,
tas ir neprātīgs darba apjoms, lai katrs masīva elements pārvietotos
pa kreisi, lai atbrīvotu vietu.
Tāpēc mēs turpināsim to darīt vienkārši un vienkārši izliksim tos,
kas šobrīd atrodas.
Tagad varbūt mums paveicas, un numurs 7 patiesībā ir tuvāk galamērķim.
Varbūt mums nepaveicas, un tas aiziet tālāk.
Bet mēs esam atrisinājuši vismaz vienu problēmu.
Ja mums sākumā bija n problēmas, tagad mums ir n mīnus 1, jo skaitlis
0 patiešām ir īstajā vietā.
Tātad, ja es turpināšu rīkoties šādi, ļaujiet man iet uz priekšu un
pateikt 2, kas pašlaik ir mazākais.
5, nē, 4, nē, 1 šobrīd mazākais.
Es došu prātā.
6, 7, 3, un tagad ļaujiet man pauzēt.
1 acīmredzami tagad ir mazākais elements.
Vai tad man vajadzēja turpināt?
Nu, izrādās, vismaz tā kā esmu definējis atlases kārtošanu, man ir
jāturpina, jo es tikai apgalvoju, ka lietoju vienu mainīgo savā
prātā, lai atcerētos tobrīd mazāko elementu.
Es neesmu tik gudrs kā mēs, cilvēki, lai atcerētos, pagaidiet, 1
noteikti tagad ir mazākais.
Man nav visas šīs atmiņas.
Tāpēc es tikai sekoju līdzi mazākajam.
Tātad numur 1, jūsu vārds bija?
DŽEKS: Džeks.
DEIVIDS MALANS: Džek, kur Džekam jāiet?
Droši vien tur.
Un kā tevi sauc?
ITSELLE: Itselle.
DEIVIDS MALANS: Labi, Džeks un Itselle, ja vēlaties apmainīties
vietām, tagad esam atrisinājuši divas no n kopējām problēmām.
Un tagad mēs to darīsim nedaudz ātrāk.
Ja katrs no jums vēlas sākt apmainīt, kā es atrodu īsto cilvēku, tad
5 mazākie, 4 mazāki, 2 ir mazāki.
Jāturpina pārbaudīt.
Labi, 2 bija mazāki.
Labi, tagad es atgriezīšos sākumā.
Labi, 4 ir mazs.
5 nav.
6 nav.
7 — ak, 3 ir mazs.
Kur tu vēlies doties?
Labi, labi.
Es atgriezīšos šeit.
Un es varu būt nedaudz gudrs.
Man nav jāiet līdz galam, jo es zinu, ka šie cilvēki jau ir sakārtoti.
Tāpēc es varu vismaz nedaudz optimizēt.
Tātad tagad 5 ir mazs.
6 ir mazs.
7 ir 4, 4 ir mazāks.
Ja gribi iet tur vietā.
Un tagad šeit lietas kļūst interesantas.
Es varu optimizēt, vairs neskatoties uz šiem cilvēkiem, jo viņu
problēma acīmredzami ir atrisināta.
Bet tagad 5 ir mazs, 6 nav, 7 nav.
Labi, 5, tu vari palikt tur, kur esi.
Tagad cilvēks istabā acīmredzami jautās, kāpēc es tērēju vairāk laika.
Bet ar atlases kārtošanu, kā es to līdz šim esmu definējis, man
joprojām ir jāpārbauda 6. kontrole, kas ir mazākā, nevis 7.
Un tagad mans pēdējais solis, labi, tie visi ir savās vietās.
Tātad arī šeit ir šī dihotomija starp to, kas mums visiem ir, ir šis
visas problēmas skatījums no putna lidojuma, kur ir skaidrs, kur
ikvienam ir jāiet.
Bet datoram, kas to īsteno ar masīvu, patiešām ir jābūt metodiskākam.
Un patiesībā mēs šeit ietaupām soli.
Ja mēs patiešām to darītu, neviens no šiem skaitļiem nebūtu redzams.
Visi astoņi mūsu brīvprātīgie atrastos aizslēgtu durvju iekšpusē.
Un tikai tad mēs tos varējām redzēt pa vienam.
Bet mēs tagad koncentrējamies tikai uz šķirošanas aspektu.
Tāpēc ļaujiet man tikai, pirms mēs šeit veicam vēl vienu
demonstrāciju, ierosināt, ka tas, ko es patiešām tikko šeit izdarīju
pseidokodā, bija kaut kas līdzīgs šim.
Attiecībā uz i no 0 līdz n mīnus 1, paturot prātā, ka 0 vienmēr ir
masīva kreisā puse.
n mīnus 1 vienmēr ir masīva labais gals.
Ja i no 0 līdz n mīnus 1, es atradu mazāko skaitli starp skaitļu
iekavas i un skaitļu iekavas n mīnus 1.
Un tas ir ļoti gudrs veids, kā izteikt šo optimizāciju.
Es vienmēr sāku no skaitļu iekavas i, lai kur arī atrastos.
Un tad viss pārējais pa labi.
Un tieši tas ļāva man ignorēt jau sakārtotos brīvprātīgos.
Tomēr, ja manā pēdējā rindiņā ir teikts, ka mazāko skaitli apmainiet
ar skaitļiem i, domāju, ka tas īsteno to, ko mūsu cilvēki darīja,
fiziski ejot uz citu vietu.
Labi, tad tas būtu tas, ko mēs sauksim par atlases kārtošanu.
Dosimies uz priekšu un izmantosim otru pieeju, izmantojot algoritmu,
ko es saukšu par burbuļu kārtošanu.
Taču, lai to izdarītu, jums visiem ir jāatjauno sākotnējā atrašanās
vieta.
Ja vēlaties atgriezties šajā pozīcijā, uz tāfeles ir neliela
krāpšanās lapa.
Un ļaujiet man izmantot principiāli atšķirīgu pieeju, jo man īsti
nepatīk atlases kārtošana tāda, kāda tā ir, jo tā ir sava veida liela
staigāšana uz priekšu un atpakaļ.
Un daudzās pastaigas liek domāt par daudz, daudz soļu atkal un atkal.
Tātad, ko es varētu darīt tā vietā?
Burbuļu kārtošana liks man nedaudz intuitīvāk koncentrēties tikai uz
mazākām problēmām.
Un paskatīsimies, vai tas mani aizvedīs kaut kur citur.
Tātad, ja es tikai skatos uz šo sarakstu, neskatoties uz visiem
pārējiem, 7. un 2., tā acīmredzami ir problēma.
Kāpēc?
Jo tu neesi no ierindas.
Tāpēc vispirms atrisināsim vienu nelielu problēmu.
Tātad 7 un 2, kāpēc jūs neapmainīsit?
Es zinu, ka 2 tagad ir labākā vietā, jo viņai noteikti ir mazāk par 7.
Tāpēc es domāju, ka tagad varu turpināt.
7 un 5, problēma.
Tātad atrisināsim to.
7 un 4, problēma.
Atrisināsim to, 7 un 1, atrisināsim to.
7 un 6, atrisināsim to.
7 un 0, atrisiniet to.
7 un 3, atrisiniet to.
Labi, darīts.
Sakārtots, vai ne?
Vai arī, protams, nē, ja paskatās uz šiem skaitļiem šeit.
Bet būtībā mēs esam nedaudz atvairījušies no problēmas.
7 tiešām ir īstajā vietā.
Tātad mums ir maksimāli n mīnus 1 citas problēmas, kas jāatrisina.
Tātad, kā to izdarīt?
Es domāju, ka varu atkārtot to pašu loģiku.
Ļaujiet man iet šeit.
2 un 5, labi.
5 un 4, Nr.
5 un 1, Nr.
5 un 6, jā.
6 un 0, nē.
6 un 3, Nr.
Tātad tagad mēs esam atrisinājuši divas no problēmām.
Un kas ir jauki burbuļu šķirošanā, vismaz pēc šī skatiena tas ir
jauki un vienkārši.
Tas ir jauki un vietēji.
Un jūs tikai pakāpeniski risiniet arvien vairāk problēmu.
Tāpēc turpināsim un darīsim to vēlreiz.
Un es to izdarīšu — mēs to varam izdarīt ātrāk.
2 un 4, mēs zinām, ir labi.
4 un 1, 4 un 5, 5 un 0, 5 un 3, 5 un 6, 6 un 7, labi.
Tātad mēs atgriežamies, 2 un 1.
Ak, tagad vēl viens problēmas risinājums.
2 un 4, 4 un 0, 4 un 3, 4 un 5, 5 un 6, 6 un 7.
Un tāpēc ievērojiet 2 — tā nosaukumā lielākie elementi ir sasnieguši
ceļu uz augšu.
Šķiet, ka tas notiek tieši tad, kad mēs novēršam dažas atlikušās
problēmas.
Tātad gandrīz pabeigts.
1 un 2, 2 un 0, 2 un 3, 3 un 4, 4 un 5, 5 un 6, 6 un 7, gandrīz
gatavs.
Acīmredzot mums, cilvēkiem, tas izskatās paveikts.
Kā es varu droši zināt kā datoru?
Kāds man būtu visdrošākais veids, kā tagad iet, tas nav izdarīts,
atvainojiet.
Tā ir kļūda.
Labi, 1 un 0, 1 un 2, 2 un 3, 3 un 4, 4 un 5, 5 un 6, 6 un 7.
Labi, tagad tas ir acīmredzami sakārtots mums pārējiem uz skatuves.
Kā es varu apstiprināt tik daudz kā kodu?
Jūs to darāt ar prātu, tikai paskatoties uz šo.
Kā dators, kods, droši zinātu, ka šis saraksts tagad ir sakārtots?
Jā.
STUDENTS: vēl vienu reizi [dzirdams].
DEIVIDS MALANS: Darīsim vēl vienu reizi.
Un skaties, kādu secinājumu izdarīt?
STUDENTS: Ka vispār nekas nav jāpārslēdzas.
DEIVIDS MALANS: Jā, darīsim to vēl vienu reizi, lai gan tas ir
nedaudz izšķērdīgi.
Bet loģiski, ja es vēlreiz, vēlreiz un vēlreiz pārlasu visu sarakstu,
salīdzinot pārus, un tajā laikā nedaru nekādu darbu, tagad ir
acīmredzami loģiski droši vienkārši apstāties, jo pretējā gadījumā es
tērēju savu laiku, veicot tas pats atkal un atkal, ja neviens
faktiski nekustas.
Tāpēc es baidos, ka mums visiem nav monopola spēles.
Bet mums ir astoņas stresa bumbas.
Un aplausi, ja mēs varētu, mūsu brīvprātīgajiem.
Ja vēlies savus numurus nolikt tur plauktā.
Tātad, ja mēs to uz brīdi apsveram, paldies.
Liels paldies.
Protams.
Paldies.
Protams.
Tātad, ja mēs tagad ņemam vērā šos divus algoritmus, kurš no tiem ir
labāks?
Vai ir kāda intuīcija par to, vai atlases kārtošana pirmā ir labāka
vai sliktāka nekā otrā?
Kādas domas?
Jā.
jo tas ir mazāk darba [dzirdams]..
DEIVIDS MALANS: Šķiet, ka burbuļu kārtošana ir mazāk darba, jo īpaši
tāpēc, ka es koncentrējos uz šīm lokalizētajām problēmām.
Cita intuīcija?
Atlases kārtošana pret burbuļu kārtošanu.
Ļaujiet man ierosināt, lai mēs mēģinātu to kvantificēt, lai mēs
varētu to kaut kādā veidā analizēt.
Un tas nav uzdevums, ko mēs pastāvīgi veiksim daudziem algoritmiem.
Bet tie ir diezgan reprezentatīvi algoritmiem.
Tātad mēs varam domāt par šo lietu veiktspēju vai dizainu.
Tātad, šeit ir mans pseidokods atlases kārtošanai, un saskaņā ar tā
nosaukumu es tikai iteratīvi atlasu nākamo mazāko elementu atkal un
atkal.
Tātad, kā mēs varam analizēt kaut ko līdzīgu šim?
Mēs to varētu vienkārši izdarīt uz papīra zīmuļa un saskaitīt soļu
skaitu, kas, šķiet, loģiski izriet no koda.
Mēs varētu burtiski saskaitīt soļu skaitu, ko es gāju atkal un atkal,
no kreisās uz labo pusi.
Mēs varētu arī vienkārši saskaitīt salīdzinājumu skaitu, ko es veicu
ar katru no iesaistītajām personām.
Un es to darīju ātri atlases veidā.
Bet katru reizi, kad skatījos uz cilvēku, kurš mēģina izlemt, vai es
vēlos atcerēties, ka skaitlis ir mazākais?
Šis skaitlis, es salīdzināju divas vērtības ar zīmi vienāds ar
vienāds vai mazāks vai lielāks par, vismaz tad, ja mēs to būtu
izdarījuši kodā.
Tātad tā mēdz būt norma.
Analizējot šādus algoritmus, skaitot salīdzinājumu skaitu, jo tā ir
sava veida globāla mērvienība, ko varam izmantot, lai pilnībā
salīdzinātu dažādus algoritmus.
Tāpēc arī padomājiet, ka vispārīgā gadījumā, ja mums ir vairāk nekā
astoņi brīvprātīgie, vairāk nekā septiņas durvis, mēs varam
vispārināt savu masīvu kopumā, jo tas ir pirmais elements 0. iekavā.
Un tā beigas vienmēr ir n mīnus 1.
Tātad masīvi vai durvis, šajā gadījumā vai brīvprātīgie, vienmēr tiek
skaitliski indeksēti no 0 līdz n mīnus 1, ja to kopā ir n.
Tātad, kā mēs analizējam atlases kārtošanas kodu?
Nu, cik soļus man vajadzēja, lai atrastu pirmo mazāko elementu?
Vai precīzāk, cik daudz salīdzinājumu man vajadzēja veikt, kad es
gāju no kreisās uz labo pusi, lai atrastu mūsu pirmo mazāko cilvēku,
kas galu galā bija 0?
Cik daudz salīdzinājumu veicu, ejot no kreisās uz labo pusi?
Ja uz skatuves būtu astoņi cilvēki, cik daudz es salīdzinu?
Piemēram, ja ir astoņi cilvēki, es salīdzināju šos cilvēkus.
Tad šī persona, šī persona, jā.
Jā, kopā septiņi, vai ne?
Jo, ja uz skatuves ir astoņi cilvēki, kopā var veikt tikai septiņus
salīdzinājumus, jo pretējā gadījumā jūs salīdzinātu vienu numuru ar
sevi.
Tātad šķiet, ka vispārīgā gadījumā, ja jums ir n skaitļi, kurus
mēģināt kārtot, vispirms jāsalīdzina mazākais elements — n mīnus 1.
Kopā varbūt n soļi no kreisās uz labo pusi.
Bet salīdzinājumu skaits, kas, manuprāt, ir tikai noderīga
mērvienība, ir n mīnus 1.
Kā būtu ar nākamā mazākā cilvēka atrašanu?
Cik soļu man bija jāveic, lai atrastu nākamo mazāko skaitli, kas galu
galā bija skaitlis 1?
Jā.
STUDENTS: [NESASKAMS] n mīnus 2.
DEIVIDS MALANS: Jā, tātad tikai n mīnus 2.
Kāpēc?
Jo es jau biju atrisinājis vienu problēmu.
Kāds jau bija pareizajā pozīcijā.
Būtu muļķīgi tos skaitīt atkal un atkal.
Tāpēc es varu samazināt savu salīdzinājumu skaitu nākamajai kārtai
līdz n mīnus 2.
Trešā kārta, lai atrastu trešo mazāko skaitli, būtu n mīnus 3.
Un tad punkts, punkts, punkts, iespējams, šis stāsts, šī formula
beidzas, kad jums ir tikai viens pēdējais pāris, cilvēki beigās, ko
salīdzināt.
Tātad, ja tas nedaudz atgādina kaut kādu atkārtošanos no vidusskolas
vai vidusskolas matemātikas, fizikas vai tamlīdzīgi, ļaujiet man
tikai noteikt, ka, ja jūs patiešām veicat šo matemātiku un to
vispārināt, tas ir tas pats, kas n reizes. n mīnus 1 dalīts ar 2.
Un, ja jūs esat sarūsējis par to, nekas liels.
Vienkārši atcerieties, ka ikreiz, kad saskaitīsiet šāda veida
sērijas, kaut ko plus kaut ko nedaudz mazāku un kaut ko nedaudz
mazāku, no kuriem katrs atšķiras ar 1, jūs iegūsit šo formulu.
n reizes n mīnus 1 pār 2Ja mēs, protams, to reizinām, tas tiešām ir n
kvadrātā mīnus n, viss dalīts ar 2.
Ja mēs to turpinām reizināt, tas ir n kvadrātā dalīts ar 2 mīnus n
pār 2.
Un tagad mums ir sava veida vārdu krājums, ar kuru mēs varam runāt
par šī algoritma efektivitāti un dizainu.
Bet godīgi sakot, man ir vienalga par šo precizitātes līmeni,
piemēram, n kvadrātā dalīts ar 2 mīnus n dalīts ar 2.
Kad n kļūst patiešām liels, kurš no šiem simboliem, kurš no šiem
terminiem patiešām dominēs, kļūs par lielāko soļu kopējās vērtības
ietekmētāju?
vai ne?
Tas ir laukums, vai ne?
Tas noteikti nav n dalīts ar 2.
Tā ir kāda brīvlaika skūšanās.
Bet n kvadrātā, kad n kļūst liels, kļūs patiešām liels.
Ja n ir 100, tad n kvadrātā ir lielāks.
Ja n ir miljons, n kvadrātā tiešām ir lielāks.
Un tātad dienas beigās, kad mēs patiesībā runājam tikai par rokas
analīzes vilni un augšējo robežu, ja vēlaties, pieņemsim tikai to, ka
atlases kārtojums, kā šeit analizēts, tas ir n kvadrātu soļu secībā.
.
Tas nav precīzi n kvadrātveida soļi.
Bet zini ko?
n kvadrātā dalīts ar 2, intuīcija šeit varētu būt tāda, labi, tā ir
puse no tā.
n kvadrātā ir tas, kas patiešām ir svarīgs, jo n kļūst ļoti, ļoti
liels.
Un tieši tad jūs sākat domāt un mēģināt atrisināt pasaules Google
problēmas.
Kad n kļūst liels, tad jums ir jābūt gudrākam, nevis vienkārši naivam
jebkura algoritma ieviešanai.
Tātad, kur tad šis algoritms ietilpst šajā kategorijā?
Nu, n kvadrātā, izrādās, ir n kvadrātu soļu secībā, sliktākajā
gadījumā neatkarīgi no tā, vai tas ir sakārtots vai nē.
Tomēr izrādās, ka zemākā robeža, ja ņemam vērā šo pašu kodu,
pieņemsim labāko scenāriju, piemēram, uz skatuves kāpa mūsu astoņi
brīvprātīgie.
Un tikai tāpēc, ka viņi jau ir sakārtojuši sevi, tātad no 0 līdz 7.
Pieņemsim, ka viņi vienkārši bija tādā stāvoklī.
Cik soļus atlases veikals veiktu, lai sakārtotu jau sakārtotu
brīvprātīgo sarakstu?
Kāda intuīcija?
Jā.
STUDENTS: Vai tas joprojām būtu [dzirdams]?
STUDENTS: Joprojām esiet 7 [dzirdams].
DEIVIDS MALANS: Tātad pirmajā piegājienā tas joprojām būtu 7 par
pirmo pāreju pāri cilvēkiem.
Jo, lai gan, jā, es apgalvoju, ka šeit ir 0, es nezinu, ka 0 ir
mazākais, līdz es nokļūstu līdz galam, veicot visus septiņus
salīdzinājumus.
Labi, labi, pirmajā piegājienā bija septiņi vai vairāk vispārīgi n
mīnus 1 soļi.
Ko darīt, ja es meklēju nākamo mazāko elementu un cilvēki šajā stāstā
jau ir sakārtoti no 0 līdz 7?
Nu jā, šeit ir skaitlis 1, un es tos redzu vispirms.
Bet es nezinu, ka viņi ir mazākie, kamēr es nesalīdzinu ar visiem
pārējiem, kas nonāk saraksta beigās.
Un mēs domājam, ak, tas bija muļķīgi.
Man jau tad rokā bija mazākais cilvēks.
Un tāpēc šis pseidokods, šī atlases kārtošanas ieviešana ir fiksēta
šādi.
Nav neviena īpaša gadījuma, kurā teikts, ka, ja tas jau ir sakārtots,
pametiet agri.
Tas vienmēr prasīs n soļus kvadrātā.
Un tāpēc šajā gadījumā, ja mēs aizņemamies savu žargonu no
iepriekšējiem, izmantojot omega apzīmējumu, lai būtu skaidrs, atlases
kārtošana būs arī šajā iemiesojumā omega no n kvadrātā, jo pat
labākajā gadījumā, kur saraksts jau ir šķirots, jūs tērēsit milzīgu
laiku, lai pārbaudītu tikpat daudz vai atklātu tik daudz, lai gan
mēs, cilvēki, to varētu redzēt uzreiz.
Tātad atlases kārtošanai, šķiet, ir jāveic gan n kvadrātveida soļi
sliktākajā gadījumā, gan n soļi kvadrātā labākajā gadījumā.
Un tad zini ko?
Šim nolūkam mēs varam izmantot mūsu teta terminoloģiju.
Šeit būtu algoritms, tāpat kā skaitīšana iepriekš, kas vienmēr aizņem
n soļus kvadrātā neatkarīgi no tā, vai masīvs ir sakārtots vai nav no
sākuma.
Labi, cerams, ka mums izdosies labāk.
Un kāds iepriekš ierosināja šo burbuļu kārtošanu, šķiet, ka tas
izmanto mazāk soļu.
Nu, apsvērsim to tālāk.
Es apgalvoju, ka ar burbuļu šķirošanu mums bija šis pseidokods.
Tāpēc vispirms pievērsīsimies koda iekšpusei.
Šeit lejā, ko es darīju?
i no 0 līdz n mīnus 2.
Tas ir ziņkārīgi.
Mēs nekad iepriekš neesam redzējuši n mīnus 2.
Bet es uzdevu šo jautājumu.
Ja skaitļu iekava i un skaitļu iekava i plus 1 nav kārtībā, nomainiet
tos.
Tas bija tad, kad es norādīju uz mūsu pirmajiem diviem
brīvprātīgajiem.
Es redzēju, ka tie nav kārtībā, tāpēc es tos samainīju.
Kā gan es to daru atkal un atkal līdz n mīnus 2, nevis n mīnus 1, ko
līdz šim vienmēr esam izmantojuši kā savu vistālāko labo robežu?
Vai ir kāda intuīcija, kāpēc es to daru no 0 līdz n mīnus 2?
Jā.
STUDENTS: [NEdzirdams] numurs, jūs
nevar tikt vaļā no itā numura.
Nav neviena labdabīga personāža, ar kuru jūs varētu apmainīties.
DEIVIDS MALANS: Tieši tā.
Tā kā es šeit skatos uz i-to personu šajā pseidokodā un i-to plus 1
personu, es labāk pārliecinos, ka nepārkāpju sava masīva robežas.
Tātad, ja jūs domājat par manu kreiso roku.
Kad es šeit atradu muguru pret tevi, norādot uz pašreizējo cilvēku
pirmajā pozīcijā, mana labā roka šim, ja kondicionieris būtībā rāda
uz blakus esošo cilvēku.
Un jūs vēlaties ar kreiso roku atkārtot visus šos cilvēkus.
Bet jūs nevēlaties, lai jūsu kreisā roka norādītu uz pēdējo personu.
Jūs vēlaties, lai tas norādītu uz otro līdz pēdējo personu.
Bet mēs zinām, ka pēdējā persona vienmēr ir pie n mīnus 1.
Tātad matemātiski no otrā līdz pēdējā persona ir pie n mīnus 2.
Tātad tas ir smalkums.
Bet šī ir seģ vaina, kas gaida savu notikumu.
Ja jūs ieviestu burbuļu kārtošanu, izmantojot n mīnus 1, mana labā
roka izietu ārpus masīva robežām, tāpēc vienkārši slikti.
Labi, kāpēc es to saku n-tās reizes?
Mēs to darījām ļoti organiski ar cilvēkiem.
Bet katru reizi, kad kāds — katrā piegājienā, ko es izdarīju cauri
masīvam, kāds uzburbuļoja līdz galam.
Skaitlis 7, tad numurs 6, tad numurs 5.
Tātad, ja katrā izejā cauri brīvprātīgo grupai es atrisināju vismaz
vienu problēmu, šķiet, ka burbuļu kārtošana var vienkārši palaist
n reizes, lai atrisinātu visas n problēmas, jo pirmajā piegājienā
tiks ievietots vismaz viens skaitlis.
Otrā caurlaide, otrais numurs vietā.
Jums varētu paveicies, un tas darītu vairāk.
Bet sliktākajā gadījumā šķiet, ka ar to pietiek.
Vienkārši dariet to akli n reizes, un viņi visi nostāsies rindā.
Nu, tehniski... labi, tagad mēs ķeramies pie nezālēm.
Tehniski jūs varat to vienkārši atkārtot mīnus 1 reizēs, jo, ja jūs
atrisināsit visas n mīnus 1 citas problēmas, un jums paliek 1,
burtiski šī persona ir tur, kur tai jābūt, tikai loģiski.
Ja esat jau sakārtojis visu pārējo un jums ir palicis tikai 1, tas
jau ir uzpūsts.
Tātad, kā mēs to analizējam?
Burbuļu veidā mēs varētu darīt kaut ko līdzīgu šim.
Es būtībā daru n mīnus 1 lietas n mīnus 1 reizes.
Tagad ļaujiet man atgriezties pie pseidokoda, jo tas ir nedaudz mazāk
acīmredzams.
Šeit jūs faktiski varat matemātiski secināt no savas cilpas, cik
soļus veicat.
Tātad šī pirmā rinda burtiski saka: atkārtojiet nākamo n mīnus 1
reizes.
Tātad mūsu matemātiskā formula ir ļoti vienkārša.
Dariet kaut ko n mīnus 1 reizi.
Šī cilpa, tikai tāpēc, ka es izmantoju cilpas terminoloģiju, ir
ierāmēta nedaudz savādāk.
Bet, ja jūs atkārtojat no 0 līdz n mīnus 2, jūs atkārtojat kopā n
mīnus 1 reizes.
Un atkal aritmētika kļūst mazliet kaitinoša.
Bet tas tikai nozīmē, ka jāveic šādas darbības n mīnus 1 reizes.
Tātad izdariet n mīnus 1 lietas n mīnus 1 reizi.
Tagad mēs varam izpildīt matemātiku šādi.
Mums ir formula n mīnus 1 reiz n mīnus 1.
Šeit mēs izmantojam mazo FOIL metodi, n kvadrātā mīnus 1 reizi n,
mīnus 1 reizi n, plus 1.
Mēs varam apvienot līdzīgus terminus.
n kvadrātā mīnus 2n plus 1.
Bet šajā brīdī, kad n kļūst ļoti liels, par kuru terminu mēs patiešām
rūpējamies?
Tas ir pēc pasūtījuma?
Jā, n kvadrātā.
Tātad vismaz asimptomotiski.
Asimptotiski nozīmē, ka n tuvojoties bezgalībai, kļūst patiešām liels.
Izrādās, ka augšējā robeža atlases kārtošanai un burbuļu kārtošanai
būtībā ir vienāda.
Tagad, ja mēs patiešām izvēlētos un salīdzinātu kopējo salīdzinājumu
skaitu, tie varētu nedaudz atšķirties.
Taču, godīgi sakot, n kļūst liels, jūs tikko pamanīsit atšķirību
starp šiem diviem algoritmiem.
Bet kā ar apakšējo robežu?
Ja burbuļu kārtošanas augšējā robeža ir arī liela O no n, kā ir ar
apakšējo robežu?
Nu, ar šo pseidokodu, kāda būtu burbuļu kārtošanas apakšējā robeža?
Pat labākajā gadījumā, kad visi brīvprātīgie ir sakārtoti.
Kāda intuīcija?
Šajā pseidokodā.
Jā, pa vidu.
STUDENTS: Atvainojiet, ātrs jautājums.
Vai burbuļu kārtošana nav strukturēta tā, lai nebūtu jāsalīdzina
skaitļi, kas jau ir izveidojušies burbuļos?
DEIVIDS MALANS: Labs jautājums.
Vai burbuļu kārtošana nav veidota tā, lai jums nebūtu jāsalīdzina
skaitļi, kas jau ir uzpeldējuši?
Tas ir tas, kas notiek šeit pa vidu, netieši.
Es vienmēr eju no kreisās uz labo pusi.
Bet atcerieties, ka pat tad, kad es beigās sabojāju un pēdējie divi
cilvēki nebija kārtībā, man vienmēr ir nepieciešams restartēt sākumā,
jo lielie skaitļi iet uz šo pusi, bet mazie - uz šo pusi.
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Tātad tā ir taisnība.
Ir dažas nelielas optimizācijas, kuras es šeit nedaudz noklusēju.
Ļaujiet man noteikt, ka tas joprojām būtu n kvadrātā.
Bet tas noteikti samazinātu faktisko darbības laiku.
Bet ko darīt, ja saraksts jau ir sakārtots?
Mūsu pseidokodā pašlaik nav pieļaujama iespēja, ja saraksts jau ir
sakārtots, agri aiziet.
Tāpēc mēs akli darīsim n mīnus 1 lietas un mīnus 1 reizi, ja vien mēs
nepārveidosim savu pseidokodu, kā es to darīju verbāli iepriekš, es
ierosināju šo.
Šīs ārējās cilpas ietvaros, ja jūs veicat piespēli pāri visiem
brīvprātīgajiem un jūsu prāta skaitītājs nav veicis mijmaiņas
darījumus, jums ir jāseko līdzi, izmantojot kādu mainīgo, tad jūs
varētu arī apstāties.
Jo, ja jūs veicat visu piespēli un neveicat mijmaiņas darījumus,
kāpēc jūs tērētu laiku, to darot vēlreiz, gaidot atšķirīgu uzvedību?
Tāpēc, lai palīdzētu tos vizualizēt, tagad burbuļu kārtošana var būt
izdevīga, ja dati jau ir sakārtoti vai lielākoties ir sakārtoti.
Kāpēc?
Jo tajā ir šī īssavienojuma detaļa.
Vismaz, ja mēs to īstenojam šādi, kā mēs varam šīs lietas vizualizēt
mazliet skaidrāk?
Nu, ļaujiet man iet uz priekšu un darīt to.
Ļaujiet man parādīt tieši šo algoritmu vizualizāciju, pateicoties
šeit esošajam trešās puses rīkam, kas mums palīdzēs vizualizēt šos
kārtošanas algoritmus šādi.
Mazie stabiņi apzīmē mazus skaitļus.
Lielas joslas apzīmē lielus skaitļus.
Tagad ideja ir tāda, ka es šeit nospiežu pogu, lai visus mazos
stieņus iegūtu šādā veidā, visus lielos stieņus šādā veidā.
Tātad, tāpat kā mūsu brīvprātīgie.
Bet tā vietā, lai turētu apgaismotus skaitļus, tie ir stabiņi, kas
attēlo to lielumu.
Tātad, turpināsim un sāksim, piemēram, ar atlases kārtošanu.
Un jūs redzēsiet rozā krāsā, tiek izcelts pašreizējais numurs, kas
tiek atlasīts un pēc tam pavilkts līdz galam pa kreisi.
Tātad šis ir atlases veids.
Un atkal tā ir nākamā mazākā elementa atlase.
Bet šeit vēl jo redzamāk var redzēt, ka gluži kā manas cilvēka kājas
mēs speram daudz soļu.
Tāpat arī šis algoritms pieskaras šiem elementiem atkal un atkal un
atkal.
Un tāpēc n kvadrātā tiešām ir lieta.
Šeit ir jābūt kādai raksturīgai atlaišanai.
Piemēram, kāpēc mēs atkal un atkal skatāmies uz tiem pašiem sasodītām
elementiem?
Mēs to darām, ņemot vērā mūsu pseidokodu, tas ir jādara.
Bet tieši šie liekie salīdzinājumi izskaidro, kāpēc n kvadrātā
patiešām ir.
Tātad tagad tas ir izdarīts.
Mazie bāri te, lieli bāri tur.
Un man bija jāturpina runāt, lai nogalinātu laiku, jo tas notiek
salīdzinoši lēni.
Ļaujiet man atkārtoti randomizēt masīvu, lai mēs sāktu ar citu secību.
Un tagad ļaujiet man noklikšķināt uz burbuļu kārtošanas.
Un jūs redzēsit līdzīgu ideju, bet atšķirīgu algoritmu.
Tagad divas rozā joslas ir tās divas, kas tiek salīdzinātas un,
iespējams, labotas, ja tās nav kārtībā.
Un jau tagad var redzēt, ka lielākie bāri mutuļo augšup uz augšu.
Bet tagad jūs varat arī redzēt šo atlaišanu, piemēram, mēs atkal un
atkal lēkājam cauri sarakstam, tāpat kā es turpināju staigāt uz
priekšu un atpakaļ.
Un tas ir n kvadrātā.
Tas nav tik daudz bāru.
ko?
10, 20, tur ir kādi 40 vai kaut kas cits, es domāju.
Tas jau ir diezgan lēns, lai sakārtotu 40 ciparus.
Un es domāju, ka tas kļūs garlaicīgi, ja es turpināšu par to runāt.
Tāpēc pieņemsim, ka arī tas notiek salīdzinoši lēni.
Ja man būtu paveicies un saraksts jau būtu gandrīz sakārtots, burbuļu
kārtošana būtu bijusi diezgan ātra.
Bet tas bija patiesi nejaušs masīvs, tāpēc mums nepaveicās.
Patiešām, vissliktākais varētu būt tas, kas šeit notiek.
Tāpēc es jūtu, ka tas būs pretklimatisks, piemēram, šķaudīšana, ja
neļaušu jums redzēt šīs lietas beigas.
Tā nu lūk.
Nekas interesants drīzumā nenotiks.
Gandrīz pabeigts.
Labi, darīts.
Labi, tāpēc paldies.
[APLAUSI]
Paldies.
Tomēr joprojām ir nedaudz lēns.
Kā gan mēs, iespējams, varam būt nedaudz labāki?
Tāpēc mēs to varam izdarīt, ja ieviešam vēl vienu tehniku.
Un šī ir ne tik daudz koda funkcija, bet gan koncepcija.
Un tas ir kaut kas tāds, ko jūs, iespējams, esat redzējis reālajā
pasaulē, bet varbūt ne tik acīmredzami.
Tātad izrādās, ka programmēšanā rekursija attiecas uz funkcijas spēju
sevi izsaukt.
Matemātikas pasaulē, ja jums ir funkcija f, ja f parādās gan formulas
kreisajā, gan labajā pusē, tā būtu rekursīva funkcija arī matemātikas
pasaulē.
Ikreiz, kad f tiek definēts pats par sevi vai mūsu gadījumā,
aprēķinot, programmējot, jebkurā laikā, kad funkcija izsauc sevi, šī
funkcija tiek uzskatīta par rekursīvu.
Un tas patiesībā ir kaut kas, ko mēs esam redzējuši jau klasē, lai
gan mēs to nesaucām tik daudz.
Tā, piemēram, apsveriet šo agrāko pseidokodu, kur šis bija pseidokods
meklēšanai, izmantojot bināro meklēšanu, veselu virkni durvju.
Ja durvis nav atstātas, tika atgrieztas nepatiesas, tas bija papildu
nosacījums, ko pievienojām.
Bet tad, ja skaitlis aiz vidējām durvīm atgriezās patiess, un šeit ir
interesantā daļa, ja skaitlis ir mazāks par vidējām durvīm, meklējiet
kreiso pusi.
Citādi, ja skaitlis ir lielāks par vidējām durvīm, meklējiet labo
pusi.
Šis pseidokods agrāk pats par sevi bija rekursīvs.
Kāpēc?
Jo šeit ir meklēšanas algoritms.
Bet ko mums stāsta algoritms?
Nu, šajā un šajā rindiņā tas liek mums meklēt kaut ko citu.
Tātad, lai gan kodā tas nav skaidri definēts kā nosaukums, ja tas ir
meklēšanas algoritms un tomēr meklēšanas algoritms izmanto meklēšanas
algoritmu, šis pseidokods ir rekursīvs.
Tagad tas var ātri ievest jūs nepatikšanās, ja funkcija atkal un
atkal un atkal izsauc sevi.
Bet kāpēc intuitīvi nav problemātiski, ka šis kods, šis pseidokods
sevi sauc?
Kāpēc algoritms joprojām apstāsies?
Jā.
ja nav palikušas durvis, [DZUSMAMS]..
DEIVIDS MALANS: Tieši tā.
Tam ir daži izejas nosacījumi, piemēram, ja nav atstātas durvis.
Un vēl svarīgāk, ikreiz, kad meklējat kreiso pusi, jūs meklējat
mazāku problēmas versiju.
Ikreiz, kad meklējat pareizo pusi, jūs meklējat mazāku problēmas
versiju, burtiski uz pusi mazāku.
Tāpēc tālruņu katalogā es acīmredzami nevarēju bezgalīgi daudzas
reizes pārraut tālruņu grāmatu uz pusēm, jo tā burtiski ar katru
reizi kļuva mazāka.
Tātad rekursija ir šī spēja saukt sevi, ja vēlaties.
Bet svarīgi ir tas, ka jūs to darāt ar mazāku, mazāku problēmu, lai
galu galā jums vairs nebūtu risināmu problēmu vai vairs nebūtu datu,
vairs nebūtu durvju.
Tātad šīs divas rindas šeit būtu rekursīvie elementi.
Bet, ja mēs atgrieztos 0 nedēļā, mēs būtu varējuši izmantot rekursiju
citā veidā.
Tātad šis bija mūsu pseidokods tālruņu katalogam 0. nedēļā.
Un atcerieties, ka mēs šīs dzeltenās līnijas aprakstījām kā cilpu,
sava veida ciklu atkal un atkal.
Bet šeit bija palaist garām iespēja.
Kā būtu, ja es būtu atkārtoti ieviesis šo kodu, lai to izdarītu?
Tā vietā, lai teiktu atvērt līdz grāmatas kreisās puses vidum un pēc
tam atgriezties pie 3. rindiņas, piemēram, burtiski izraisīt cilpu,
vai atvērt grāmatas labās puses vidū un atgriezties 3. rindiņā,
ierosinot citu cilpu. Vai atpazīstu, ka tas, uz ko es tagad skatos,
ir algoritms meklēšanai tālruņu grāmatā?
Un, ja vēlaties meklēt mazākā tālruņu katalogā, piemēram, no A līdz M
vai N līdz Z, mēs izmantosim to pašu algoritmu.
Tāpēc es varu šīs dzeltenās līnijas aizstāt tikai ar šo, nejauši
runājot.
Meklēt grāmatas kreisajā pusē, meklēt grāmatas labajā pusē.
Tas būtu netieši, un tagad es varu saīsināt visu, rekursīvu tālruņu
grāmatas pseidokoda ieviešanu no 0. nedēļas.
Un tas ir rekursīvs, jo, ja tas ir meklēšanas algoritms un jūs sakāt,
meklējiet kaut ko citu, tas ir labi.
Tas ir rekursīvi.
Bet, tā kā jūs meklējat pusi tālruņu kataloga, tā patiešām kļūs
mazāka un mazāka.
Pat reālajā pasaulē vai reālajā virtuālajā pasaulē jūs varat redzēt
rekursīvas datu struktūras savvaļā vai vismaz Super Mario Brothers kā
šis.
Ļaujiet man atbrīvoties no visiem traucējošajiem faktoriem un
koncentrēties uz šo piramīdu, kur jums ir viens bloks, tad divi, tad
trīs, tad četri.
Nu, tas pats par sevi ir tehniski rekursīvi definēts tādā nozīmē, ka,
nu, kam paredzēta augstuma piramīda?
Nu, tas tiešām ir, ko?
Kā jūs raksturotu 4. augstuma piramīdu, kas patiesībā ir tas pats,
kas piramīda: STUDENTS: 3. augstums.
DAVID MALAN: --no 3 augstuma, plus 1 papildu slānis.
Nu, kas ir 3. augstuma piramīda?
Nu, tehniski tā ir piramīda ar augstumu 2 plus 1 papildu slānis.
Un tāpēc pat fiziskas struktūras var būt rekursīvas, ja varat tās
definēt pašas par sevi.
Tagad kādā brīdī jums jāsaka, ka, ja piramīdas augstums ir 1, tur ir
tikai viens bloks.
Jūs nevarat mūžīgi teikt, ka tas ir definēts kā augstums negatīvs 1,
negatīvs 2, jūs nekad neapstātos.
Tātad jums ir jābūt īpašam gadījumam.
Bet ejam uz priekšu un tulkosim kaut ko līdzīgu šim, patiesībā, lai
kodētu.
Ļaujiet man atgriezties pie VS koda šeit un ļaujiet man ieviest
programmu, ko sauc par iterāciju, kas attiecas uz cilpas iterāciju.
Un ļaujiet man īstenot šādu ļoti vienkāršu piramīdu.
Tāpēc ļaujiet man iet uz priekšu un iekļaut CS50 bibliotēku.
Šodien iekļaušu mūsu standarta io.h int main void, bez komandrindas
argumentiem.
Un ejam uz priekšu un darīsim to.
Deklarēsim mainīgo, ko sauc par augstumu, pajautāsim cilvēkam šīs
piramīdas augstumu.
Un tad iesim uz priekšu un uzzīmēsim tāda augstuma piramīdu.
Tagad, protams, izdarīt vēl neeksistē.
Tāpēc man vajadzēs izgudrot vilkšanas funkciju.
Ļaujiet man iet uz priekšu un definēt funkciju, kurai nav atgriešanas
vērtības.
Tam būs tikai blakusparādības.
Tas vienkārši drukā ķieģeļus uz ekrāna, ko sauc par zīmēšanu.
Un tā ievade izmanto veselu skaitli n.
Un kā es to īstenošu?
Nu atkal es gribu izdrukāt vienu bloku, tad divus, tad trīs, tad
četrus.
Tas ir diezgan vienkārši, vismaz tad, kad esat apmierināts ar cilpām.
Ļaujiet man atgriezties pie koda šeit.
Ļaujiet man iet uz priekšu un pateikt 4, int i, get 0.
i ir mazāks par n.
es plus plus.
Un tas atkārtosies, būtībā rindu pēc rindas.
Un katrā rindā es gribu izdrukāt vienu, tad divus, tad trīs, tad
četrus ķieģeļus.
Bet es atkārtoju no 0 līdz 1 līdz 2 līdz 3.
Tāpēc es domāju, ka tas ir labi.
Es varu pateikt kaut ko līdzīgu: 4 int j get 0.
j, būsim gudri šajā jautājumā, ir mazāks par i.
j++.
Un tagad ļaujiet man turpināt, un šajā cilpā es domāju, ka varu
iztikt, izdrukājot tikai vienu jaucējzīmi.
Bet tad ārpus šīs cilpas, līdzīgi kā pagājušajā nedēļā, es izdrukāšu
savu jauno rindiņu atsevišķi.
Tātad sākumā tas ir nedaudz acīmredzams.
Bet šī ārējā cilpa atkārtojas rindu pēc rindas, rindu pēc rindiņas,
ja vēlaties.
Un tad iekšējā cilpa tikai nodrošina, ka tad, kad i ir vienāds ar
nulli, redzēsim.
Ak, nē, tur ir kļūda.
Man ir jāpārliecinās, ka j ir mazāks par i plus 1.
Tātad, kad manā pirmajā izvades rindā ir 0, es izdrukāšu vienu
ķieģeli.
Kad man būs 1, es izdrukāšu divus ķieģeļus un tā tālāk.
Tāpēc ļaujiet man iet uz priekšu un veikt atkārtojumu.
Labi, un tagad, šķiet, apkopo.
Ak, ak.
Netieša funkcijas zīmēšanas deklarācija.
Tāpēc es atkal pieļauju pirmajā nedēļā kļūdas.
ko?
Saki vēlreiz.
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Jā.
Trūkst prototipa.
Es to nedeklarēju augšpusē.
Tas ir viegli labojams, un vienīgo reizi ir pareizi un nepieciešams
kopēt ielīmēt.
Ļaujiet man tur nokopēt funkciju deklarāciju un to ar semikolu.
Tā ka zvana tagad zina, ka izloze pastāvēs.
Veiciet iterāciju.
Tagad tas darbojas.
Paldies.
dot slash iterationMēs ierakstīsim kaut ko līdzīgu 4.
Un tā ir mūsu viena, divu, trīs, četru augstuma piramīda, kas
izskatās diezgan līdzīga šai, lai gan izmantojot jaucējzīmes.
Tātad mēs to būtu ieviesuši šādi, piemēram, pirms divām nedēļām
pirmajā nedēļā, varbūt pagājušajā nedēļā, bet tikai izmantojot
masīvus.
Bet ļaujiet man ierosināt, ka tā vietā mēs varētu kaut ko darīt
rekursīvi.
Ļaujiet man aizvērt šo koda versiju.
Un ļaujiet man atgriezties pie VS Code un atvērt recursion.c, lai
kaut ko rekursīvi parādītu.
Un es to darīšu nepareizi apzināti pirmajā reizē.
Tāpēc ļaujiet man iekļaut cs50.h.
Ļaujiet man iekļaut standarta io.h.
Ļaujiet man izdarīt galveno tukšumu.
Un ļaujiet man vienkārši akli uzzīmēt piramīdu, kuras augstums ir 1.
Bet tagad manā zīmēšanas funkcijā ļaujiet man to ieviest mazliet
savādāk.
Tātad mana izlozes funkcija šoreiz joprojām aizņem skaitli n.
Bet tieši tik daudz jaucēju tas tiks izdrukāts.
Tātad izdarīsim 4, un es saņemu 0.
i ir mazāks par n.
i++.
Tad ejam uz priekšu un izdrukāsim vienu jaucējzīmi šeit.
Un tad pēc tam izdrukāsim rindas beigas, tāpat kā iepriekš.
Bet tagad tas, protams, veidos tikai vienu rindu.
Tiks izdrukāta viena vai divas jaucējzīmes vai trīs jaucējzīmes, bet
tikai vienā rindā.
Ļaujiet man tagad, nepareizi, bet ziņkārīgi pateikt: labi.
Nu, ja tas uzzīmē piramīdu ar augstumu 1, izmantosim sevi, lai
uzzīmētu piramīdu ar augstumu n plus 1.
Tāpēc pirmo reizi, kad es piezvanīšu uz izlozi, tiks izdrukāts viens
hash.
Tad otrreiz, kad izsaukšu vilkšanu, tiks izdrukātas divas
jaucējzīmes, pēc tam trīs, tad četras.
Tāpēc mēs liekam šos ķieģeļus no augšas uz leju.
Veiciet rekursiju.
Oi, es atkal sapucējos.
Tātad, kopēsim prototipu šeit.
Noliksim to šeit, semikolu.
Darīsim to vēlreiz.
Veiciet rekursiju.
Labi, labi, punktveida slīpsvītras rekursija.
Un tagad ļaujiet man palielināt savu termināļa logu, lai jūs varētu
redzēt vairāk izvades.
Un šeit mēs esam.
Labi, slikti, bet paldies.
Tātad mums ir bezgala augsta piramīda.
Un tas vienkārši lido pāri ekrānam, tāpēc tas izskatās kā haoss.
Bet es izdrukāju piramīdu ar augstumu 1, tad 2, un tad 3 un tad 4.
Un diemžēl, kā man trūkst jebkāda veida ātrā stāvokļa, jebkāda veida
nosacījuma, kas saka: pagaidi minūti, kad tas ir pārāk garš,
pārtrauciet pavisam.
Tātad šī ir bezgalīga cilpa.
Bet tā nav cilpa.
Tas ir rekursīvs zvans.
Un patiesībā to darīt vispār ir ļoti slikti.
Nākamnedēļ mēs redzēsim, ka, izsaucot funkciju pārāk daudz reižu, jūs
faktiski var izraisīt vēl vienu no šiem segmentācijas traucējumiem,
jo būtībā izmantojat pārāk daudz atmiņas.
Bet pagaidām es to vēl neesmu aktivizējis.
Control C ir jūsu draugs, kuru atcelt.
Turklāt, ja jūs spēlējat kopā mājās vai spēlējat ar šo kodu vēlāk, es
šeit krāpjos.
Mums ir īpaša zvana konfigurācijas funkcija, kas neļauj jums izsaukt
šādu funkciju un radīt problēmu.
Es to pārkāpu tikai demonstrācijas dēļ.
Bet izredzes ir mājās, jūs pats nevarētu sastādīt šo kodu.
Bet ļaujiet man veikt pareizu šī koda versiju rekursīvi šādi.
Ļaujiet man atgriezties pie koda šeit.
Ļaujiet man iet uz priekšu un ne tikai akli sākt zīmēt vienu, tad
divus, tad trīs ķieģeļu slāņus.
Ļaujiet man, tāpat kā iepriekš, norādīt piramīdas augstumu, kādu viņi
vēlas, izmantojot mūsu get int funkciju.
Un tagad ļaujiet man atkal izsaukt augstuma vilkšanu.
Tāpēc tagad es atgriezīšos pie cilpas veida versijas.
Bet tā vietā, lai tagad izmantotu cilpu, šeit rekursija kļūst diezgan
eleganta, ja vēlaties.
Ļaujiet man turpināt un izpildīt un kodēt izlozes funkciju šādi.
Pēc jūsu definīcijas, ja 4. augstuma piramīda patiešām ir tikai
3. augstuma piramīda plus vēl viena rinda, tad pieņemsim to burtiski.
Ļaujiet man atgriezties pie sava koda.
Un, ja vēlaties uzzīmēt 4. augstuma piramīdu, ejiet tieši uz priekšu
un vispirms uzzīmējiet piramīdu ar augstumu 3 vai vispārīgāk no n
mīnus 1.
Bet kāds ir otrais solis?
Kad esat uzzīmējis 3. augstuma piramīdu, uzzīmējiet papildu rindu.
Tāpēc man vismaz šī problēmas daļa ir jāatrisina pašam.
Tāpēc ļaujiet man darīt, lai es saņemu 0.
i ir mazāks par n i++.
Un ļaujiet man, šīs funkcijas programmētājam, izdrukāt jaucējvērtības.
Un tad pašā apakšā izdrukājiet jaunu rindiņu, lai kursors pārvietotos
uz nākamo rindiņu.
Bet tas tagad ir elegants, es uzdrošinos teikt, ka izloze ir
rekursīva, jo es burtiski tulkoju no angļu valodas uz C kodu, šī
ideja, ka 4. augstuma piramīda patiesībā ir tikai 3. augstuma
piramīda.
Tāpēc es to daru vispirms.
Un es ticu, ka tas darbosies.
Tad man tikai jāuzliek vēl viena ķieģeļu kārta, četras no tām.
Tātad, ja n ir 4, šī ir tikai vienkārša cilpa, a la nedēļa 1, kas
izdrukās papildu slāni.
Bet tas, protams, galu galā būs problemātiski.
Kāpēc?
Tas vēl nav izdarīts, šī programma.
Cik reižu šajā modelī sevi piezvanīs zīmēšana?
STUDENTS: Tas ir bezgalīgi.
DEIVIDS MALANS: Bezgala daudz reižu.
Kāpēc?
STUDENTS: Jo nav atmest funkcijas.
DEIVIDS MALANS: Jā, nav līdzvērtīga atmešanai.
Piemēram, ja esat jau pietiekami drukājis, tad pametiet, kā mēs to
tveram?
Nu, es nedomāju, ka mēs vēlamies, lai tas būtu negatīvs.
Nebūtu jēgas zīmēt negatīvu augstuma piramīdu.
Tāpēc es domāju, ka mēs kā programmētājs varam vienkārši izvilkt
vienkāršu gadījumu, vieglu atbildi, tā saukto pamata gadījumu.
Un es tikai to darīšu.
Manas zīmēšanas funkcijas augšdaļā ļaujiet man vienkārši pateikt: ja
n ir mazāks par vai, velns, mazāks vai vienāds ar 0, tas arī viss.
Iet uz priekšu un vienkārši atgriezieties.
Vairs nav ko darīt.
Un šis vienkāršais nosacījums, kas tehniski pazīstams kā bāzes
gadījums, nodrošinās, ka kods nedarbosies mūžīgi.
Kāpēc?
Pieņemsim, ka izloze tiek izsaukta ar argumentu 4.
4, protams, nav mazāks par 0, tāpēc mēs neatgriežamies.
Bet mēs zīmējam piramīdu ar augstumu 3.
Un šeit lietas kļūst nedaudz garīgi sarežģītas.
Jūs nepāriet uz 20. rindu, kamēr nav izsaukta izloze.
Tātad, kad draw tiek izsaukts ar argumentu 3, tas ir tā, it kā jūs
atkal izpildītu no šīs funkcijas augšdaļas.
3 nav mazāks par 0.
Tātad, ko jūs darāt?
Jūs uzzīmējat 2.
Kā jūs uzzīmējat 2?
Nu, 2 nav mazāks par 0, tāpēc jūs neatgriežaties.
Tātad jūs uzzīmējat 1.
Šeit jābūt uzmanīgiem.
Izloze 1.
Un tagad mēs atgriežamies pie sākuma.
Kā jūs uzzīmējat 1?
Nu, 1 nav mazāks par 0, tāpēc jūs neatgriežaties.
Jūs uzzīmējat augstumu 0.
Kā jūs uzzīmējat 0 augstumu?
Pagaidiet minūti.
0 ir mazāks vai vienāds ar 0.
Un tu atgriezies.
Un tāpēc tas ir kā šis garīgais kaudze, šis darāmo darbu saraksts.
Jūs turpināt atlikt, izpildīt šīs apakšējās koda rindas, jo jūs
pastāvīgi restartējat, restartējat, restartējat zīmēšanas funkciju,
līdz beidzot kāds no šiem funkciju izsaukumiem saka, ka nav ko darīt,
atgriezieties.
Un tagad visa lieta sāk atšķetināt, ja vēlaties.
Un jūs atsākat no vietas, kur pārtraucāt.
Un tas, iespējams, ir labākais scenārijs.
Mēs to nedarīsim klasē.
Bet, ja vēlaties to atrisināt pats, izmantojot debug50, lai turpinātu
ieiet, ieiet, ieiet katrā no šīm līnijām, loģiski, jūs redzēsit, kas
patiesībā notiek.
Tāpēc ļaujiet man doties uz savu termināli un veikt rekursiju, kas
tagad ir šī pareizā koda versija, punktveida slīpsvītras rekursija.
Ievadīsim augstumu 4.
Un voila, tagad mums ir tā pati piramīda, neizmantojot iterāciju per
se, lai gan, protams, mēs izmantojam iterāciju, lai drukātu papildu
slāni.
Tagad mēs rekursīvi izmantojam zīmēšanu, lai drukātu visas mazākās
piramīdas, kurām jābūt pirms tās.
STUDENTS: Vai jūs varat izmantot rekursiju tikai tukšuma funkcijai?
[NEdzirdams]
DEIVIDS MALANS: Nē.
Jautājums ir, vai rekursiju var izmantot tikai ar tukšuma funkciju?
Nē, nemaz.
Faktiski ļoti bieži tiek izmantota atgriešanas vērtība, piemēram,
vesels skaitlis vai kaut kas cits, lai jūs varētu kaut ko
konstruktīvi paveikt ar šo faktisko vērtību.
Citi jautājumi par šo.
STUDENTS: Kad tiek izpildīta 21. rinda?
DEIVIDS MALANS: Sakiet to nedaudz skaļāk.
STUDENTS: Kad tiek izpildīta 21. rinda?
DEIVIDS Malans: Kad tiek izpildīta 21. rindiņa?
Tātad, ja turpināsiet, ļaujiet man ritināt vēl mazliet uz leju, lai
jūs varētu redzēt koda augšdaļu.
Tātad 21. rinda tiks izpildīta, tiklīdz 19. rinda tiks izpildīta pati.
Tagad stāstā, ko es stāstīju, mēs turpinājām saukt vēlreiz, vēlreiz,
vēlreiz.
Bet, tiklīdz nekavējoties atgriežas kāds no funkciju izsaukumiem, kur
n ir 0, mēs neturpinām zīmēt atkal un atkal.
Tātad, ja jūs domājat par procesu kā atpakaļgaitu, tad turpiniet 21.
rindu, pēc tam vēlreiz 21. rindu, tad atkal 21. rindu un kā loģikas
atšķetināšana.
Un nākamnedēļ mēs patiesībā uzzīmēsim priekšstatu par to, kas
patiesībā notiek datora atmiņā.
Bet pagaidām tas ir tikai ļoti līdzīgs tālruņu kataloga pseidokodam.
Jūs tikai meklējat atkal un atkal.
Bet jūs gaidāt līdz pašām beigām, lai atgūtu gala rezultātu.
Google tagad, ko es šodien nejaušības dēļ pieminu, protams, ir pilns
ar programmētājiem.
Šeit ir jautrs vingrinājums.
Ļaujiet man atgriezties pārlūkprogrammā.
Es iešu uz priekšu un meklēju rekursiju, jo vēlos kaut ko uzzināt par
rekursiju.
Šeit ir sava veida interneta mēms vai joks.
Ja es šeit pietuvinu, Google inženieri ir smieklīgi.
Redzi, kāpēc?
STUDENTS: Ak.
DEIVIDS MALANS: Ak, lūk.
Jā.
Jā, tā ir rekursija.
Un tagad būs tik daudz mēmu, ar kurām jūs saskarsities, piemēram, ja
kādreiz esat pavērsis kameru pret televizoru, kas rāda kameru, un
atkal un atkal redzat sevi vai attēlu, tas tiešām ir. rekursija.
Un tādā gadījumā tas apstājas tikai tad, kad nokļūstat viena pikseļa
pamata korpusā.
Bet tas ir ļoti smieklīgs joks dažās aprindās, kad runa ir par
rekursiju un Google.
Tātad, kā mēs varam faktiski izmantot Google vai, pareizāk sakot, kā
mēs varam faktiski izmantot rekursiju konstruktīvi?
Ļaujiet man ierosināt, ka mēs faktiski ieviesām trešo un pēdējo
šķirošanas algoritmu, kas, cerams, darbojas labāk nekā divi līdz šim.
Mēs esam veikuši atlases kārtošanu un burbuļu kārtošanu.
Bubble sort, mums patika nedaudz labāk, vismaz tiktāl, cik labākajā
gadījumā saraksts jau ir sakārtots.
Bubble sort ir vismaz gudrāks, un tas faktiski beigsies agri,
sniedzot mums labāku apakšējo robežu mūsu omega apzīmējuma ziņā.
Bet izrādās, ka rekursija, un tā ne vienmēr ir rekursijas iezīme, bet
gan kaut kas, ko mēs tagad varam izmantot.
Izrādās, izmantojot rekursiju, mēs varam izmantot principiāli
atšķirīgu pieeju, lai sakārtotu veselu skaitļu gūzmu tā, lai mēs
varētu veikt daudz mazāk salīdzinājumu un ideālā gadījumā paātrināt
gala rezultātus.
Tātad šeit ir pseidokods tam, ko mēs gatavojamies redzēt kaut kam, ko
sauc par sapludināšanas kārtošanu.
Un tas tiešām ir tik īss.
Kārtojiet skaitļu kreiso pusi.
Kārtojiet skaitļu labo pusi.
Apvienojiet sakārtotās pusītes.
Tas ir gandrīz muļķīgi, jo, ja jums tiek prasīts kārtošanas
algoritms, un jūs atbildat ar, labi, kārtojiet kreiso pusi, kārtojiet
labo pusi.
Tas ir grūti, jo es prasu šķirošanas algoritmu.
Jūs man tikai sakāt, lai sakārtoju kreiso pusi un labo pusi.
Taču šajā pēdējā rindā sapludināšana ir diezgan spēcīga šāda veida
iezīme.
Tagad mums ir nepieciešams vēl viens bāzes gadījums augšpusē.
Tāpēc ļaujiet man pievienot šo.
Ja mēs atrodam sev sarakstu, masīvu, kura izmērs ir 1, tad šis masīvs
acīmredzami ir sakārtots.
Ja tajā ir tikai viens elements, nekas nav jādara.
Tātad tas būs mūsu bāzes gadījums.
Bet tagad ļaujot mums tikai šajās, četrās, sešās pseidokoda rindās
faktiski sakārtot dažus elementus.
Bet vispirms pievērsīsimies tikai šī apakškopai.
Uz brīdi padomāsim, ko nozīmē sašķirotu pusīšu sapludināšana.
Tāpēc Kārters ir brīnišķīgi nācis pie brīvprātīgā darba, lai
palīdzētu mums atiestatīt šos skaitļus.
Pieņemsim, ka stāsta vidū, ko mēs gatavojamies stāstīt, mums ir divas
sakārtotas puses.
Es jau esmu sakārtojis šo skaitļu kreiso pusi, un tiešām, 2, 4, 5, 7
ir sakārtoti no mazākā uz lielāko.
Un labā puse, šķiet, jau ir sakārtota, 0, 1, 3, 6, jau sakārtota.
Tātad manā pseidokodā mēs jau esam pabeiguši šķirot kreiso pusi un
labo pusi.
Bet pēc brīža redzēsim, kā būs.
Nu, kā es varu apvienot šīs divas puses?
Tā kā tie jau ir sakārtoti un jūs vēlaties tos apvienot secībā, es
domāju, ka mēs varam apgriezties uz leju.
Mēs varam paslēpt visus skaitļus, izņemot pirmos, katrā no šiem
apakšsarakstiem.
Šeit mums ir puse, kas sākas ar 2.
Un man ir vienalga, kādi ir citi skaitļi, jo tie nepārprotami ir
lielāki par 2.
Es varu koncentrēties tikai uz 2 un arī 0, arī 0.
Mēs zinām, ka 0 ir mazākais, tāpēc ignorēsim skaitļus, kurus Kārters
laipni pagrieza uz leju.
Tātad, kā apvienot šos divus sarakstus jaunā sakārtotā lielākā
sarakstā?
Es salīdzinu divus kreisajā pusē esošus ar 0 labajā pusē, protams,
kas ir pirmais, 0.
Tāpēc ļaujiet man to nolikt šeit.
Un Kārter, ja vēlaties dot mums nākamo elementu.
Tagad man ir divas sakārtotas pusītes.
Bet vienu jau esmu noplūkusi.
Tāpēc tagad es salīdzinu abus ar 1.
1 acīmredzot nāk nākamais.
Tāpēc es izņemšu 1 un ievietošu to šeit.
Tagad es atkal salīdzināšu abas puses.
2 un 3, kuru apvienot vispirms?
Acīmredzot nākamais nāk 2.
Un tagad ievērojiet, ka katru reizi, kad es to daru, manas rokas
teorētiski virzās uz priekšu.
Es nedublēju atpakaļ, kā turpināju darīt ar atlases kārtošanu vai
burbuļu kārtošanu, uz priekšu un atpakaļ, uz priekšu un atpakaļ.
Mani pirksti pastāvīgi virzās uz priekšu, un tā būs galvenā detaļa.
Tāpēc es acīmredzami salīdzinu 4 un 3, 3.
Es acīmredzami salīdzinu 4 un 6, 4.
Es acīmredzami salīdzinu 5 un 6, 5.
Un tad es salīdzinu 7 un 6, protams.
Un, visbeidzot, mums ir palicis tikai viens elements.
Un, lai gan es kā cilvēks pārvietojos neveikli, manas rokas tehniski
virzījās tikai pa labi.
Es nekad neatgriezos kaut ko darot atkal un atkal.
Un tā, iespējams, ir intuīcija, un tikai pietiekami daudz vietas 7.
Tādā veidā jūs apvienotu divas sakārtotas daļas.
Mēs sākām ar kreiso pusi sakārtotu, labo pusi sakārtotu.
Un saplūšana ir tāpat kā tas, ko jūs darītu kā cilvēks.
Un Kārters vienkārši pagrieza skaitļus uz leju, tāpēc mēs
koncentrējāmies tikai uz mazākajiem elementiem katrā.
Vai jums ir kādi jautājumi, pirms mēs turpinām runāt par to, ko tad
nozīmē apvienoties šādā veidā?
Tātad tagad šeit ir oriģināls saraksts.
Mēs apzināti to ievietojām augšpusē, jo ir viena sapludināšanas
detaļa, kas ir galvenā.
Sapludināšanas kārtošana tehniski aizņems nedaudz vairāk vietas.
Un tā, lai gan iepriekš mēs vienkārši pārvietojām savus cilvēkus un
mainījām cilvēkus un pārliecinājāmies, ka viņi galu galā paliek
sākotnējā pozīcijā.
Izmantojot sapludināšanas kārtošanu, izliekas, ka šeit ir mūsu
sākotnējais atmiņas masīvs.
Man būs nepieciešams vismaz viens cits atmiņas masīvs.
Un es krāpšos, un es izmantošu vēl vairāk atmiņas.
Bet tehniski es faktiski varētu iet uz priekšu un atpakaļ starp 1
masīvu un sekundāro masīvu.
Bet tas man aizņems vairāk vietas.
Tātad, kā šajā kodā ieviest sapludināšanas kārtošanu?
Nu, ņemsim vērā šo.
Šeit ir 8 izmēra masīvs.
Ja izstājas tikai viens numurs, tas acīmredzami nav piemērojams.
Tāpēc koncentrēsimies uz sulīgo daļu.
Kārtojiet skaitļu kreiso pusi.
Labi, kā sakārtot skaitļu kreiso pusi?
Es vienkārši pagrūdīšu tos, lai būtu skaidrs, kas ir kreisā puse.
Šeit tagad ir 4. izmēra apakšsaraksts.
Kā kārtot kreiso pusi?
Nu, vai man ir algoritms šķirošanai?
Jā, ko man darīt?
Šeit ir 4. izmēra saraksts.
Kā to kārtot?
Kas ir pirmais solis?
Kārtojiet kreiso pusi.
Tāpēc es tagad savā prātā konceptuāli izmantoju šo 4. izmēra
apakšsarakstu.
Un es to sakārtoju, vispirms šķirojot kreiso pusi, tagad
koncentrējoties uz 7. un 2.
Labi, šeit ir 2. izmēra saraksts.
Kā kārtot 2. izmēra sarakstu?
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Atvainojiet?
Es domāju, ka mēs vienkārši turpinām sekot mūsu norādījumiem.
Kārtojiet kreiso pusi.
Labi, šeit ir 1. izmēra saraksts.
Kā kārtot 1. izmēra sarakstu?
STUDENTS: [NEdzirdams]
DEIVIDS MALANS: Esmu pabeidzis.
Tas ir izdarīts.
Tāpēc es atstāju šo mierā.
Kāds bija stāsta nākamais solis?
Es tikko sakārtoju kreiso pusi no kreisās puses.
Kas būs tālāk?
Es šķiroju labo pusi no kreisās puses kreisās puses, un esmu
pabeidzis, jo tas ir tikai 1. izmēra saraksts.
Kas nāk pēc šī?
Apvienot.
Šeit tas kļūst nedaudz trausls, jo jums ir jāatceras, kur mēs
pārtraucam stāstu, lai darītu lietas rekursīvi atkal un atkal.
Bet, ja es tikko sakārtoju kreiso pusi un tikko sakārtoju labo pusi,
tagad es tās apvienoju.
Šis ir ļoti īss saraksts, tāpēc mums nav vajadzīga Kārtera palīdzība
kā iepriekš.
Bet es domāju, ka pirmais skaitlis, ko es šeit paņemu, ir 2.
Un tad otrais skaitlis, ko es paņemu, jo tā ir vienīgā iespēja, ir 7.
Bet tagad patīkami ir tas, ka, ievērojiet, kreisā puse patiešām ir
sakārtota, jo es triviāli sakārtoju tās kreiso pusi un labo pusi.
Bet tad saplūšana patiešām ir vieta, kur notiek burvība.
Labi, vēlreiz, ja jūs domājat attīt atpakaļ, ja es tikko sakārtoju
kreiso pusi no kreisās puses, kas notiks tālāk?
Kārtojiet labo pusi no kreisās puses.
Tātad atkal jūs kaut kā attāties laikā.
Tātad, kā to izdarīt?
Man ir 2. izmēra saraksts.
Es šķiroju kreiso pusi, tikai 5, pabeigta.
Kārtot labo pusi, 4, gatavs.
Tagad interesantā daļa, es sapludinu kreiso pusi un labo pusi no
kreisās puses labās puses.
Tātad, ko man darīt?
4 nāk šeit.
5 nāk šeit.
Un tagad ievērojiet, kas man ir.
Kreisā puse ir sakārtota.
Labā puse ir sakārtota.
Ja attīt laiku atpakaļ, kur ir mans nākamais solis, 3?
Apvienojiet abas puses.
Un tas ir tas, ko Kārters man palīdzēja darīt iepriekš.
Koncentrēsimies tikai uz mazākajiem elementiem, lai būtu mazāka
uzmanības novēršana.
Es salīdzinu 2 un 4.
2 ir pirmajā vietā, tāpēc, protams, liksim to šeit.
Tagad es salīdzinu šī saraksta jauno sākumu un šī saraksta veco
sākumu.
4 acīmredzot nāk nākamais.
Un tagad es salīdzinu 7 ar 5.
5 acīmredzot nāk nākamais.
Un tagad, visbeidzot, man ir palicis viens numurs.
Tāpēc tagad esmu nokļuvis 7.
Tātad, pat ja jūs esat pazaudējis dažas no niansēm šeit, ja jūs
vienkārši sperat soli atpakaļ, sākotnējā labā puse joprojām ir
neskarta.
Bet sākotnējās ievades kreisā puse tagad patiešām ir sakārtota,
kārtojot kreiso pusi, labo pusi, kreiso pusi, labo pusi, bet ar šiem
sapludinājumiem starp tiem.
Labi, tādēļ, ja esam tikko sakārtojuši kreiso pusi, mēs attīsim
atpakaļ līdz sākumam.
Ko man tagad darīt?
Labi, kārtojiet labo pusi.
Tātad kārtojiet labo pusi.
Kā kārtot 4. izmēra sarakstu?
Vispirms es šķiroju kreiso pusi, 1. un 6.
Kā kārtot 2. izmēra sarakstu?
Jūs kārtojat kreiso pusi, tikai numuru 1.
Acīmredzot nav ko darīt.
Gatavs, sakārtojot kreiso pusi.
6, darīts, šķirojot labo pusi.
Ko man darīt?
Es sapludinu kreiso pusi šeit ar labo pusi šeit.
Un tas ir diezgan vienkārši.
Ko man darīt?
Es tikko apvienojos.
Tāpēc tagad es to šķiroju.
Es tikko sakārtoju kreiso pusi no labās puses.
Tāpēc tagad es šķiroju labās puses labo pusi.
Tāpēc es uzskatu, ka 0 ir gatavs.
Es uzskatu, ka 3 ir pabeigts.
Tagad es apvienoju šos divus kopā.
0, protams, ir pirmajā vietā.
Tad nāk 3.
Un tagad es esmu tajā stāsta punktā, kur esmu sakārtojis labās puses
kreiso pusi un labās puses labo pusi.
Tātad 3. darbība ir sapludināšana.
Un es darīšu to vēlreiz, kā mēs to darījām ar Kārteru.
Labi, 1 un 0, protams, 0 ir pirmais.
Tagad salīdziniet 1. un 3.
Acīmredzot pirmais ir pirmais.
Salīdziniet 6 un 3, protams, 3.
Un tad visbeidzot, 6.
Tātad, kur mēs esam tagad?
Mēs esam paņēmuši visas lietas kreiso pusi un sakārtojuši to.
Pēc tam mēs paņēmām visas lietas labo pusi un sakārtojām to.
Tātad tagad mēs pēdējo reizi esam pie 3. darbības.
Ko mēs darām?
Apvienot.
Un tāpēc, lai būtu konsekvence, ļaujiet man tos pazemināt un
salīdzināt.
Kreisā vai labā roka, pamanot, ka viņi tikai progresē uz priekšu,
neviens no šiem turp un atpakaļ salīdzinājumiem.
2 un 0, protams, 0.
Tāpēc mēs to noliksim vietā.
2 un 1, protams, 1.
Tāpēc mēs to ievietojām vietā.
2 un 3, mēs, protams, šajā gadījumā apvienojam 2.
4 un 3, šajā gadījumā mēs tagad apvienojam 3.
4 un 6, mēs tagad, protams, apvienojam 4 vietā.
Un tagad mēs salīdzinām 5. un 6.
Mēs paturam 5.
Kļūda.
Labi, izliecieties, ka 5 ir ieslēgts.
Ak, tāpēc.
Labi, tāpēc tagad mēs salīdzinām 7 un 6.
6. ir pazudis.
Un visbeidzot, 7 ir pēdējais vietā.
Un, lai gan es to pieļauju no visiem algoritmiem, tas, iespējams, ir
visgrūtāk sekot līdzi, it īpaši, ja es to daru kā balsi.
Saprotiet, ka tas, ko mēs tikko esam paveikuši, ir tikai šie trīs
soļi, rekursīvi.
Mēs sākām ar 8. izmēra sarakstu.
Mēs sakārtojām kreiso pusi.
Mēs sakārtojām labo pusi.
Un tad mēs apvienojam abus kopā.
Bet, ja jūs ejat uz leju katrā no šīm trušu bedrēm, tā sakot, kreisās
puses šķirošana ietver kreisās puses kreisās puses šķirošanu un
kreisās puses labās puses šķirošanu, un tā tālāk.
Bet šis idejas dīglis par patiesu problēmas sadalīšanu un
pārvarēšanu, nevis tā, ka jums ir problēma un jātiek galā tikai ar
vienu pusi.
Skaidrs, ka mēs šķirojam vienu pusi un otru pusi un galu galā tās
apvienojam.
Tas joprojām mūs noved pie tā paša risinājuma.
Un, ja mēs tagad vizualizējam šīs paliekas, ja es to attēloju šādi,
kur šeit ekrānā jūs redzat, kur skaitļi sākotnēji sākās augšējā rindā
no kreisās uz labo.
Būtībā, lai gan tas ir citā secībā, es galu galā sadalīju šo
8. izmēra sarakstu astoņos 1. izmēra sarakstos.
Un šeit sākās pamatgadījums un vienkārši teica: Labi, mēs esam
pabeiguši šķirošanu.
Un pēc tam, loģiski, es apvienoju divus 1. izmēra sarakstus daudzos
2. izmēra sarakstos un 2. izmēra sarakstus 4. izmēra sarakstos.
Un tad visbeidzot 4. izmēra saraksts vienā lielā sarakstā, kas
sakārtots pēc 8. izmēra.
Un tāpēc es izliku šo attēlu ar mazajiem līniju indikatoriem, jo cik
reizes es dalīju, dalīju, dalīju uz pusēm?
Vai tiešām dubultā, dubultā, dubultā.
Tātad eksponents ir pretējs - spoileris.
Cik reizes es sadalīju?
Tātad trīs, konkrēti.
Bet, ja kopā ir astoņi elementi un vispārīgāk ir n, tas tiešām ir
jautājums par log n reižu sadalīšanu un iekarošanu.
Jūs sākat to un varat dalīt vienu, divas, trīs reizes, reģistrēties n
reizes.
Vai otrādi, jūs varat sākt šeit un eksponenciāli dubultot, dubultot,
dubultot trīs reizes, kas ir log n.
Bet katrā rindā, katrā plauktā, burtiski, es sacēlu traci par to, ka
rādīju rokas tikai no kreisās uz labo pusi, nepārtraukti virzot tās
uz priekšu, tā ka katru reizi, kad veicu šos sapludināšanu, es
pieskāros katram elementam vienreiz un tikai vienu reizi.
Uz skatuves nebija nekā tāda turp un atpakaļ, šurpu turpu.
Tātad, ja es kaut ko daru log n reizes vai, ja es daru, n lietas log
n reizes, kāda būtu mūsu lielā O formula, iespējams?
n lietas reģistrētas n reizes?
STUDENTS: Ak, tas ir n log n.
DEIVIDS MALANS: Jā, tātad n log n.
Faktiski n log n secība ir tāda, kā mēs aprakstītu sapludināšanas
kārtošanas darbības laiku.
Un tā no visiem līdzšinējiem veidiem, mēs esam redzējuši, ka
sapludināšanas kārtošana šeit faktiski ir n log n, kas ir noteikti
labāka nekā n kvadrātā, kur ir gan atlases kārtošana, gan burbuļu
kārtošana.
Bet tas ir arī lēnāks nekā, piemēram, lineārā meklēšana.
Bet jūs drīzāk to sagaidīsit.
Ja jums ir daudz jāstrādā, lai sakārtotu dažus elementus, nevis tikai
tos meklētu, jums būs jāpieliek lielākas pūles.
Un tāpēc jautājums par to, vai jums vajadzētu kaut ko akli meklēt,
izmantojot lineāro meklēšanu, un netraucēt to šķirot, patiešām ir
saistīts ar to, vai jūs varat atļauties tērēt tik daudz laika?
Un, ja esat pasaules Google, pastāv iespēja, ka nevēlaties katru
reizi veikt meklēšanu viņu datubāzē lineāri.
Kāpēc?
Jo jūs varat to kārtot vienreiz un pēc tam gūt labumu miljoniem,
miljardiem cilvēku, pēc tam izmantojot kaut ko līdzīgu binārajai
meklēšanai vai, atklāti sakot, praksē kaut ko vēl skaistāku un ātrāku
par bināro meklēšanu.
Bet vienmēr būs šis kompromiss.
Bināro meklēšanu var veikt tikai tad, ja elementi ir sakārtoti.
Cik tev izmaksā to šķirošana?
Varbūt n kvadrātā, ja izmantojāt kādu no iepriekšējiem algoritmiem.
Bet izrādās, arī pieteikšanās ir diezgan ātra.
Tātad dienas beigās šie darbības laiki ietver kompromisus.
Un patiešām, 2. sapludināšanas kārtojumā, man jāatzīmē, ka
sapludināšanas kārtošanas apakšējā robeža arī būs n log n omega.
Tādējādi mēs to varam aprakstīt ar mūsu teta apzīmējumu, sakot, ka
sapludināšanas kārtošana patiešām ir n log n teta.
Tātad vispārīgi runājot, iespējams, labāk ir izmantot kaut ko līdzīgu
sapludināšanas kārtošanai vai kādu citu algoritmu, kas ir n log n.
Praksē lielākā daļa programmētāju paši neievieš šos šķirošanas
algoritmus.
Iespējams, viņi izmanto bibliotēku no plaukta, kas paši ir pieņēmuši
lēmumu par to, kuru no šiem algoritmiem darīt.
Bet vispārīgi runājot, un tagad mēs to redzam pirmo reizi, ja
vēlaties uzlabot laiku, piemēram, izmantot mazāk laika, rakstīt
ātrāku kodu, jums ir jāmaksā cena.
Un tas varētu būt jūsu cilvēciskais laiks, taču jums ir nepieciešams
vairāk laika, lai iekodētu kaut ko sarežģītāku, grūtāk īstenojamu.
Vai arī jums ir jāpavada kaut kas līdzīgs telpai.
Kā liecina šie plaukti, arī tā ir viena no galvenajām sapludināšanas
detaļām.
Jūs nevarat vienkārši nomainīt elementus savās vietās.
Vajag vismaz palīgmasīvu, lai, veicot sapludināšanu, būtu kur tos
likt.
Un tas ir pārmērīgi liels atmiņas apjoms.
Es būtu varējis iet uz priekšu un atpakaļ starp augšējo plauktu un
apakšējo plauktu.
Bet ir nedaudz interesantāk iet no augšas uz leju.
Bet jums ir nepieciešams vairāk vietas.
Toreiz, pirms gadu desmitiem, telpa bija patiešām dārga.
Un tad zini ko?
Iespējams, būtu bijis labāk neizmantot sapludināšanas kārtošanu,
burbuļu kārtošanu vai atlases kārtošanu vai kādu citu algoritmu.
Mūsdienās telpa ir salīdzinoši lēta.
Un tāpēc tie ir pieņemamāki kompromisi.
Bet tas ir pilnībā atkarīgs no lietojumprogrammas.
Pēdējā lieta, ko mēs domājām darīt, ir parādīt dažu šo šķirošanas
algoritmu faktisku salīdzinājumu.
Tas ir apmēram 60 sekundes garš.
Un tas salīdzinās jums, atlases kārtošanu, burbuļu kārtošanu un
sapludināšanu, vienlaikus ar kādu jautru šķirošanas mūziku, parādot,
ko patiesībā nozīmē būt O no n kvadrātā vai vēl labāk lielam O no n
log n. .
Augšpusē atlase.
Burbulis apakšā.
Apvienojiet vidū.
[MŪZIKA ATSKAŅOTĀS]
Labi, tas ir paredzēts CS50.
Tiksimies nākamreiz.