[За възпроизвеждане на музика] Дъг LLOYD: ОК, така че най- този момент в хода, ние сме обхванати голяма част от основите на C. Ние знаем много за променливи, масиви, указатели, всички добри неща. Тези са всички видове вградени , за да видите като основите, но можем да направим повече, нали? Ние можем да комбинираме нещата заедно в интересни начини. И така, нека да направим това, нека да започнем за разклоняване на това, което ни дава C, и да започне да създадем собствен данни структури, използващи тези сграда блокове заедно, за да направят нещо наистина ценно, полезно. Един начин можем да направим това е да се говори за колекции. Така че досега сме имали един вид данни структура за представяне на колекции от искал ценности, сходни ценности. Това ще бъде масив. Имаме колекции от цели числа, или колекции от герои и така нататък. Конструкции също са нещо като данни структура за събиране на информация, но това не е за събиране на подобни ценности. Той обикновено се смесва различни типове данни заедно вътре в една кутия. Но това не е самата използва, за да верига заедно или да се свържете заедно подобна предмети, като масив. Масивите са страхотни за елемент погледнете нагоре, но изземване че е много трудно да вмъкнете в масив, освен ако не сме вмъкване самия край на този масив. И най-добрият пример имам за това е, сортиране чрез вмъкване. Ако си спомняте нашите видео при поставяне на сортиране, Имаше много Разходи, свързани с необходимостта да вземете елементи, и да ги пренасочат от пътя, за да се поберат нещо в средата на масива. Масивите също страдат от друга проблем, който е липсата на гъвкавост. Когато декларираме масив, ние се получи един изстрел в него. Имаме възможност да кажа, искам това много елементи. Може да е 100, може да да бъде 1000, тя може да бъде х където х е номер, който потребителят ни даде най-бързо или по команда линия. Но ние само се получи един изстрел в него, ние не се получи да се каже тогава, о, всъщност аз необходими 101, или имах нужда х плюс 20. Твърде късно, вече сме обявил масив, и ако искаме да получим 101 или х плюс 20, ние трябва да се декларират съвсем различен масив, копирате всички елементи на масива над, а след това имаме достатъчно. И какво, ако ние можем да грешим отново, това, което ако ние действително се нуждаят 102, или х плюс 40, ние трябва да направим това отново. Така че те са много непреклонни за преоразмеряване на нашите данни, но ако ние комбинираме заедно някои на основите, които вече сме Научих за указатели и структури, по-специално с помощта на динамична памет разпределение с изчистване, ние може да постави тези парчета заедно За да създадете нова данни structure-- а поединично свързан списък можем да say-- която ни позволява да растат и свие колекция от ценности и ние няма да има загуба на пространство. Така че отново, ние наричаме тази идея, това понятие, свързан списък. По-специално, в това видео ние сме Говорим за единично свързан списък, и след това друг видеоклип ще поговорим за двойно свързани списъци, които е само вариация на тема тук. Но едно единично свързан списък се състои от възли, възли са просто абстрактен term-- това е просто нещо, което наричам това е един вид структура, основно, аз съм? Просто ще го наречем node-- и това възел има двама членове или две полета. Тя има данни, обикновено число, символ плувка, или може да бъде друг вид информация че сте дефинирана с тип дефиниция. И тя съдържа указател към друг възел от същия тип. Така че ние имаме две неща вътре този възел, данни и показалец към друга възлова точка. И ако започнете да се визуализира това, можете да мислите за него като верига от възли, които са свързани заедно. Имаме първия възел, тя съдържа данни и указател на втората възлова точка, която съдържа данни и указател към трети възел. И така, това е защо ние го наричаме по- свързан списък, те са свързани помежду си. Какво прави този специален структура възел изглежда? Е, ако си спомняте от нашето видео на дефиниране на потребителски типове, с тип дефиниция, можем да определим и structure-- Типове определи структурата по този начин. tyepdef структура на sllist, а след това аз съм използване на думата стойност тук произволно да посочи всеки тип данни наистина. Може да се прехвърлят на цяло число или поплавък, бихте могли да имат каквото си искате. Това не е ограничена до само числа, или нещо подобно. Така стойност не е просто произволно тип данни, и след това указател до друг възел от същия тип. Сега там е малко улов тук с определяне на структура когато това е структура, самостоятелно справочно. Аз трябва да имат временен име за моята структура. В края на деня, в който ясно искате да го наречете SLL възел, това е в крайна сметка новите назове част от моето определение на типа, но не мога да използвам SLL възел в средата на тази. Причината е, че не съм създаден тип, наречен SLL възел докато не се удари тази крайна точка тук. До този момент, аз трябва да имам друг начин да се позове на този тип данни. И това е самостоятелно справочно тип данни. Тя; е тип данни на структура, която съдържа данни, и указател към друга структура от същия тип. Така че аз трябва да бъде в състояние да се позове този тип данни поне временно, така че да даде временно име на структура на sllist ми позволява да се каже след това искам указател към друга структура на sllist, една структура на sllist звезда, и след това след като съм завършил определението, Сега мога да се обадя на този тип SLL възел. Така че това е защо те видя там временно име тук, но постоянно име тук. Понякога може да видите дефиниции на структура, Например, които не са самостоятелно справочно, че не е нужно името на спецификатор тук. Тя просто ще кажа, typedef структура на, отворите фигурна скоба и след това да го определи. Но ако сте структура на е самостоятелно справочно, тъй като това е една, вие трябва да посочите временно наименование на типа. Но в крайна сметка, сега че ние сме направили това, ние можем просто да се отнасят до тези възли, тези възли, като SLL възли за целите на останалата част на този видеоклип. Добре, така че ние знаем как да се създаване на свързан списък възел. Ние знаем как да се определят свързан списък възел. Сега, ако ще да се започне ги използват за събиране на информация, има няколко операции ние Трябва да се разбере и да се работи. Ние трябва да знаем как да се създаде свързан списък от нищото. Ако няма списък вече, искаме да започнем една. Така че ние трябва да бъдем в състояние за създаване на свързан списък, ние трябва да се вероятно търсите през списъка с линк да се намери един елемент, който търсим. Ние трябва да бъдем в състояние да вмъкнете нови неща в списъка, ние искаме нашия списък, за да може да расте. И по същия начин, ние искаме да бъде в състояние да изтриете неща от нашия списък, ние искаме нашия списък, за да може да се свие. И в края на нашия програми, особено ако си спомняте, че ние сме динамично разпределяне на паметта за изграждане на тези списъци обикновено, ние искаме да освободим всички, че паметта когато сме готови да работи с него. И така, ние трябва да бъдем в състояние да изтриете Цялата свързан списък в един замах се провали. Така че нека да мине през Някои от тези операции и как можем да ги визуализира, говори в Псевдокод код конкретно. Така че ние искаме да създадем свързан списък, така че може би ние искате да дефинирате функция с този прототип. SLL възел звезда, създавате, и аз съм минаваща в един аргумент, някои произволни данни въведете отново, на произволен тип данни. Но аз съм returning-- тази функция трябва да върне при мене показалка, с единично списък свързана възел. Отново, ние се опитваме да създадем свързан списък от нищото, така че имам нужда указател към този списък, когато съм направил. Така че какви са включени тук стъпки? Е, първото нещо, което съм ще направя, е динамично разпредели пространство за нов възел. Отново, ние сме го създава от нищото въздух, така че ние трябва да изчистване място за него. И разбира се, веднага след като сме изчистване, ние винаги се уверете, че нашата pointer-- ние не се върна за нищожна. Защото, ако ние се опитваме и уважение нулев указател, отиваме имаше segfault и ние не искаме това. След това ние искаме да попълните в областта, ние искаме да се инициализира полето за стойност и инициализира следващото поле. И тогава ние искаме to-- в крайна сметка, тъй като функция прототип indicates-- искаме да се върне указател към SLL възел. Така че това, което направи тази прилича визуално? Ами, първо ние ще динамично разпредели пространство за нов SLL възел, така че ние malloc-- това е визуално представяне на възела ние току-що създадената. И ние се уверете, това не е null-- в този случай, на снимката няма да има показано, ако тя е нищожна, щяхме да свършат на паметта, така че сме добре да отида там. Така че сега сме към стъпка C, инициализира поле възли стойност. Е, въз основа на тази функция обадя аз съм с тук, Прилича Искам да премине в 6, Така че аз ще 6 в полето за стойност. Сега, инициализира следващото поле. Е, аз какво ще правя там, няма нищо, следващия, нали, това е единственото нещо в списъка. И така, какво е следващото нещо, което в списъка? Тя не трябва да сочи към нещо, нали. Няма нищо друго там, така че това, което е понятието, което знаем за това е nothing-- указатели към нищо? Тя трябва да бъде може би искаме да се сложи нулев указател там, и аз ще представлява нула показалеца като само една червена кутия, ние не можем да отиде по-нататък. Както ще видим малко по-късно, ние ще имаме в крайна сметка вериги от стрели свързване тези възли заедно, но когато ви удари червена кутия, това е нищожна, ние не можем да отиде по-нататък, това е края на списъка. И накрая, ние просто искаме да върне указател към този възел. Така че ние ще го наричаме нова, и ще се върне ново така може да се използва в каквото и функция го е създал. Така че там да отидем, Ние създадохме поединично списък свързана възел от нищото, и сега имаме списък можем да работим. Сега, нека да кажем вече има голяма верига, и ние искаме да се намери нещо в него. И ние искаме функция, която ще за да се върнете вярно или невярно, в зависимост за това дали съществува стойност в този списък. A функция прототип, или декларация за тази функция, може да изглежда като this-- BOOL намерите и След това ние искаме да премине в два аргумента. Първият, е указател към Първият елемент от свързан списък. Това всъщност е нещо, което ще Винаги искате да следите, и действително може да бъде нещо, което вие дори в глобална променлива. След като създадете списък, Вие винаги, винаги искате да следите на самото Първият елемент от списъка. По този начин можете да се обърнете към всички останали елементи от просто следвайки веригата, без да се налага да се поддържа указатели непокътнат до всеки един елемент. Трябва само да следите на първата един, ако всички те са оковани заедно. И тогава второто нещо ние сме преминаване отново е произволно some-- независимо от вида на данните, че сме търси там е вътре надявам се един от възли в списъка. Така че какви са стъпките? Ами, първото нещо, което правим, е ние създаваме напречна показалка посочвайки главата на списъци. Е, защо правим това, ние вече има указател към главата на списъци, защо просто не се движат, че един наоколо? Е, като току-що казах, това е наистина важно за нас винаги да следи за първи елемент в списъка. И така, това е действително по-добре да създадете копие на тази, и да използва това, за да се придвижват, така че ние никога не случайно се движат далеч, или ние винаги има указател в някакъв момент, че е точно на първия елемент на списъка. Така че по-добре е да се създаде втора такава, която ние използваме, за да се движат. Тогава ние просто сравни дали полето за стойността на този възел е това, което търсим, и ако това е Не, ние просто се премести към следващото възел. И ние продължаваме да правим това над, и отново, и отново, докато ние или намерите елемента, или ударим null-- сме достигнали края от списъка и то не е там. Това трябва да се надяваме, че камбаната на вас като просто линейно търсене, ние просто го репликира в с единична свързан списък структура вместо да се използва масив, за да го направя. Така че тук е един пример за с единична свързан списък. Това се състои от пет възли, а ние имаме указател към главата на списък, който се нарича списък. Първото нещо, което искам да направя е отново, да създавате, че пакетът показалка. Така че ние имаме сега два указатели тази точка на едно и също нещо. Сега, забележете, тук също, не го направих Трябва да изчистване на всяко пространство, за Trav. Не съм казал, Trav равнява изчистване нещо, този възел вече съществува, това пространство в паметта вече съществува. Така че всичко, аз съм всъщност прави е създаване на нов показалец към него. Аз не съм mallocing допълнителен пространство, просто трябва предприятието две указатели сочейки към едно и също нещо. Така е 2, което аз търся? Е, не, така че вместо да съм ще се премине към следващия. Така че основно бих казал, Trav Trav равнява следващата. Има 3 това, което търся, не. Така че аз продължавам да отидете чрез, докато накрая стигнем до 6, което е това, което търся на базата на повикването функция Имам най-отгоре там, и така че аз съм направил. Сега, какво ще стане ако елементът съм търсите, не е в списъка, е то все още продължава да работи? Е, забележите, че списъкът тук е едва доловимо различен, и това е друго нещо, което е важно с свързани списъци, не е нужно да се запази ги в специален ред. Можете, ако искате, но може би вече сте забелязали че ние не сме следенето какъв номер елемент ние сме на. И това е нещо като едно търговско че ние има със свързан списък стихове масиви, е то ние нямаме произволен достъп вече. Не можем просто да кажем, искам за да отидете на 0th елемент, или 6-ия елемент на моя масив, което мога да направя в масив. Не мога да кажа, че искам да отида до 0th елемент, или 6-тия елемент, или 25-ия елемент от моята свързан списък, че няма форум, свързани с тях. И така всъщност няма значение ако ние запазим нашия списък в ред. Ако искате да сте Със сигурност може, но има Няма причина, поради която те се нуждаят, за да да бъде запазена в произволен ред. Така че отново, нека се опитаме и 6 намерите в този списък. Е, ние започне в започващ, не намерим 6, и след това ние не продължаваме да намери 6, докато ние в крайна сметка стигна до тук. Така че точно сега TRAV точки до възела съдържаща 8, а шест не е там. Така че следващата стъпка ще бъде да преминете към следващото показалеца, така казват Trav Trav равнява следващата. Е, Trav следващия, посочено от червената кутия там, е нищожна. Така че има къде другаде да отидете, и така в този момент можем да заключим, че сме достигнали края на свързан списък, и 6 не е там. И щеше да се върне фалшиво в този случай. OK, как да вмъкнете нов възел в свързан списък? Така че ние сме били в състояние да създаде свързан списък от нищото, но най-вероятно искате да изгради верига, а не създаде един куп различни списъци. Ние искаме да имаме един списък, който има куп възли в нея, Не куп списъци с един възел. Така че ние не можем просто да продължите да използвате Създаване функция ние определено по-рано, сега ние искате да вмъкнете в един списък, който вече съществува. Така че този случай, ние ще да премине през два аргумента, показалеца на ръководителя на които свързан списък, който ние искаме да добавим. Отново, това е защо това е толкова важно, че ние винаги следите от него, защото това е единственият начин ние наистина трябва да се отнасят до целия списък е само от указател към първия елемент. Така че ние искаме да премине в указател към този първи елемент, и каквото можем стойност искате да добавите към списъка. И в крайна сметка тази функция ще се върне указател до новия ръководител на свързан списък. Какви са включени тук стъпки? Е, точно както при създаване, ние трябва да се разпределят динамично пространство за нов възел, и се уверете, сме сигурни, че не се изчерпи на паметта, отново, защото ние сме с помощта на изчистване. След това ние искаме да се пренесат и го поставете на възела, така увеличиха броя, каквото Вал е в възел. Искаме да въведете възел при началото на свързан списък. Има причина, че аз искате да направите това, и то Може би си заслужава да вземе втора да направите пауза във видеото тук, и си мисля за това, защо аз ще искам да вмъкнете в началото на свързан списък. Отново, аз споменах по-рано че това не е така наистина значение, ако искаме да я запазим в някоя ред, така че може би това е представа. А ти видя какво ще стане, ако ние Исках to-- или от само на секунда Преди, когато отивахме чрез търсене на вас можеше да види какво може да се се случи, ако ние се опитвахме за вмъкване в края на списъка. Тъй като ние не разполагаме с указател към края на списъка. Така че причината, поради която аз ще искам да вмъкнете в началото, е така, защото мога да го направя веднага. Имам показалеца в началото, и ние ще видим това в визуален в секунда. Но ако искате да вмъкнете в края, Трябва да започнем от самото начало, прекосяват целия път до край, а след това го халс нататък. Така че това би означавало, че вмъкване в края на списъка ще се превърне в о п операция, се връщам до нашата дискусия за изчислителна сложност. Тя ще се превърне в о п дейност, където е като списъкът има по-големи и по-големи, и по-големи, че ще стават все повече и по-трудно да халс нещо на края. Но тя винаги е много лесно да се халс нещо в началото, вие сте винаги в началото. И ние ще видим визуално на това отново. И тогава, след като сме готови, след като ние сме добавя нов възел, ние искаме да се върне нашия указател към новият шеф на свързан списък, който тъй като ние сме вмъкване в започващ, всъщност ще бъде указател към възела, ние току-що създадената. Нека да визуализираме това, защото мисля, че ще помогне. Така че тук е нашия списък, той се състои от четири елемента, един възел, съдържащи 15, който сочи към възел съдържащ 9, което точки на една възлова точка, съдържащи 13, който сочи към възел, съдържащ 10, която има нула показалка като следващото си показалеца така че това е края на списъка. Така че ние искаме да вмъкнете нов възел със стойността 12 в началото на тази списък, какво ще правим? Ами, първо ние изчистване пространство за възел, а след това ще се постави 12 в там. Така че сега сме достигнали решение точка, нали? Имаме няколко указатели, че бихме могли да се движи, които човек трябва да се движим напред? Трябва ли да се направи 12 точка до новият шеф на list-- или да ме извините, трябва да направим 12 сочи към старата начело на списъка? Или ако трябва да кажем, че списък сега започва в 12. Има разлика там, и ние ще разгледаме какво се случва и с двете в секунда. Но това води до чудесна тема за страничната лента, което е, че един от трудните неща, с свързани списъци е да се организира указателите в правилния ред. Ако се движите нещата в ред, можете да се окажете случайно orphaning останалата част от списъка. И тук е един пример за това. Така че нека да отидем с идеята of-- добре, ние току-що сте създали 12. Ние знаем, 12 ще бъде новият шеф на списъка, и така че защо да не можем просто да се движат показалеца на списъка към точка там. ОК, така че това е добре. Така че сега, когато прави 12 следващия момент? Искам да кажа, визуално можем да видим че ще точка 15, като хора това е наистина очевидно за нас. Как компютърът знае? Ние нямаме нищо сочейки към 15 вече, нали? Ние сме загубили всякаква способност да се отнасят до 15. Не можем да кажем нова стрелки следващите равни нещо, там няма нищо. В действителност, ние сме сираци останалата част от списъка по този начин, ние сме случайно счупен веригата. И ние със сигурност не искам да правя това. Така че нека да се върнем и да опитаме отново. Може би най-правилното нещо да направя е да се определят 12 следващата показалка до стария начело на списъка на първо място, След това можем да се движим в списъка свърши. И в действителност, че е правилния ред, че ние трябва да се следват, когато сме работа с единично свързан списък. Ние винаги искаме да свържете нов елемент в списъка, преди да вземете този вид Важна стъпка за промяна когато начело на списъка е свързан. Отново, това е като основно нещо, ние не искаме да губи представа за него. Така че ние искаме да се уверите, че всичко е прикован заедно, преди да продължим, че показалеца. И така, това ще бъде най-правилния ред, който е за свързване 12 до списъка след това казват, че списъкът започва с 12. Ако споменатите списъка започва в 12 и след това се опита да се свърже 12 в списъка, ние вече сме виждали какво се случва. Губим списъка по погрешка. ОК, така че още едно нещо, за да се говори за. Какво става, ако искаме да се отървем от цяла свързан списък наведнъж? Отново сме mallocing всичко това пространство, така и ние трябва да го освободи, когато сме готови. Така че сега ние искаме да изтриете цялата свързан списък. Е, какво искаме да направим? Ако сте достигнали нулевата показалеца, ние искат да се спре, в противен случай, просто да изтриете останалата част от списъка и след това ме освободи. Изтриване на останалата част от списъка, и след това освобождаване на текущия възел. Какво означава, че звучи като, каква техника има говорихме за по-рано ти звучи като? Изтриване на всички останали, а след това се върне и да изтриете мен. Това е рекурсия, което сме направили проблем е малко по-малък, ние сме като каза изтриете всички друго, след това можете да ме изтриете. И по-надолу по пътя, този възел Ще кажете, изтрийте всички останали. Но в крайна сметка ние ще стигнем до точка, където списъкът е нищожна, и това е нашата база случай. Така че нека да погледнем на това, и как това може да свърши работа. Така че тук е нашия списък, това е същото изброят бяхме просто говоря за, а има и стъпките. Има много текст тук, но надяваме визуализацията ще помогне. Така че ние have-- и аз също дръпна нашата стека рамки илюстрация от нашите видео на повикване стекове, и се надявам всичко това заедно ще ви покажа какво се случва. Така че тук е нашата Псевдокод код. Ако стигнем до нула показалка, спрете, в противен случай, изтриване на останалата част от списъка, След освобождаване на текущия възел. Така че точно сега, list-- показалеца, че ние сме минаваща през да унищожи пункта до 12. 12 не е нулев указател, така че сме ще изтрие останалата част от списъка. Какво се заличи почивка от нас участва? Е, това означава, вземане на призовавам да се унищожи, казвайки че 15 е началото на почивка на списъка искаме да унищожи. И така поканата да унищожи 12 е вид на изчакване. Той е замръзнала там, в очакване на призовавам да унищожи 15, за да продължи своята работа. Е, 15 не е нулев указател, и така че ще да кажа, всичко е наред, добре, изтриване на останалата част от списъка. Останалата част от списъка започва на 9, и така че ние просто ще изчакайте, докато не изтриете всичко, което неща, след това се върна и да изтриете мен. Ами 9 ще кажа, добре, Аз не съм нулев указател, така изтриете останалите в списъка от тук. И така се опита да унищожи 13. 13 казва, аз не съм нищожна показалеца, едно и също нещо, тя преминава отмятат. 10 не е нулев указател, 10 съдържа нулев указател, но 10 не е самата нищожна показалеца точно сега, и така той преминава долар също. И сега се изброят точки там, Наистина би желала да some-- ако имах повече пространство в изображението, тя би желала да някои случайни пространство че ние не знаем какво е то. Това е нищожна показалеца обаче, списъкът е буквално предприятието определя това е стойности нула. Тя посочи, че направо в червено каре. Стигнахме нулев указател, така че можем да спрем, и сме готови. И така, това лилаво конструкция е now-- в Начало на stack-- това е активната рамка, но това е направено. Ако сте достигнали нулев указател, спрете. Ние не правим нищо, ние не може да се освободи нулев указател, ние не изчистване всеки пространство, и така сме готови. Така че тази функция конструкция е разрушен, а ние resume-- ние оттам, откъдето тръгнахме с следващата най-високата, която е това тъмно синя рамка тук. Така че ние вземем точно там, където сме спрели. Ние заличава останалата част от списък вече, така че сега сме ще освободи сегашните възли. Така че сега можем да освободим този възел, а сега ние сме достигнали края на функцията. И така, тази функция конструкция е унищожена, и ние вземем в светло синьо един. Така че това says-- вече съм done-- изтриване на останалата част от списъка, така освободи текущия възел. И сега на жълтата рамка е обратно на върха на стека. И така, както виждате, ние сме сега унищожаване на списъка от дясно на ляво. Какво щеше да се случи, все пак, ако бяхме направили нещата по грешен начин? Точно както, когато ние се опитахме да добавят елемент. Ако сме побъркани веригата, ако е ние не се свържете указателите в правилния ред, ако ние Просто остави на първия елемент, ако ние просто освободил ръководител на списъка, сега ние Няма как да се отнася до останалата част от списъка. И така, ние ще трябва сираци всичко, щяхме да имаме това, което е нарича изтичане на памет. Ако си спомняте от нашето видео за динамично разпределение на паметта, това не е много хубаво нещо. Така че, както казах, има няколко операции че ние трябва да се използва за работа със свързан списък ефективно. И може би сте забелязали I пропусне една, изтриване на един елемент от свързано списък. Причината, че го направих е това е всъщност вид трудно да се мисли за това как да изтриете един елемент от поединично свързан списък. Ние трябва да бъдем в състояние да прескочим нещо в списъка, който означава да стигнем до point-- ние искате да изтриете този node-- но за да го направи, така че ние не губи всякаква информация, ние трябва да се свържете този възел тук, тук. Така че аз може би направил, че погрешно от визуална гледна точка. Така че ние сме в началото на нашата списък, ние сме осъществява чрез, ние искаме да изтриете този възел. Ако ние просто да го изтриете, ние сме разбити веригата. Този възел точно тук се отнася до всичко останало, тя съдържа в процеса от сега нататък. Така че това, което трябва да направим в действителност след като стигнем до тази точка, е, че трябва да се върнем назад една и свържете този възел към този възел, така че след това ние можем да изтриете този в средата. Но поединично свързани списъци не го правят дайте ни начин да се върнете назад. Така че ние трябва или да се запази две насоки, и да ги преместите сортиране на разстояние стъпка, един зад друга като отидем, или да получите до точка и след това да изпрати друг показалеца сам. И както можете да видите, това може да се получи малко разхвърлян. За щастие, ние имаме друг начин за разрешаване, които, когато говорим за двойно свързани списъци. Аз съм Дъг Лойд, това е CS50.