[Powered by Google Translate] [Раздел 3 - по-комфортно] [Роб Боудън - Харвардския университет] [Това е CS50. - CS50.TV] Така че първият въпрос е странно формулирана. GDB позволява "дебъгване" програма, но, по-конкретно, какво ви позволи да направите? Ще отговори на този въпрос, и аз не знам какво точно очаква, така че предполагам, че е нещо по подобие на това ви позволява да стъпка по стъпка ходи чрез програмата, да взаимодейства с него, промяна на променливи, всички тези неща - основно изцяло да контролират изпълнението на програмата и да инспектира която и да е част от изпълнението на програмата. Така че тези функции ви позволяват да развенчава неща. Добре. Защо двоично търсене изисква се сортират масив? Кой искаш да ти отговоря? [Ученик] Тъй като това не работи, ако това не е сортиран. >> Да. [Смях] Ако това не е сортиран, а след това е невъзможно да се разделят на половина и знаят, че всичко на ляво е по-малко и всичко в дясно е по-голяма от средната стойност. Така че трябва да се сортира. Добре. Защо е балон вид в O N квадрат? Ли някой искам първо да се даде много бърз високо ниво преглед на това, което балон вид е? [Ученик] основно мине през всеки един елемент и да проверите първите няколко елемента. Ако те са на мястото, където ги разменят, а след това да проверите следващите няколко елемента и така нататък. Когато стигнете до края, тогава знаете, че най-големият елемент е поставен в края, , така че да пренебрегнем факта, че след това продължавате да става чрез и всеки път, когато трябва да се провери един по-малко елемент, докато не направи никакви промени. >> Да. Тя се нарича балон вид, защото, ако обърнете масив от своя страна, така че е и надолу, вертикални, големи стойности ще потъне на дъното и малки стойности ще изплуват на върха. Ето как той получава своето име. И да, просто отидете. Вие продължавате да ходите чрез масив, смяна на по-голямата стойност за да получите най-големите стойности на дъното. Защо е о н квадрат? Първо, няма кой искам да кажа защо е О N на квадрат? [Ученик] Защото за всеки план отива н пъти. Можете да бъдете сигурни, че сте взели най-големият елемент по целия път надолу, тогава ще трябва да повторя, че като много елементи. >> Да. Така че имайте предвид това, което Big O означава и какви големи Омега средства. The Big O е като горна граница за това как бавно тя действително може да работи. Така че, като казват, че е O N квадрат, той не е O на N или иначе щеше да бъде в състояние да тече в линейното време, но е о н кубчета тъй като тя е ограничена от O N кубчета. Ако е ограничена от O N квадрат, а след това е ограничена и от N кубчета. Така че това е N на квадрат, и в абсолютно най-лошия случай не може да направи по-добре, отколкото н квадрат, което е, защо е O N квадрат. Така че, за да видите лек математика как тя идва, за да бъдат н квадрат, ако имаме пет неща в нашия списък, за първи път колко суапове можем потенциално трябва да се направи за да се получи това? Нека всъщност само Колко суапове ние ще трябва да направи в първия манш на балон вид чрез масив? [Ученик] - 1. >> Да. Ако има 5 елемента, ние ще трябва да се направи N - 1. След това на втория колко суапове ние ще трябва да направи? [Ученик] - 2. >> Да. И трето ще бъде N - 3, а след това за удобство ще напиша последните две както и тогава ние ще трябва да направят две суапове и 1 суап. Предполагам, че последната може или не може всъщност трябва да се случи. Суап? Не знам. Така че това са общите суми, за суап или най-малко сравнения, които трябва да направите. Дори ако не сменяте, все още трябва да се сравнят стойностите. Така че има N - 1 сравнения в първия манш чрез масив. Ако реорганизиране на тези неща, нека го направи шест неща, така че нещата се натрупват добре, и тогава аз ще направя 3, 2, 1. Така че просто пренареждане на тези суми, искаме да видим колко сравнения правим в целия алгоритъм. Така че, ако ние носим тези момчета тук, тогава ние все още само сумиране обаче много сравнения имало. Но ако сумираме тези и обобщим тези и обобщим тези, тя все още е същия проблем. Ние просто обобщим тези определени групи. Така че сега сме сумиране 3 н. Това не е само на 3 н. Той винаги ще бъде N / 2 н. Така че тук сме се случи да има 6. Ако имахме 10 неща, тогава бихме могли да направим тази група в продължение на пет различни двойки неща и в крайна сметка с N + N + N + N + N. Значи винаги ще получите N / 2 N и така че това ще го нахвърлям н квадрат / 2. И така, въпреки че това е фактор на половина, което се случва, да дойде в поради факта, че през всяка итерация над масива сравним един по-малко така че това е начина, по който получават над 2, но тя все още е N квадрат. Не ни пука за постоянен фактор на половина. Така много големи неща O като това се основава на просто за правене на този вид математика, смятане суми и геометрична прогресия неща, но повечето от тях в този курс са доста ясен. Добре. Защо е вмъкване вид в омегата на N? Какво омега означава? [Двама студенти говорят едновременно - неразбираеми] >> Да, Омега можеш да се сетиш като долната граница. Така че без значение колко ефективен алгоритъм за вмъкване вид, независимо от списъка, който ще премина в, тя винаги трябва да се сравнят най-малко N неща или има за обхождане н неща. Защо е така? [Ученик] Защото, ако списъкът е вече подредени, след това през първата итерация можете само да се гарантира, че първия елемент е най-малкото, и втората итерация можете само да се гарантира, първите две са защото не знаят, че останалата част от списъка се сортират. >> Да. Ако премине в напълно сортиран списък, най-малкото, което трябва да премине всички елементи да се види, че нищо не трябва да се местят. Така че, минаваща през списъка и да казва О, това е вече подредени, това е невъзможно, за да знаеш, че е сортират, докато не се провери всеки елемент да се види, че те са подредени за. Така че долната граница за добавяне вид е омегата на N. Какво най-лошия случай времето за работа на вид сливане, най-лошия случай са големи O отново? Така че в най-лошия случай, как се сливат вид бягаш? [Ученик] N дневник н. >> Да. Най-бързите общи алгоритми за сортиране н н дневник. Не можеш да направиш по-добре. Има специални случаи, и ако имаме време днес, но вероятно won't - можем да видим този, който прави по-добре от N дневник н. Но в общия случай, не може да направи по-добре, отколкото N дневник н. И се сливат вид се случва да бъде този, който трябва да знаете за този курс, който е N дневник н. И така, ние действително ще се реализира това днес. И накрая, в не повече от три изречения, как работи на избора Сортиране? Ли някой ще иска да отговори, и аз ще брои твоите изречения защото ако отидете над 3 години - Има ли някой помни вид избор? Избор на вид обикновено е доста лесно да се помни само от името. Обхождане на масива намерите всичко, най-голямата стойност е или най-малката - какъвто ред сортиране инча Така че нека да кажем, че ние сме сортиране от най-малкия до най-. Обхождане на масива, за каквато и да е елемент на минимална го изберете, и след това просто го сменяте каквото и да е на първо място. И тогава на второто преминаване през масива, погледнете отново за минималния елемент, го изберете, и след това да го сменяте с това, което е на втора позиция. Така че ние просто бране и избор на минималните стойности и да ги поставите в предната част на масива, докато тя се сортират. Въпроси за това? Това неминуемо се появяват във формулярите, които трябва да попълните, когато сте подаване на pset. Тези, които са в основата на отговорите на тези. Добре, сега кодиране проблеми. Вече изпрати по имейл - Никой ли не получите този имейл? Добре. Вече изпрати по имейл пространството, че отиваме да се използва, и ако кликнете върху името ми - така че аз мисля, че ще бъда на дъното поради назад R, но ако кликнете върху името ми, ще видите две ревизии. Преглед на 1 ще бъде вече копира и кода в пространства за търсене, което вие ще трябва да прилагат. Revision 2 ще бъде нещо, вид, който ние прилагаме след това. Така че, можете да кликнете върху моя Преглед на 1 и да работят от там. И сега искаме да прилагане на двоично търсене. Някой иска ли да даде pseudocode високо ниво обяснение от това, което ще трябва да направите, за търсене? Да. [Ученик] Просто средата на масива и да видим дали това, което търсите за е по-малко от това, или повече от това. И ако това е по-малко, и да отидете до половината, това е по-малко, и ако това е по-, отидете до половината, това е повече и ви повтарям, че докато само едно нещо. [Bowden Да. Забележете, че нашите номера масив вече е сортиран, и така това означава, че можем да се възползват от това и ние първо да се провери, Добре, аз съм за номер 50. Така че мога да отида в средата. Средата е трудно да се определи, когато е четен брой на нещата, но нека просто кажем, че ние винаги ще се отреже до средата. Така че тук имаме 8 неща, така че средата ще бъде 16. Търся 50, така че 50 е по-голямо от 16. Така че сега мога да основно лечение на моя масив, тъй като тези елементи. Мога да изхвърлите всичко, което е от 16 над. Сега масив ми е само тези четири елемента, и повтарям. Значи искам отново да се намери средата, която ще бъде 42. 42 е по-малко от 50, така че мога да изхвърлим тези два елемента. Това е моят останалите масив. Отивам да се намери средата. Предполагам, че 50 е лош пример, защото бях винаги захвърли неща наляво, но от същата мярка, ако аз търся нещо и това е по-малко от елемента Аз съм в момента гледа, тогава аз ще изхвърля всичко в дясно. Така че сега ние трябва да се прилагат. Забележете, че ние трябва да мине по размер. Ние също така не може да се наложи трудно размера на кода. Така че, ако ние се отърва от това # определят Добре. Как мога добре да разбера каква е големината на номерата масив в момента е? Колко елементи са в номера масив? [Студентски] числа, скоби, дължина? [Bowden Това не съществува в C. Нуждаете се дължина. Масивите не са свойства, така че не е дължина на собственост на масиви , които просто ще ви дам колкото и дълго да се случва да бъде. [Ученик] Вижте колко памет има и да се разделят с колко - >> Да. И така, как можем да видим, колко памет има? >> Студент Sizeof. >> Да, sizeof. Sizeof е оператор, който ще се върне размера на номерата масив. И това ще бъде обаче много числа има пъти размера на цяло число тъй като това е колко памет всъщност се. Така че, ако искам броя на нещата в масива, тогава аз ще искат да се разделят от размера на цяло число. Добре. Така че това ми позволява да премине в размер тук. Защо въобще трябва да се премине в размер на? Защо не мога просто правя тук INT размер = sizeof (купа сено) / sizeof (INT)? Защо не работи? [Ученик] Това не е глобална променлива. [Bowden Haystack съществува и ние сме преминаване в числа като купа сено, и това е един вид предвестник на това какво ще стане. Да. [Ученик] купа сено е само препратка към него, така че ще се върне, колко е голяма тази препратка е. Да. Съмнявам се в лекцията, че все още сте виждали стека наистина, нали? Ние току-що говорих за това. Така че стека е мястото, където всички променливите ще се съхраняват. Всяко памет, която е отпусната за локални променливи в стека, и всяка функция си има своя собствена пространство в стека, своя собствена рамка стак е това, което се нарича. Така че основната има своя стак рамка и вътре в него ще съществува този брой масив, и тя ще бъде на размера sizeof (брой). Ще има размер на числа, разделени според размера на елементите, но че всички живее в рамките на стека рамка на главната. Когато ние наричаме търсене, търсене получава своя собствена рамка стека, своето пространство за съхранение на всички локални променливи. Но тези аргументи - така купа сено не е копие на целия този масив. Ние не премине в целия масив като копие в търсене. Тя просто минава позоваване на този масив. Така че търсенето може да получите достъп до тези номера чрез тази препратка. Тя все още достъп до неща, които живеят вътре в стека рамка на главната, но основно, когато стигнем до указатели, което трябва да бъде скоро, това е, което указатели са. Указатели са само препратки към неща, и можете да използвате указатели за достъп до неща , които са в стек рамки на други неща. Така че, въпреки че номера е местно до главната, ние все още може да получите достъп до него чрез този указател. Но тъй като това е просто показалеца и това е просто, sizeof (купа сено) се връща размера на самия референтен. Тя не се връща размера на нещо, което той посочи. Тя не се връща действителния размер на номера. И така, това не се случва да работят, тъй като искаме да. Въпроси за това? Указатели ще се отиде в значително по-кървави подробности в седмици, за да дойде. И това е защо много от нещата, които виждате, повечето неща за търсене или подреди нещата, те са почти всички ще трябва да се вземе действителният размер на масива, тъй като в C, ние нямаме представа каква е големината на масива. Трябва ръчно да го давате. И вие не можете ръчно да премине в целия масив, защото вие сте просто преминава през референтния и не може да е в размер от референтната. Добре. Така че сега ние искаме да се изпълни това, което беше обяснено преди. Можете да работите върху него за една минута, и не е нужно да се притеснявате за получаване на всичко перфектно 100% работа. Просто напишете половината pseudocode за това как смятате, че тя трябва да работи. Добре. Не е нужно да бъдат напълно готови с тази все още. Но има ли някой да се чувства комфортно с това, което те са толкова далеч, като нещо, което можем да работим заедно? Някой иска ли доброволец? Или ще избере произволно. То не трябва да бъде от всяка мярка, но нещо, което може да променя в работно състояние. [Ученик] Разбира се. >> Добре. Така че може да ви спести преразглеждане, като кликнете върху малката икона Save. Ти си Ramya, нали? >> Студент Да. >> Bowden Добре. Така че сега мога да видите преразглеждане и всеки може да тегли до ревизията. И тук имаме - Добре. Така Ramya отиде с рекурсивно решение, което определено е приемливо решение. Има два начина, които можете да направите на този проблем. Можете да го направите итеративно или рекурсивно. Повечето проблеми, които срещнете, че може да се направи рекурсивно може да се извършва итеративно. Така че тук сме го правили рекурсивно. Някой иска ли да се дефинира какво означава да се направи функция рекурсивно? [Ученик] Когато имате функция се наричат и след това се нарича, докато излезе с верни и истинни. >> Да. Рекурсивна функция е само една функция, която нарича себе си. Има три неща, които на рекурсивна функция, трябва да имат. Първият е очевидно, че нарича себе си. Вторият е в основата случай. Така че в някакъв момент тази функция трябва да престане да се обадите, и това е, което базовия модел. Така че тук ние знаем, че трябва да спрем, ние трябва да дадем в нашето търсене когато старт се равнява на края - и ние ще отидем какво означава това. Но в крайна сметка, последното нещо, което е важно за рекурсивни функции: функциите по някакъв начин трябва да се обърне към базов. Както и ако не сте всъщност актуализиране нещо, когато правят втори рекурсивно повикване, ако сте буквално извикване на функция отново със същите аргументи и без глобални променливи са се променили или нещо подобно, никога няма да постигнете случай база, в случай, че е лошо. Това ще бъде безкрайна рекурсия и препълване на стека. Но тук ние виждаме, че актуализацията се случва, тъй като ние сме актуализиране започнете + края / 2, актуализиране на края аргумент тук, ние сме актуализиране началото аргумент тук. Така че във всички рекурсивни повиквания са в процес на осъвременяване на нещо. Добре. Искате ли да се разходим из вашето решение? >> Разбира се. Аз съм с SearchHelp, така че всеки път, когато правя тази функция повикване Имам началото на мястото, където Търся в масива и в края на мястото, където Търся масива. На всяка стъпка, където казват, че е средата елемент, който е края на началото + / 2, е, че равно на това, което търсим? И ако е така, тогава ние го намери, и аз предполагам, че тя започва да се нивата на рекурсия. И ако това не е вярно, тогава ние се провери дали, че средната стойност на масива е твърде голям, в този случай ние в лявата половина на масива, като от началото до средата индекс. А иначе правим края на 1/2. [Bowden Добре. Това звучи добре. Добре, така че няколко неща, и всъщност, това е много високо ниво, което че никога няма да трябва да знаете за този курс, но това е вярно. Рекурсивни функции, вие винаги ще чуете, че те са лоша сделка , защото ако рекурсивно наричат ​​себе си твърде много пъти, можете да получите препълване на стека тъй като, както казах и преди, всяка функция получава своя собствена рамка стека. Така че всеки разговор на рекурсивна функция получава своя собствена рамка стека. Така че, ако направите 1000 рекурсивни повиквания, можете да получите 1000 стека рамки, и бързо да доведе до твърде много рамки стека и нещата просто се прекъсне. Така че това е защо рекурсивни функции като цяло са лоши. Но е хубаво подмножество на рекурсивни функции, наречени опашката рекурсивни функции, и това се случва да бъде пример на една, където, ако компилатор забелязва това и тя трябва да, мисля, че звъня, ако преминете на O2 флаг след това ще забележите, това е опашката рекурсивно и да направим нещата добре. Тя ще използва един и същи кадър стак отново и отново за всяко рекурсивно повикване. И така, тъй като вие използвате един и същ кадър стак, не е нужно да се притеснявате за някога стека прелива, и в същото време, както ти каза преди, където някога се върнете вярно, то тогава трябва да върне всички тези стека рамки и 10 призив към SearchHelp трябва да се върне към 9, трябва да се върне до 8-ми. Така че това не трябва да се случи, когато функции са опашката рекурсивна. И така, това, което прави тази функция опашката рекурсивен е известие, че за дадена покана да searchHelp рекурсивно повикване, което прави, е това, което е връщане. Така в първата покана за SearchHelp, или незабавно да върне невярна, незабавно да върне вярно, или ние правим рекурсивен призив към SearchHelp когато Връщаме е това, че се завръща повикване. И не можем да направим това, ако сме направили нещо като Int X = SearchHelp, връщане х * 2, просто някаква случайна промяна. Така че сега този рекурсивно повикване, вътр х = SearchHelp рекурсивно повикване, вече не е опашка рекурсивна, защото всъщност няма да се върне обратно към предишния кадър на стека, така че, че предишната покана на функцията след това може да се направи нещо с върнатата стойност. Така че това не е опашка рекурсивен, но това, което сме имали преди е добре опашката рекурсивна. Да. [Ученик] Ако не бъдат проверени втория случай база първа защото може да има ситуация, където, когато го преминеш аргумент сте започнете = край, но те са стойността на иглата. Въпросът не е да бягаме в случай, когато краят е стойността на иглата или започнете = край, подходящо, започнете = край и не сте действително проверените още, че определена стойност, след това започнете + края / 2 е просто ще бъде една и съща стойност. Но ние сме се завърнали вече невярна и ние всъщност никога не проверява стойността. Така че най-малкото, при първата покана, ако размера е 0, тогава ние искаме да се върне фалшиви. Но ако размер е 1, а след това започва да тече не се случва на равно края и най-малко ще провери един елемент. Но мисля, че сте прав в това, че можем да се окажете в случай, когато започнете + края / 2, начало в крайна сметка е същият като края на старт + / 2, но ние никога не действително проверените този елемент. Така че, ако ние първо проверете средата елемент стойността търсим, тогава можем да връщат незабавно вярно. Иначе, ако те са равни, тогава няма смисъл да продължаваме тъй като ние просто ще се актуализира на случаите, когато сме на един елемент от масива. Ако това един елемент не е това, което търсим, тогава всичко е наред. Да. [Ученик] Работата е там, че след като размер е по-голям от броя на елементите в масива, вече има офсет - >> Така автоматично ще [Ученик] Кажете, ако масива е размер 0, тогава SearchHelp действително ще провери купа сено 0 по първата покана. Масив има размер 0, така че 0 е - >> Да. Има и нещо друго, че тя може да е добра. Нека да помислим. Така че, ако масива е 10 елемента и средата, отиваме да се провери е индекс 5, така че ние сме проверка на 5, и нека кажем, че стойността е по-малка. Така че ние сме хвърлят всичко от 5 нататък. Така че започнете + края / 2 ще бъде нашият нов края, Така че, да, тя винаги ще остане след края на масива. Ако това е случаят, ако тя е равна или странно, тогава ние ще провери, да речем, 4, но все още изхвърлите Така че да, краят е винаги ще бъде извън ефективния края на масива. Така елементи, ние се фокусираме върху края винаги ще бъде след това. И така, ако началото някога прави равен края, ние сме в масив с размер 0. Другото нещо, което си мислех е, че са в процес на осъвременяване започнат да се започне + края / 2, така че това е случай, че аз съм като проблем, когато започнете + края / 2 е елемент, който ние сме проверка. Да кажем, че този 10-елемент на масива. Както и да е. Така че започнете + края / 2 ще бъде нещо подобно на това, и ако това не е стойността, да кажем че искате да актуализирате. Стойност е по-голяма, така че искаме да разгледаме в тази половина на масива. Така че, как сме актуализиране началото, ние сме актуализиране старт на този елемент. Но това все още може да работи, или най-малкото, да не започват + края / 2 + 1. [Ученик] Не е нужно да се започне + края чува] >> Да. Ние вече проверява този елемент и знам, че не е един търсим. Така че ние не трябва да актуализирате старт на този елемент. Ние можем само да я пропуснете и актуализира започне, за да бъде този елемент. И има ли случай, нека кажем, че това беше края, така че след това начало би било това, започнете + края / 2 ще бъде това, започнете + края - Да, мисля, че може да свърши в безкрайна рекурсия. Да кажем, че това е просто един масив с размер 2 или масив с размер 1. Мисля, че това ще свърши работа. Така че в момента, началото е този елемент и в края е една отвъд него. Така елемент, който отива да се провери, е тази, и тогава, когато ние актуализираме началото, ние актуализирате започнат да се 0 + 1/2, която ще ни върна с началото този елемент. Така че ние сме проверка на един и същ елемент отново и отново. Така че това е случай, където всеки рекурсивно повикване, трябва да актуализират нещо. Така че ние трябва да направим края на старт + / 2 + 1, или пък има случай където ние всъщност не сме актуализиране начало. Всеки видя това? Добре. Дали някой има въпроси относно този разтвор или повече коментари? Добре. Дали някой има един повтарящ се решение, което всички ние можем да погледнем? Ли всички ние го направи рекурсивно? Или и аз предполагам, ако нейните отвори, тогава може да има преимущество предишната си. Прави това автоматично спаси? Аз не съм положително. Дали някой има повтарящ се? Ние можем да минеш през нея заедно, ако не. Идеята е да бъде същата. Повтарящ решение. Отиваме да искат всъщност да направи същата идея там, където искаме да следите на новия края на масива и ново начало на масива и не, че отново и отново. И ако това, което сме следене като началото и края някога се пресичат, тогава не го намерите и можем да се върнем фалшива. И така, как да го направя? Всеки, който има предложения или кодове за мен да спра? [Ученик] Да цикъл, докато >> Да. Вие ще искате да направите една линия. Имахте ли код мога да спра, или това, което щеше да предложи? [Ученик] Мисля, че да. >> Добре. Това прави нещата по-лесни. Какво ти беше името? [Ученик] Лукас. Преразглеждане 1. Добре. Нисък е това, което ние наричаме започне преди. Не е съвсем това, което ние наричаме края преди. Всъщност, краят е в рамките на масива. Това е елемент, който трябва да се обмисли. Толкова ниско е 0, е размерът на масива - 1, и сега ние се примка, и ние сме проверка - Предполагам, че може да минеш през нея. Какво е вашето мислене през това? Разходка нас чрез кода си. [Ученик] Разбира се. Погледни в купа сено стойността в средата и я сравни с игла. Така че, ако това е по-голяма от иглата, а след това искате - О, всъщност, че трябва да бъде назад. Вие ще искате да изхвърлите дясната половина, и така да, това трябва да е начин. [Bowden] Така че това трябва да бъде по-малко? Е, че това, което каза? >> Студент Да. [Bowden Добре. По-малко. Така че, ако това, което търсим, е по-малък от това, което ние искаме, тогава да, ние искаме да изхвърлите лявата половина, което означава, че са в процес на осъвременяване на всичко, което се обмисля чрез преместване от ниска към правото на масива. Това изглежда добре. Мисля, че има същия проблем, който ние казахме на предишния, където при ниска е 0 и е една, а след това ниско + нагоре / 2 се ще да бъде едно и също нещо отново. И дори ако това не е така, тя все още е по-ефективно, най-малкото просто да изхвърлите елемент ние просто погледна, на която сме сигурни, че не е наред. Толкова ниско + нагоре / 2 + 1 - >> [ученик] Това трябва да бъде по друг начин. [Bowden] Или това трябва да бъде една, а другият трябва да бъде + 1. [Ученик] И трябва да има двоен знак за равенство. >> Bowden Да. [Ученик] Да. Добре. И най-накрая, че сега имаме това + 1 - 1 нещо, е - може да не е - това е някога е възможно за ниска, за да се свърши с стойност по-голяма, отколкото до? Мисля, че единственият начин, по който може да се случи - Възможно ли е? >> [Ученик] Не знам. Но ако става отрязва и след това получава минус 1 и след това - >> Да. [Ученик] вероятно ще се побъркани. Мисля, че трябва да бъде добър, само защото , за да свърши по-ниско, те ще трябва да бъдат равни, мисля. Но ако те са равни, тогава ние не би направил примка време да започнем с и ние просто щеше да се върне стойността. Така че аз мисля, че сме добре. Забележете, че въпреки че този проблем вече не е рекурсивен, същия вид идеи прилага, когато можем да видим как това толкова лесно се поддава на рекурсивно решение от факта, че ние просто актуализиране на индексите отново и отново, ние сме прави проблема по-малък и по-малък, ние се фокусираме върху подмножество на масива. [Ученик] Ако ниско е 0 и нагоре е едно, и двамата щели да е 0 + 1/2, който ще отиде на 0, и след това ще бъде + 1, ще бъде - 1. [Ученик] Къде проверка на половете? Както и ако средата е всъщност игла? Ние не сме прави в момента? О! Ако it's - Да. Не можем просто да направи тест тук, защото нека кажем, че първият средата - [Ученик] всъщност Не изхвърляйте граница. Така че, ако изхвърлите граница, ще трябва да го проверите първи или каквото. Ah. Да. >> Студент Да. Така че сега ние сме изхвърлили ние в момента погледна, което означава, че сега трябва да има (купа сено (ниско + Up) / 2] == игла), а след това можем да се върнат вярно. И дали сложих друг или просто, ако тя буквално означава едно и също нещо защото това щеше да се върне вярно. Така че аз ще сложа друг, ако, но това няма значение. Иначе, ако това, иначе това, и това е нещо, което правя дори ако това е случая, когато всичко е добре тук, като ниско никога не може да бъде по-голяма, отколкото нагоре, че не си струва разсъждения дали това е вярно. Така че може да се каже, докато ниско е по-малка или равна на или по време на ниско е по-малко от така че ако те са винаги равна или по-ниска случва да мине, тогава можем да се откъснем от този цикъл. Въпроси, се отнася коментари? Добре. Това изглежда добре. Сега искаме да направим вид. Ако отидем в моята втора ревизия, виждаме същите тези числа, но сега те вече не са в подредени цел. И ние искаме да приложи вид с помощта на всеки алгоритъм в O N дневник н. Така че, който алгоритъм мислиш ли, че трябва да прилагат тук? >> Студент Merge вид. [Bowden Да. Обединяване вид е O (N дневник н), така че това е, което ние ще направим. И проблемът ще бъде доста сходен, , където лесно се поддава на рекурсивно решение. Можем също така да излезе с един повтарящ решение, ако искаме, но рекурсия ще бъде по-лесно тук и ние трябва да направим рекурсия. Предполагам, че ние ще ходим първият вид сливане, въпреки че вече е прекрасно видео на вид сливане. [Смях] Така се слеят вид има - аз губя толкова много на този документ. О, има само едно ляво. Така се слеят. О, 1, 3, 5. Добре. Обединяване отнема две отделни масиви. Самостоятелно тези два масива двете са сортирани. Така че този масив, 1, 3, 5, сортирани. Този масив, 0, 2, 4, сортирани. Сега какво сливане трябва да направите е да ги комбинирате в един масив, който сам по себе си е сортиран. Така че ние искаме масив с размер 6, че ще има тези елементи вътре в него подредени за. И така, можем да се възползваме от факта, че тези два масива са подредени да направите това в линейното време, линейното време смисъл, ако този масив е размер х и това е размер г., тогава общият алгоритъм трябва да бъде O (X + Y). Добре. Така предложения. [Ученик] Можем ли да започне от ляво? Така че ще постави 0 надолу първа и след това на 1 и след това тук сте на две. Така че това е нещо като имате раздел, който се движи надясно. >> Bowden Да. За двете тези масиви, ако ние просто се съсредоточи върху най-лявата елемент. Тъй като двата масива са подредени, ние знаем, че тези два елемента са най-малките елементи в двата масива. Така че това означава, че една от тези два елемента трябва да бъде най-малкият елемент в обединената ни масив. Просто така се случи, че най-малкото е на този път. Така че ние 0, поставете го на ляво, защото 0 е по-малко от 1, така че отделете 0, поставете го в първи нашата позиция, и тогава ще актуализира тази да се съсредоточи върху първия елемент. И сега ние повтаряме. Така че сега ние сравни 2 и 1. 1 е по-малък, така че ние ще вмъкнете 1. Ние обновяваме този указател да сочи към този човек. Сега ще го направя отново, така че 2. Това ще обнови, да сравните тези два, три. Това актуализации, 4 и 5. Така че това е сливане. Тя трябва да бъде доста очевидно, че това е линейното време, тъй като ние просто отидете веднъж през всеки елемент. И това е най-голямата стъпка към прилагането на сливане вид прави това. И това не е толкова трудно. Няколко неща, които трябва да се притесняваш е, нека кажем, че сливането 1, 2, 3, 4, 5, 6. В този случай ние в крайна сметка в сценарий, при който това ще бъде по-малък, тогава ние се актуализира тази показалеца, това ще бъде по-малък, актуализира, това е по-малък, а сега трябва да признаем, , когато сте се изчерпи на елементите да се сравни с. Тъй като вече са използвали целия този масив, всичко в този масив се сега просто се вмъква в тук. Така че, ако някога сме в точката, в която един от нашите масиви вече е напълно слети, тогава ние просто предприемат всички елементи на другата масив и ги поставете в края на масива. Така че ние можем просто поставете 4, 5, 6. Добре. Това е едно нещо, което трябва да внимавате за. Прилагане, че трябва да бъде стъпка 1. Обединяване сортирате след това на базата на това, че е две стъпки, два глупави стъпки. Нека просто да даде този масив. Така че се сливат вид, стъпка 1 е да рекурсивно разбие масива на две половини. Така разделя този масив на две половини. Сега имаме 4, 15, 16, 50 и 8, 23, 42, 108. И сега ние го правим отново и се разделя на две половини. Аз просто ще го направя от тази страна. Така че, 4, 15 и 16, 50. Ние ще направим същото нещо тук. И сега ние отново го разделя на две половини. И ние имаме 4, 15, 16, 50. Така че това е случай на нашата база. След като масиви са с размер 1, след това спираме с разделянето на две половини. Сега какво ще правим с това? Ние в крайна сметка това също ще се разделят на 8, 23, 42 и 108. Така че сега сме на този етап, сега стъпка две от вид сливане е просто сливане на двойки, за да списъците. Така че ние искаме да се слеят тези. Ние просто се обадете се слеят. Съединяването ще се върне в сортират за. 4, 15. Сега искаме да се слеят, и че ще се върне списък с подредени за 16 и 50. Ние се сливат тези - не мога да пиша - 8, 23 и 42, 108. Така че ние имаме обединени двойки веднъж. Сега ние просто се сливат отново. Забележете, че всеки един от тези списъци се сортират по себе си, и тогава ние може просто да се слеят тези списъци, за да получите списък с размер 4, които се сортират и да се слеят тези две списъци, за да получите списък с размер 4, които се сортират. И накрая, да обедините тези два списъка с размер 4, за да се получи един списък с размер 8, които се сортират. Така че, за да се види, че това е като цяло N дневник N, ние вече видяхме, че сливането е линейна, така че когато ние се занимават с обединяването на тези, така, като общата стойност на сливане за тези два списъка е само на 2, защото Или добре, това е О N, но н тук е само тези два елемента, така че това е 2. И тези 2 ще бъде 2 и тези 2 ще бъде на 2 и тези 2 ще бъде 2, така цяла слива, че ние трябва да се направи, ние в крайна сметка прави н. Като 2 + 2 + 2 + 2 е 8, което е н така че разходите за сливане в тази група е N. И тогава едно и също нещо тук. Ще се слеят тези две, след това тези две, и индивидуално това сливане ще отнеме четири операции, това сливане ще отнеме четири операции, но отново, между всички тези, ние стигаме до обединяване н общите неща, и така че тази стъпка н. И така, всяко ниво отнема н елементи се сливат. И колко нива са там? На всяко ниво, масив расте с размер 2. Тук нашите масиви са с размер 1, тук те са с размер 2, тук те са с размер 4 и в крайна сметка, те са с размер 8. Така че, тъй като тя се удвоява, там ще да бъде общо на дневника N от тези нива. Така че с дневника н нива, всяко ниво, като N общите операции, Вход N N алгоритъм. Въпроси? Има хора, които вече постигнатия напредък за това как да приложат тази? Има ли някой вече в състояние, когато мога просто да спра своя код? Мога да дам минути. Това ще бъде по-дълъг. Аз силно препоръчвам повтори - Не е нужно да се направи рекурсия за сливане защото, за да се направи рекурсия за сливане, вие ще трябва да преминат през куп различни размери. Можете, но това е досадно. Но рекурсия за себе си вид е доста лесно. Просто буквално се обадя вид на лявата половина, нещо от дясната половина. Добре. Всеки, който има всичко, което може да тегли още? Или пък аз ще дам минути. Добре. Всеки, който има нещо, което може да работи с? Или пък ние просто ще работим с това и след това разгънете от там. Всеки, който има повече от това, че мога да спра? [Ученик] Да. Можете да дръпнете моя. >> Добре. Да! [Ученик] Имаше много условия. >> О, по дяволите. Можеш ли - [Ученик] трябва да го спаси. >> Да. Така че сме направили направи сливане отделно. О, но това не е толкова зле. Добре. Така вид сам по себе си е Обаждам mergeSortHelp. Обяснете ни какво mergeSortHelp. [Ученик] MergeSortHelp доста струва две основни стъпки, която е да сортирате всяка половина на масива и след това да се слеят двете от тях. [Bowden Добре, така че ми даде втори. Мисля, че това - >> [ученик] трябва да Да. Аз съм липсва нещо. В сливане, осъзнавам, че трябва да се създаде нов масив защото не може да го направи на място. >> Да. Вие не може. Правилно. [Ученик] създам нов масив. Забравих в края на документи за повторно промените. Добре. Имаме нужда от нов масив. Сливат в нещо, това е почти винаги вярно. Част от разходите за по-добър алгоритъм време-мъдър почти винаги се налага да използвате малко повече памет. Така че тук, без значение как го правиш слеят вид, неизбежно ще трябва да използвате някои допълнителни памет. Той или тя създава нов масив. И тогава ти казват, че в крайна сметка ние просто трябва да копирате нов масив в оригиналния масив. [Ученик] Мисля, че да, да. Аз не знам дали това работи в условията на преброяване чрез позоваване или каквото - Да, той ще работи. >> Студент Добре. Знаете ли, пуснете? >> [Ученик] Не, не още. >> Добре. Опитайте да го изпълняват, и после ще говорим за това за секунда. [Ученик] трябва да разполага с всички функционални прототипи и всичко, обаче, нали? Прототипа на функция. О, имате предвид, като - Да. Сортирай се обажда mergeSortHelp. Така че, за да вид да се обадя mergeSortHelp mergeSortHelp трябва да са били определени преди вид или ние просто трябва прототипа. Просто копирайте и поставете този. И по същия начин, mergeSortHelp се обажда се сливат, но сливане все още не е определена, така че може просто да mergeSortHelp знам , че това е, което се сливат ще изглежда, и това е всичко. Така mergeSortHelp. Имаме проблем тук, където ние нямаме база случай. MergeSortHelp е рекурсивен, така че всяка рекурсивна функция ще се нуждаят от някаква база случай, за да знае кога да спре рекурсивно самия призовава. Какво е нашата база случай ще бъде тук? Да. [Ученик] Ако размерът е 1? >> Bowden Да. Така че, както видяхме там, спряхме разделяне масиви След като имаме в масиви с размер 1, което неминуемо се сортирани. Така че, ако размер е равен на 1, ние знаем, вече е сортиран масив, така че можем само да се върне. Забележете, че е нищожен, така че ние не връща нищо специално, ние просто се върне. Добре. Така че това е случай на нашата база. Предполагам, че нашия случай база също може да бъде, ако се случи да се сливане масив с размер 0, най-вероятно искате да спрете в някакъв момент, така че ние може просто да се каже, размер по-малко от два или по-малко или равно на 1 , така че това ще работи за всеки масив. Добре. Така че това е случай на нашата база. Сега искат да ни преведе през сливат? Какво означават всички тези случаи? Тук, ние просто правим една и съща идея, - [Ученик] трябва да се минава размер с всички обаждания mergeSortHelp. Добавих размер като допълнителен първични избори и това не е там, като Размерът / 2. [Bowden] О, Размерът / 2, Размерът / 2. >> [Ученик] Да, а също и по-горе функция, както и. [Bowden] тук? >> [Ученик] Само размер. >> Bowden О Размер размер? >> Студент Да. [Bowden Добре. Нека да помисля за секунда. Да се ​​натъкнем на проблем? Ние сме винаги лечение на ляво като 0. >> [Ученик] Не Това е грешно. Извинете. Тя трябва да бъде началото. Да. [Bowden Добре. Харесва ми, че по-добре. И край. Добре. Така че сега иска да ни преведе през сливат? >> Студент Добре. Аз съм просто се разхождах из този нов масив, че съм създал. Нейният размер е размерът на частта на масива, че ние искаме да се сортират и се опитва да намери елемент, който трябва да се постави в нова стъпка масив. Така че, за да направите това, първо аз съм проверка дали в лявата половина на масива продължава да има повече елементи, и ако това не стане, тогава ще сляза, че друго условие, което просто казва добре, тя трябва да бъде в правилната масив, и ние ще сложим, че в текущия индекс на newArray. И тогава по друг начин, аз съм проверка дали дясната страна на масива е също завърши, в този случай аз съм сложил в ляво. Това всъщност може да не е необходимо. Не съм сигурен. Но така или иначе, а другите двама проверка коя от двете е по-малък в лявото или дясното. А също и във всеки случай, аз съм увеличаване в зависимост от това кое контейнер нарастване. [Bowden Добре. Това изглежда добре. Някой има ли коментари или притеснения или въпроси? Така че четирите дела, които трябва да доведе нещата в просто е - или тя изглежда като пет - но ние трябва да се помисли дали лявата масив е свършила неща, които трябва да се слеят, дали правото масив е свършила неща, които трябва да се слеят - Сочи в нищото. Така че,, дали лявата масив е свършила на нещата или правото масив е да се изчерпят неща. Това са два случая. Ние също се нуждаят от тривиален случай дали лявата е по-малко от правилното нещо. След това ние искаме да изберете лявата нещо. Това са случаи. Така че това е правилно, така че е това. Array напусна. Това е 1, 2, 3. Добре. Така че, да, това са четирите неща, които бихме искали да направите. И ние няма да отидем един повтарящ решение. Аз не бих препоръчал - Обединяване вид е пример за функция, която е не опашка рекурсивни не е лесно да се направи го опашката рекурсивен, но и че не е много лесно да го повтарящ се. Това е много лесно. Този изпълнението на вид сливане, сливат, без значение какво правиш, ти започваш да се изгради сливане. Така че се слеят вид, построен на върха на сливане рекурсивно е само тези три линии. Итеративно, тя е по-досадно и по-трудно да се мисли за. Но забележете, че не е опашката рекурсивно тъй като mergeSortHelp - когато нарича себе си - тя все още трябва да направи неща, след това рекурсивни връща повиквания. Така че тази рамка стек трябва да продължи да съществува дори и след извикването това. И тогава, когато ти се обадя, рамката стека трябва да продължи да съществува защото дори и след това разговорът, ние все още трябва да се слеят. И това е nontrivial да направи тази опашка рекурсивно. Въпроси? Добре. Така че се връщам да сортирате - О, има две неща, които искате да покажете. Добре. Връщайки се към вид, ние ще направим това бързо. Или търси. Сортирай? Сортиране. Да. Ако се върнем към началото на вид. Ние искаме да създадем алгоритъм, който сортира масив, използвайки всеки алгоритъм О н. Е, как е възможно това? Дали някой има всякакъв вид - Намекна преди в Ако сме на път да подобри от дневник н н О N, сме подобрили нашия алгоритъм време-мъдър, което означава, какво ще трябва да направите, за да компенсирате това? [Ученик] Space. >> Да. Отиваме да се използва от повече пространство. И дори не само повече пространство, това е експоненциално по-голямо пространство. Така че аз мисля, че този вид алгоритъм е псевдо нещо, псевдо polynom псевдо - аз не мога да си спомня. Псевдо нещо. Но това е, защото ние трябва да използваме толкова много пространство , че това е постижимо, но не е реалистично. И как ще се постигне това? Можем да постигнем това, ако ние гарантираме, че всеки отделен елемент в масива е под определен размер. Така че нека просто кажем, че размерът е 200, всеки елемент в масив е под размер 200. И това всъщност е много реалистично. Можете много лесно да имат множество, че знаете всичко в него ще бъде по-малко от известен брой. Както, ако имате някаква огромна вектор или нещо но вие знаете, всичко ще бъде между 0 и 5, след това тя ще бъде значително по-бързо да се направи това. И обречената на всеки от елементите е 5, така че тази граница, която е колко памет ти започваш да се използва. Така граница е 200. На теория винаги има граница, тъй като число може да бъде само до 4 млрд. евро, но това е нереалистично, тъй като тогава ние ще се използва пространството по нареждане от 4 милиарда. Така че това е нереалистично. Но тук ние ще кажем нашата граница е 200. Трик, за да го правиш в О н е, че друг масив наречен обвинения в размер ОБВЪРЗАНИ. Така че, всъщност, това е пряк път - Аз всъщност не знам дали звъня прави това. Но в GCC най-малкото - Аз съм предположи звъня го прави - това просто ще се инициализира целия масив да бъде 0s. Така че, ако не искате да направите това, тогава бих могъл отделно направя за (INT I = 0; I <вързан, I + +) и броя на [] = 0; Така че сега всичко се инициализира с 0. Обхождане на моя масив, и това, което правя, е, че аз съм преброяване на броя на всеки - Нека тук. Имаме 4, 15, 16, 50, 8, 23, 42, 108. Това разчитам е броят на срещания на всеки от тези елементи. Нека действително добавите още няколко тук с някои се повтаря. Така стойността имаме тук, стойността на които ще бъде масив [I]. Така стойност може да бъде 4 или 8 или каквото. И сега съм брои колко от тази стойност съм виждал, така се брои [Вал] + +; След като това е направено, броя ще изглежда нещо като 0001. Да не са напразни Вал] - ОБВЪРЗАНИ + 1. Сега това е само да се отчита факта, че започва от 0. Така че, ако 200 ще бъде нашият най-голям брой, след това 0 до 200 е 201 неща. Така че се брои, тя ще изглежда като 00 001, защото имаме един 4. Тогава ще имаме 0001, където ще имаме 1 в 8-ия индекс на брой. Ще имаме два в 23-та индекс на брой. Ще имаме две в индекса на 42-рата брой. Така че ние можем да използваме брой. Така num_of_item = брой кръвни клетки [I]. И така, ако num_of_item е 2, това означава, че искаме да вмъкнем 2 на брой в нашата сортиран масив. Така че ние трябва да следим колко сме далеч в масива. Така индекс = 0. Array - аз просто ще го напиша. Има значение - масив [индекс + +] =; Е, че това, което искам? Мисля, че това, което искам. Да, това изглежда добре. Добре. Така че всички разбират каква е целта на моя брои масив е? Преброяване на броя на повторенията на всеки един от тези номера. Тогава аз съм итерации, което има значение масив, ItH позиция в масив на графовете е броят на е, че трябва да се появи в сортират масив. Ето защо броя на 4 ще бъде едно и обвинения в 8 ще бъде 1, броя от 23 ще бъде 2. Така че това е колко от тях искате да вмъкнете в сортират масив. Тогава аз просто правя това. Съм вмъкване num_of_item в сортират масив. Въпроси? И така, отново, това е линейното време, тъй като ние сме просто итерации през този път, но също така е линейна в това се случва да бъде, и така до голяма степен зависи от това, което ви обвързани. С граница на 200, което не е толкова зле. Ако вашата граница ще бъде 10 000, тогава това е малко по-лошо, но ако вашата граница ще бъде 4 млрд. евро, това е напълно нереалистично и този масив ще трябва да бъде на размер на 4 млрд. евро, което е нереалистично. Така че е това. Въпроси? [Чува студент отговор] >> Добре. Разбрах едно друго нещо, когато бяхме става чрез. Мисля, че проблемът е в Лукас и вероятно всеки един от тях сме виждали. Съвсем забравих. Единственото нещо, което исках да коментирам е, че когато сте се занимават с неща като индекси, никога не видите това, когато пишете за цикъл, но технически, когато сте се занимават с тези показатели, почти винаги трябва да се справят с неподписани числа. Причината за това е, когато си имаш работа с подписани числа, така че ако имате два подписани числа и да ги съберем и те в крайна сметка е твърде голям, тогава ще се окажете с отрицателно число. Така че това е цяло число преливане. Ако добавите 2 млрд. и 1 млрд., аз се окажете с отрицателен 1 млрд.. Числа работят на компютри. Така че проблемът с използването на Това е добре, освен ако ниска случва да бъде 2 милиарда и се случва да бъде 1 млрд. евро, , то това ще бъде Отрицателна 1 милиарда и след това отиваме да се разделят, че от 2 и в крайна сметка с отрицателен 500 000 000. Така че това е проблем само, ако се случи да се търсят чрез масив на милиарди неща. Но ако е ниско + до случва да прелее, тогава това е проблем. Веднага след като ги правят грозен, след това 2 млрд. плюс 1 млрд. 3 млрд. евро. 3 милиарда евро, разделен на две, е 1.5 млрд. евро. Така че веднага щом те са грозен, всичко е перфектно. И така, това също е проблем, когато пишете за вериги, и всъщност, това вероятно го прави автоматично. Тя всъщност ще ти крещя. Така че, ако този брой е твърде голям, за да бъде само цяло число, но тя ще се вмести в неподписано цяло число, тя ще крещи на вас, така че защо никога не сте наистина се сблъскате с проблема. Можете да видите, че индексът никога няма да бъде отрицателен, и така, когато сте итерации над масив, почти винаги може да се каже, грозен Int аз, но вие наистина не трябва да. Нещата ще работим почти също толкова добре. Добре. [Шепне] Колко е часът? Последното нещо, което исках да покажа и аз просто ще го направя наистина бързо. Знаеш как сме # определят, така че можем да # определят MAX 5 или нещо такова? Нека не правим MAX. # Определят обвързана като 200. Това е, което ние направихме преди. Това определя константа, която е просто ще трябва да се копира и да се постави където и да се случи, да напишете ОБВЪРЗАНИ. Така че ние всъщност може да направи повече с # определя. Ние можем да # определят функции. Те не са наистина функции, но ние ще ги наричаме функции. Един пример ще бъде нещо като MAX (X, Y) се дефинира като (X > В идеалния случай, 14. Въпросът е, че как хеш определя работа, не забравяйте, това е буквално копиране и поставяне почти всичко, така че това ще трябва да се тълкува като е три по-малко от 1 плюс шест, два пъти едно плюс 6, 2 пъти 3. Така че поради тази причина почти винаги ще приключи всичко, което е в скоби. Всяка променлива, почти винаги ще приключи в скоби. Има случаи, в които не трябва да, като аз знам, че не е нужно да направя това тук защото по-малко, отколкото е почти винаги ще работи, въпреки че не може дори да е истина. Ако има нещо нелепо като DOUBLE_MAX (1 == 2), това ще се заменя с три по-малко от 1 равен, е равно на 2, и така то тогава ще да направя три по-малко от 1, не които са равни на две който не е това, което искаме. Така че, за да се предотвратят всякакви предимство на операторите проблеми, винаги увийте в скоби. Добре. И това е всичко, 5:30. Ако имате някакви въпроси за pset, да ни уведомите. Тя трябва да бъде забавно, и хакер издание също е много по-реалистична от хакер издание на миналата година, така че ние се надяваме, че много от вас го опитам. Миналата година беше много поразителен. [CS50.TV]