[Powered by Google Translate] [Проходження - Проблема Set 5] [Zamyla Chan - Гарвардський університет] [Це CS50. - CS50.TV] Добре. Привіт всім, і ласкаво просимо Покрокове керівництво 5. Pset5 є орфографічні помилки, в яких ми будемо робити перевірки орфографії. Перевірки орфографії є ​​надзвичайно важливими. Має це сталося з вами? Ви працюєте дуже, дуже копити на папір для зіткнення а потім все одно в кінцевому підсумку отримати дуже товариш світитися, як D або D = і все тому, що ви ліверна ковбаса спойлер кита широкий слово. Так, коректура ваші перці це питання, максимально імпотенції. Це проблема, яка зачіпає мужній, мужній студентів. Я був одного разу сказав мій мучитель класу Ситов, що я б ніколи не потрапити в хороший колега. І це все, що я коли-небудь хотів, це все, що будь-яка дитина хоче в моєму віці, просто потрапити в хороший колега. І не просто колеги. Ні, я хотів піти в Кот-правової колега. Так що, якщо я не поліпшення, пішов би мої мрії їхати в Гарвард, Жале, або в'язниця - Ви знаєте, у в'язниці, Нью-Джерсі. Так що я взяв собі для перевірки орфографії. Це трохи витяг з одного з моїх улюблених художників розмовною словом, Тейлор Малі. У всякому разі, як він каже, важливість перевірки орфографії дуже важливо. Так що ласкаво просимо Проходження 5, в якому ми будемо говорити про pset5: орфографічні помилки, , В якій ми будемо робити наші власні перевірки орфографії. Панель інструментів на цьому тижні, розподіл коду, буде важливо подивитися на просто щоб зрозуміти різні функції, що ваш словник буде мати. Ми насправді матиме кілька. С файлами, які разом роблять наші PSET. І ось, дивлячись через різні аспекти, хоча насправді ми не редагуючи один з файлів, speller.c, знаючи, як він працює з відношенню до dictionary.c, яку ми будемо писати, буде дуже важливим. Специфікація PSET також містить багато корисної інформації з точки зору речей, які ви можете припустити, правила тощо, так що не забудьте прочитати PSET специфікацію ретельно поради. І в разі сумнівів правила або щось в цьому роді, то завжди ставляться до PSET специфікації або обговорити. Це PSET буде покладатися на покажчики, тому ми хочемо переконатися, що ми розуміємо різницю між додаванням зірок перед ім'ям покажчика і амперсанд, як звільнити їх, і т.д. Таким чином, будучи майстром покажчиків буде дуже корисним в цьому завданні безліч. Ми збираємося заглянути в пов'язаних списках трохи більше, де у нас є елементи, які ми називаємо вузли, які мають як цінність, а також покажчик на наступний вузол, і так істотно зв'язують різні елементи один за іншим. Є кілька різних варіантів реалізації ваших фактичних словник. Ми будемо дивитися на два основних методу, який є хеш-таблиці, а потім намагається. В обох з них, вони пов'язані з якимось поняттям зв'язаний список де ви елементів, пов'язаних один з одним. І так ми будемо дивитися за тим, як ви могли б працювати по всьому пов'язаних списків, створити їх, перейдіть в плані того, як, наприклад, вставити в нього вузла або вільне всіх вузлів, а також. З точки зору звільнення вузлів, що дійсно важливо що коли ми Танос пам'яті, потім ми його звільнення. Тому ми хочемо, щоб переконатися, що немає покажчика йде unfreed, що у нас немає ніяких витоків пам'яті. Ми збираємося ввести інструмент під назвою Valgrind, який працює ваша програма і перевіряє, чи всі пам'яті, яку ви виділили потім звільнений. Ваша PSET тільки завершити, коли вона працює та має повну функціональність, але також, Valgrind говорить вам, що ви не знайшли витік пам'яті. Нарешті, для цього PSET, я дійсно хочу підкреслити - Я маю на увазі, як зазвичай, я, безумовно, прихильник допомогою пера і паперу для безлічі проблем, але для цього, я думаю, що ручка і папір буде особливо важливим якщо ви хочете бути малюнок стрілки на речі і розуміння того, як працюють речі. Так що обов'язково спробуйте використати ручку і папір, щоб зробити речі, перш ніж почати кодування тому що це може стати трохи брудними. По-перше, давайте йти в пов'язаних списках небагато. Зв'язані списки складаються з вузлів, де кожен вузол має значення, пов'язане з ним, а також покажчик на наступний вузол після нього. Кілька речей, важливих з зв'язаними списками в тому, що ми повинні пам'ятати, де наш перший вузол, а потім, коли ми знаємо, де перший вузол, Таким чином, ми може отримати доступ до вузла, що перші пункти вузла , А потім одна за що і після цього. І тоді останній елемент в зв'язаний список покажчиків, які вузла завжди буде вказувати на NULL. Коли вузол вказує на NULL, то ви знаєте, що ви досягли кінця списку, , Що вузол є останнім, що немає нічого після цього. Тут, у цій схемі, ви побачите, що стрілки покажчиків, і сині розділ, де зберігається це значення, , А потім червону коробку з покажчиком на це покажчик вузла вказуючи на наступний вузол після нього. І ось ви тут бачите, вузол D буде вказувати на NULL, тому що це останній елемент у списку. Давайте подивимося, як ми можемо визначити структуру для вузла. І оскільки ми хочемо мати декілька вузлів, це стане ЬурейеЕ структури , В якій ми збираємося мати кілька різних екземплярів вузлів. І таким чином, ми визначаємо його як новий тип даних. Тут ми маємо ЬурейеЕ вузла структури. У цьому прикладі ми маємо справу з цілими вузлами, тому ми маємо ціле значення імені, а потім у нас є ще один покажчик, і в цьому випадку, це покажчик на вузол, тому у нас є структура вузла * називається наступна. І тоді ми називаємо весь цей вузол річ. Переконайтеся, що ви будете слідувати цим синтаксисом. Зверніть увагу, що вузол насправді посилання нагорі, так і внизу фігурні дужки. Потім, щоб відстежувати, де моїм першим вузлом в цій пов'язаного списку, то в мене є вузол покажчиків називається головою, і я Танос достатньо місця для розміру вузла. Зауважимо, однак, що голова насправді є покажчиком вузла, на відміну від самого вузла. Таким чином, голова насправді не містить ніякого значення, вона лише вказує на який перший вузол в моєму зв'язаний список. Щоб отримати краще уявлення про пов'язаних списках, тому що це дуже важливо стежити за переконавшись, що ви підтримуєте ланцюга, Мені подобається думати про нього, як люди в лінію, тримаючись за руки, де кожна людина, тримаючись за руки наступного. Ви не можете бачити на цьому малюнку, але в основному вони вказують на наступний людина , Що в їх ланцюга. І тому, якщо ви хочете, щоб пройти зв'язаний список, де ці люди - Уявіть собі всі ці люди мають значення, пов'язані з ними , А також вказувати на наступний людина в лінії - якщо ви хочете, щоб пройти пов'язаного списку, наприклад, або змінити значення або шукати значення або щось на зразок цього, то ви хочете мати покажчик на конкретну людину. Таким чином, ми будемо мати вузол типу даних покажчика. Для цього, наприклад, назвемо його курсором. Інший поширений спосіб, щоб назвати це буде ітератор або щось на зразок того тому що це ітерації та насправді рухається, який вузол він вказує. Це тут буде наш курсор. Наш курсор спочатку вказувати на перший елемент в нашому списку. І тому те, що ми хочемо зробити, це ми хотіли б бути в основному продовжує курсор, переміщаючи його з боку в бік. У цьому випадку, ми хочемо, щоб перемістити його на наступний елемент у списку. З масивами, то, що ми робимо, що ми б просто сказати, що ми збільшенню індексу на 1. У цьому випадку, те, що ми повинні зробити, це насправді знайти людину який цей струм людина, що вказують на, і що це буде таке значення. Так що, якщо курсор знаходиться всього в вузлі покажчик, те, що ми хочемо зробити що ми хочемо, щоб дістатися до значення, що курсор вказує. Ми хочемо, щоб дістатися до цього вузла, а потім, коли ми знаходимося в цьому вузлі, дізнатися, де він вказує. Щоб дістатися до фактичного вузла, що курсор вказує на, Зазвичай ми вказуємо його (* курсора). Це дасть вам фактичного вузла, що курсор вказує. І потім, після того, що ми хочемо зробити, це ми хочемо отримати доступ все, що таке значення вузла є. Щоб зробити це, щоб отримати доступ до значень усередині структури, у нас є точка оператора. Таким чином, то це було б (* курсора). Наступний. Але це трохи брудний з погляду наявності дужки навколо * курсору, і тому ми замінити весь цей заяви з курсором>. Це тире, а потім знак більше, таким чином роблячи стрілки. Курсор-> далі. Це буде насправді вам вузол, який курсор миші. Це значення є наступною. Таким чином, замість того, зірки і крапка, ви замінюєте, що зі стрілкою. Будьте дуже обережні, щоб переконатися, що ви намагаєтеся використовувати цей синтаксис. Тепер, коли у нас є курсор, якщо ми хочемо отримати доступ до значення, перш, ми були курсору> наступний, але для доступу до значення в вузлі, що курсор вказує на, ми просто говорять вузол-> значення. Звідти, це тип даних все, що ми визначили значення і вузли, щоб бути. Якщо це ціле число вузлів, то курсор-> значення тільки збирається бути цілим числом. Так що ми можемо робити операції на те, що перевірка рівності, присвоїти різні значення, і т.д. Отже, що ви хочете зробити, якщо ви хочете, щоб перемістити курсор до наступного людині, Ви дійсно змінити значення курсора. Так як курсор знаходиться вузол покажчиків, можна змінити фактична адреса покажчика в адресу наступного вузла в вашому списку. Це просто якийсь код, де ви могли ітерації. Там, де у мене є коментар щось робити, ось де ви, ймовірно, отримати доступ до значення або зробити щось робити з цим конкретним вузлом. Щоб почати його, я кажу, що мій курсор спочатку буде вказувати на перший елемент в зв'язаний список. І ось попереду, я визначив його як главу вузла. Як я згадував раніше, звільняючи це дуже важливо. Ви хочете, щоб переконатися, що ви звільнитися кожен елемент у списку, як тільки ви закінчите з ним. Якщо у вас немає необхідності посилатися на будь-яке з цих покажчиків більше, Ви хочете, щоб переконатися, що ви звільняєте всі ці покажчики. Але ви хочете бути дуже обережним у тому, що ви хочете, щоб уникнути витоку пам'яті. Якщо ви безкоштовних однієї людини передчасно, то всі покажчики, що вузол вказує на будуть втрачені. Повертаючись до лиця Наприклад, щоб зробити його трохи більш високі ставки, давайте цим людям, але в даному випадку вони нависли над озером з монстром. Ми хочемо, щоб переконатися, що, коли ми вільні, ми не втрачаємо і відпустити будь-які вузли, перш ніж ми насправді звільнив їх. Наприклад, якщо б ви просто подзвонити безкоштовно на цього хлопця тут, Потім він буде звільнений, але потім всі з цих хлопців потім буде втрачений і вони будуть дрейфувати геть і опадають. Таким чином, ми хочемо переконатися, що замість цього, ми хочемо підтримувати зв'язок з іншими. Наш головний покажчик, який вказує на перший елемент у списку. Це ніби як мотузка якір від першої особи. Що ви можете зробити, коли ви звільнити списку є - Якщо ви хочете, щоб звільнити перший елемент перший, то ви можете мати тимчасовий покажчик , Який вказує на все, що перший елемент. Так що у вас є тимчасовий покажчик, який вказує тут. Таким чином, ми маємо в руки першого вузла. А потім, оскільки ми знаємо, що перший вузол буде звільнений, Потім ми можемо перейти цю мотузку, цей якір, наша голова, насправді вказують на все, що перше вказує. Таким чином, ця голова насправді вказує на другий елемент зараз. Зараз ми дозволили, щоб звільнити все, що зберігається в темп, і тому ми можемо стерти, що без нього загрозу всі інші вузли в нашому списку. Ще один спосіб, що ви можете зробити, це може бути кожен раз, коли ви просто звільнити останній елемент у списку тому що вони гарантовано не вказав ні до чого. Таким чином, можна просто звільнити цю одну, то безкоштовно це одне, то безкоштовно це. Це безперечно працює, але трохи повільніше, тому що за характером пов'язаних списків, Ми не можемо просто відразу перейти до останнього. Ми повинні пройти кожен елемент в зв'язаний список і переконайтеся в тому, що одне вказує на NULL, перевірити кожен раз, , А потім, як тільки ми дійти до кінця, то, що безкоштовно. Якщо б ви були для цього процесу, ви фактично буде перевірка тут, перевірка тут, то перевірка тут, звільняючи його, потім повернутися, перевіривши тут, перевіряючи, тут, звільняючи його, перевірка тут, а потім звільняючи його. Це займе трохи більше часу. Так. [Студент] Чи можна зробити списком, який зберігає виходу покажчика до кінця? Це безумовно було б можливо. Щоб повторити запитання, чи можливо, щоб мати зв'язаний список структуру таке, що у вас є вказівник на кінець пов'язаного списку? Я б сказав, що це можливо, і кожен раз, коли ви вставляєте щось у вашій зв'язаний список Вам доведеться оновлювати покажчик тощо. Ви б вузлом хвіст *, наприклад. Але коли ви реалізуєте цю функцію, ви повинні думати про компроміси, як те, скільки разів я збираюся бути ітерації з цього приводу, Наскільки важко буде стежити за хвіст, а також глава а також мої ітератор, тощо. Чи означає це -? >> [Студент] Так. Це можливо, але з точки зору дизайнерських рішень, ви повинні зважити всі варіанти. Ось скелет коду, який дозволить вам звільнитися кожного елемента в зв'язаному списку. Знову ж таки, так як я ітерації пов'язаного списку, я збираюся хочуть мати якийсь курсор або ітераторів. Ми ітерації, поки курсор не NULL. Ви ж не хочете, щоб ітерації, коли курсор знаходиться NULL тому що це означає, що немає нічого в списку. Таким чином, то тут я зробити тимчасовий вузол * вказуючи на те, що я розглядаю це перший з мого списку, а потім я перенести курсор вперед 1, а потім звільнити все, що я мав на тимчасового зберігання. Тепер ми підійшли до вставці в пов'язаних списках. У мене є три вузли в моїй пов'язаного списку, і підемо з простий випадок , Де ми хочемо, щоб вставити інший вузол в кінці нашої зв'язаний список. Щоб зробити це, все ми хотіли б зробити, це ми будемо проходити щоб знайти, де поточні кінця пов'язаного списку є, таким чином, який вузол вказує на NULL - ось цей - а потім кажуть, насправді, на цей раз не буде останнім вузлом; насправді ми матимемо ще один. Таким чином, ми б цю поточний момент до того, що ми вставкою. Так що тепер цей червоний людина тут стає останнього вузла в зв'язаний список. І так характерно для останнього вузла в зв'язаний список є те, що вона вказує на NULL. Отже, що ми повинні зробити, це встановити покажчик цю червону хлопця, щоб NULL. Там же. Але що, якщо ми хочемо, щоб вставити вузол між другим і третім? Це одна не так просто, тому що ми хочемо, щоб переконатися, що ми не відпустити будь-якого вузла в нашому зв'язаний список. Що ми повинні зробити, це переконатися, що ми якір себе кожен з них. Наприклад, давайте назвемо це друге. Якщо ви сказали, друга тепер вказує на цю нову і ви тільки що зробили покажчик там, то це призведе цей хлопець втрачається тому що немає ніякого посилання на нього. Замість цього - я намалюю це знову. Пробачте мої художні здібності. Ми знаємо, що ми не можемо безпосередньо зв'язати 2 до нової. Ми повинні переконатися, що ми тримаємося до останнього. Що ми могли б зробити, це тимчасовий покажчик на елемент, який збирається бути доданий на. Отже у нас є тимчасовий покажчик там. Оскільки ми знаємо, що це третій в даний час стежив, 2 може зв'язатися з нашим новим. І якщо цей новий хлопець червоно буде між 2 і 3, те, що покажчик, хлопець збирався вказати на? >> [Студент] Темп. Температура Так. Отже наступне значення цього червоного хлопець буде темп. Коли ви вставки в зв'язані списки, ми побачили, що ми могли б Легко додати щось до кінця шляхом створення тимчасового масиву, або якщо ми хотіли щось додати в середину нашого масиву, то це займе трохи більше перетасовки навколо. Якщо ви хочете, наприклад, є відсортований пов'язаного списку, то ви повинні виду зважити витрати та вигоди, що тому що якщо ви хочете мати впорядкований масив, це означає, що кожного разу, коли ви вставляєте в нього, це займе трохи більше часу. Однак, якщо ви хочете, щоб надалі, як ми знайдемо ми хочемо, пошук у зв'язаному списку, то було б легше, якщо ви знаєте, що все в порядку. Таким чином, ви можете зважити витрати та вигоди від цього. Інший спосіб вставити в зв'язаний список, щоб включити в самому початку списку. Якщо ми проведемо наш якір тут - це наша голова - а потім ці люди пов'язані з ним, а то у нас новий вузол повинен бути вставлений в самому початку, те, що може ми хочемо зробити? Що б неправильно з просто говорю, я хочу, щоб зв'язати червоного до синього, тому що це перший? Що станеться тут? Всі ці три заблукав. Таким чином, ми не хочемо цього робити. Знову ж таки, ми дізналися, що нам потрібно мати якийсь тимчасовий покажчик. Давайте виберемо, щоб мати тимчасову крапку в цьому хлопцеві. Тоді ми можемо мати сині однієї точки до тимчасових , А потім червону крапку на синій. Причина, чому я використовую людей тут тому, що ми дійсно хочемо, щоб візуалізувати проведення на людей, і переконавшись, що у нас є посилання на них перш ніж відпустити іншою рукою або щось на зразок цього. Тепер у нас є почуття зв'язані списки - як ми могли б створити зв'язаний список і створити структури для цього, складається з визначення типу для вузла , А потім, переконавшись, що у нас є покажчик на глави, які пов'язані списку - Після того як ми є, що і ми знаємо, як пройти через масив, доступ до різних елементів, ми знаємо, як вставляти і ми знаємо, як звільнити їх, Потім ми можемо отримати в друкарськими помилками. Як звичайно, у нас є розділ питань, що допоможе вам використовувати для роботи з зв'язні списки і різних структур, таких як черги і стеки. Тоді ми можемо рухатися в друкарськими помилками. Орфографічні помилки має в розподілі коду пару файлів важливості. Спочатку ми помітили, що у нас є цей Makefile тут, які ми дійсно не зустрічалися раніше. Якщо Ви заглянули всередину pset5 папку, ви помітите, що у вас є. Ч. файл, то у вас є два. с файлами. Що це Makefile робить це раніше, ми б просто ввести зробити, а потім назву програми і тоді ми побачимо всі ці аргументи і прапори передається в компілятор. Що Makefile робить це дозволяє компілювати кілька файлів одночасно і передати прапори, які ми хочемо. Тут ми тільки бачимо, що є файл заголовка тут. Тоді ми насправді є два вихідних файлів. У нас є speller.c і dictionary.c. Ми раді вітати Вас відредагувати Makefile, якщо хочете. Зверніть увагу, що тут, якщо ви вводите чистий, те, що він робить насправді видаляє всі , Що є основною. Якщо у вас є помилка сегментації, в основному ви отримаєте дамп пам'яті. Таким чином, це потворно маленький файл з'явиться в папці називається ядром. Ви хочете, щоб видалити це, щоб зробити його чистим. Вона видаляє всі файли EXE і. Про файлах. Давайте поглянемо на dictionary.h. Це говорить про те, що він оголошує функціональність словника. Ми маємо максимальну довжину для будь-якого слова в словнику. Ми говоримо, що це буде найдовший можливий слово. Це довжину 45. Таким чином, ми не матимемо жодних слів, які перевищують цю довжину. Тут ми просто повинні прототипи функцій. Ми не маємо фактичної реалізації, тому що це те, що ми будемо робити для цього PSET. Але те, що це робить, так як ми маємо справу з великими файлами тут і функціональність в більш широкому масштабі, це корисно. ч. файл так, що хтось читає або за допомогою коду може зрозуміти, що відбувається. А може бути, вони хочуть реалізувати намагається якщо ви зробили хеш-таблиць або навпаки. Тоді вони сказали б мої навантаження функції, фактична реалізація буде відрізнятися, але цей прототип не зміниться. Тут ми перевірка, яка повертає істину, якщо дане слово в словник. Тоді у нас є навантаження, яка в основному приймає в файл словника , А потім завантажує його в деякій структурі даних. У нас є розмір, який при виклику повертає розмір словника, скільки слів в ньому зберігаються, і потім вивантажити, який звільняє всю пам'ять, що ви можете зайняли під час внесення словник. Давайте поглянемо на dictionary.c. Ми бачимо, що вона дуже схожа на dictionary.h, тільки тепер він просто всі ці незробленого в цьому. І так, що це ваша робота. Зрештою, ви будете заповнити speller.c з усім цим кодом. Dictionary.c, коли бігти, насправді не збирається нічого робити, тому ми дивимося в speller.c, щоб побачити фактичне здійснення перевірки правопису. Навіть якщо ви не збираєтеся редагування будь-якого справжнього Кодексу, Важливо, щоб читати, розуміти, коли буде навантаження називається, коли я виклику перевірки, просто щоб зрозуміти, карта його, подивитися, як працює функція. Ми бачимо, що це перевірка для правильного використання. По суті, коли хтось біжить правопису, це означає, що це необов'язково для них, щоб пройти в файл словника, тому що це буде стандартний файл словника. А потім вони повинні пройти в текст, який буде орфографії перевіряються. rusage стосується часу, тому що частина цієї PSET якої ми будемо мати справу з більш пізніми не тільки отримувати функціонування перевірки орфографії робочих але насправді змусити його бути швидким. І так, то що там rusage збирається увійти Тут ми бачимо, що перший дзвінок на один з наших dictionary.c файлів, що є навантаженням. Навантаження повертає істину або брехня - правда на успіх, помилкових після збою. Так, якщо в словнику не завантажується належним чином, то speller.c поверне 1 і вийти. Але якщо він робить навантаження належним чином, то це буде продовжуватися. Ми як і раніше, і ми бачимо деякий файловий ввід / вивід тут, , Де він збирається мати справу з відкриття текстового файлу. Тут, як це робить орфографії перевіряє кожне слово в тексті. Так що speller.c робить прямо тут ітерації по кожному зі слів у текстовому файлі , А потім перевіряти їх у словнику. Тут ми маємо логічне помилками, які побачать, якщо перевірка повертає істину чи ні. Якщо слово насправді в словнику, то перевірка буде повертати правда. Це означає, що слова не написано неправильно. Таким чином, неправильно було б помилковим, і саме тому ми маємо вибух там, індикація. Ми продовжуємо йти, а потім відстежує, як багато слів з помилками Є в файл. Це продовжується і закриває файл. Тоді ось, він повідомляє, скільки слів з помилками у вас. Він обчислює, скільки часу знадобилося, щоб завантажити словник, Скільки часу потрібно було, щоб перевірити це, Скільки часу потрібно було, щоб обчислити розмір, , Який, як ми підемо далі, повинна бути дуже мала, і скільки часу знадобилося, щоб розвантажити словник. Тут нагорі ми бачимо заклик до вивантаження тут. Якщо ми перевіряємо розмір тут, Потім ми бачимо, що тут є виклик розміру, де вона визначає розмір словника. Awesome. Наше завдання на цьому PSET є реалізація навантаження, яка буде завантажувати словник Структура даних - Який би ви не вибрали, будь то хеш-таблиці або спробувати - зі словами зі словника файлу. Тоді у вас є розмір, який буде повертати кількість слів у словнику. І якщо ви реалізуєте навантаження в розумним способом, то розмір повинен бути досить легким. Тоді ви перевірте, яке буде перевіряти, якщо дане слово в словник. Так speller.c проходить в рядок, а потім ви повинні перевірити, що рядок міститься в словнику. Зверніть увагу, що ми, як правило, мають стандартні словники, але в цьому PSET, в основному будь словник пройшли в будь-якій мові. Тому ми не можемо просто припустити, що слово знаходиться всередині. Слово FOOBAR може бути визначена в певний словник, який ми передаємо дюйма А потім ми розвантаження, яка звільняє словник з пам'яті. По-перше, я хотів би піти по хеш-таблиці методів про те, як ми могли б реалізувати всі ці чотири функції, а потім я піду на метод намагається, як ми реалізуємо ці чотири функції, і в кінці розмови про деякі загальні поради, коли ви робите PSET а також, як ви могли б використовувати Valgrind для перевірки витоку пам'яті. Давайте в хеш-таблиці методів. Хеш-таблиця складається із списку відра. Кожне значення, кожне слово, збирається піти в одну з цих відер. Хеш-таблиці ідеально рівномірно розподіляє всі ці значення, що ви передаєте , А потім заповнює їх у відро так, що кожне відро має приблизно однакову кількість значень в цьому. Структура хеш-таблиці, у нас є масив пов'язаних списків. Що ми робимо, коли ми переходимо в значенні, ми перевіряємо, де це значення повинне належати, які відро вона належить, а потім помістити його в зв'язаний список, пов'язаний з цим відром. Ось, що у мене є хеш-функції. Це ціле число хеш-таблиці. Таким чином, для першого відра, будь-які цілі нижче 10 вдаватися в першому відрі. Будь-які цілі вище 10, але нижче 20 Перейти в секунду, і так далі, і так далі. Для мене кожне відро, що представляють ці цифри. Тим не менш, сказати, що я була пройти в 50, наприклад. Здається, ніби перші три містять ряд з десяти цифр. Але я хочу, щоб мої хеш-таблиці, щоб приймати в будь-якому вигляді цілих чисел, так, то я мав би відфільтрувати всі числа більше 30, в останні відро. І таким чином, який призведе до свого роду незбалансоване хеш-таблиці. Повторюся, хеш-таблиця просто масив відра де кожне відро пов'язаного списку. І ось щоб визначити, де кожне значення виходить, що відро він переходить в, Ви будете хотіти те, що називається хеш-функції , Яка приймає значення, а потім говорить, що це значення відповідає певний відро. Так що нагорі в цьому прикладі, мій хеш-функції взяв кожного значення. Він перевірив, чи було це менше, ніж 10. Якби це було, це було б покласти його в першому відрі. Він перевіряє, чи є це менше 20, ставить його в другу якщо це правда, перевіряє, чи є це менше, ніж 30, а потім кладе його в третю відро, а потім все інше просто падає на четвертий відро. Тому, коли у вас є значення, ваш хеш-функції Покладіть це значення у відповідне відро. Хеш-функція в основному потрібно знати, скільки у вас є відра. Ваш розмір хеш-таблиці, кількість сегментів у вас є, що це буде фіксоване число це до вас, для вас, щоб вирішити, але це буде фіксоване число. Так що ваш хеш-функція буде покладатися на те, щоб визначити, до якої кожен ключ переходить у такий, що він рівномірно розподілений. Як і в нашій реалізації пов'язаних списків, тепер кожен вузол в хеш-таблиці насправді матиме тип символу. Тому у нас є масив символів називаються слова, а потім ще один покажчик на наступний вузол, який має сенс, тому що це буде пов'язаний список. Пам'ятаєте, коли ми були зв'язані списки, я зробив вузол * називається головою , Що вказувало на перший вузол у зв'язаному списку. Але для нашої хеш-таблицю, тому що у нас є декілька пов'язаних списків, те, що ми хочемо, ми хочемо, щоб наша хеш-таблиці, щоб бути, як: "Що таке відро?" Ківш являє собою список вузлів покажчиків, і так кожен елемент у відрі насправді вказує на відповідний зв'язаний список. Щоб повернутися до цієї схеми, ви бачите, що відра самі стрілки, не актуально вузлів. Одним з найважливіших властивостей хеш-функцій є те, що вони детерміновані. Це означає, що всякий раз, коли ви хеш № 2, вона завжди повинна повертати той же відро. Кожне значення, яке входить в хеш-функцію, якщо повторюється, повинен отримати той же індекс. Так що ваш хеш-функція повертає індекс масиву де це значення належить. Як я згадував раніше, кількість сегментів фіксоване, і тому ваш індекс, що ви повернетеся повинна бути менше, ніж кількість ковшів але більше 0. Причина, чому ми маємо хеш-функції, а не тільки одного пов'язаного списку або одного масиву є те, що ми хочемо, щоб мати можливість перейти до певної частини найбільш легко якщо ми знаємо, характерні значення - замість того, щоб шукати через весь весь словник, можливість переходу до певної її частини. Ваш хеш-функція повинна брати до уваги, що в ідеалі, кожного сегмента має приблизно таку ж кількість ключів. Так як хеш-таблиці являє собою серію пов'язаних списків, Потім пов'язаних списків самі будете мати більше, ніж одного вузла. У попередньому прикладі, два різних номери, хоча вони були не рівні, При хешіруется, повернеться тим же індексом. Так що, коли ви маєте справу зі словами, одним словом, коли хешіруется буде такою ж хеш-значення, як іншим словом. Це те, що ми називаємо зіткнення, коли у нас є вузол, який, коли хешіруется Зв'язаний список у цьому відрі не порожній. Техніка, яку ми називаємо є лінійне зондування, куди ви йдете в зв'язаному списку, а потім знайти, де ви хочете вставити цей вузол тому що у вас зіткнення. Ви можете бачити, що там може бути компроміс тут, чи не так? Якщо у вас є дуже маленький хеш-таблиці, дуже невелика кількість сегментів, то ви будете мати багато зіткнень. Але тоді, якщо ви робите дуже велику хеш-таблиці, ви, ймовірно, щоб звести до мінімуму зіткнення, але це буде дуже великою структури даних. Там збирається бути компроміси з цим. Тому, коли ви робите вашу PSET, спробуйте пограти між можливо, зробити менше хеш-таблиці але потім, знаючи, що він збирається зайняти трохи більше часу, щоб пройти різні елементи з тих, зв'язані списки. Які навантаження збираюся зробити, це перебір кожне слово в словнику. Він проходить в покажчик на файл словника. Отже, ви збираєтеся скористатися файлу I / O функції, які ви освоїли в pset4 і перебирати кожне слово в словнику. Ви хочете, щоб кожне слово в словник, щоб стати новим вузлом, і ви збираєтеся помістити кожен з цих вузлів всередині вашої структури даних словника. Всякий раз, коли ви отримуєте нове слово, ви знаєте, що він збирається стати вузлом. Таким чином, ви можете піти відразу і Танос вузла покажчик для кожного нового слова, яке у вас є. Тут я дзвоню мій вузол покажчиків new_node і я mallocing що? Розмір вузла. Тоді читати фактичної рядки з файлу, оскільки словник насправді зберігається словом, а потім на новий рядок, що ми можемо скористатися є функцією fscanf, яким файл файл словника, який ми проходили в, так він сканує файл на рядки і рядки місцях, які в останній аргумент. Якщо ви пам'ятаєте тому в одній з лекцій, коли ми перейшли і вид очищені шари назад на бібліотеку CS50, ми бачили здійснення fscanf там. Щоб повернутися до fscanf, у нас є файл, який ми читаємо с, Ми шукаємо рядок у файл, а потім ми помістивши його в Тут у мене є new_node-> слово, тому що new_node це вузол покажчиків, Не фактичного вузла. І тоді я кажу new_node, я хочу, щоб перейти до вузла, що це вказує на , А потім привласнити це значення слова. Ми хочемо, щоб потім взяти це слово і вставити його в хеш-таблиці. Зрозумійте, що ми зробили new_node вузла покажчика тому що ми збираємося хочемо знати, що адресу цього вузла коли ми вставляємо його в тому, що структура вузлів собі, про структуру, є те, що у них є вказівник на новий вузол. Так що те що адресу цього вузла буде вказувати? Ця адреса буде new_node. Чи має це сенс, чому ми робимо new_node вузол * на відміну від вузла? Добре. У нас є слово. Це значення є new_node-> слово. , Який містить слово зі словника, який ми хочемо вхід. Отже, що ми хочемо зробити, це ми хочемо, щоб подзвонити в наш хеш-функції на цей рядок тому що наш хеш-функція приймає рядок, а потім повертає нас ціле число, де це число є індексом, де хеш-таблиці за цим індексом уявляє, що відро. Ми хочемо, щоб цей індекс, а потім перейти на цю індексу хеш-таблиці а потім використовувати це зв'язаний список, щоб вставити вузол в new_node. Пам'ятайте, що як би ви вирішили вставити свій вузол, будь то в середині, якщо ви хочете, щоб залагодити його або на початку або в кінці, просто переконайтеся, що ваш останній вузол завжди вказує на NULL тому що це єдиний шлях, який ми знаємо, де останній елемент нашого зв'язаний список. Якщо розмір ціле число, яке представляє кількість слів у словнику, Потім один із способів зробити це є те, що всякий раз, коли величина називається ми проходимо кожен елемент в нашій хеш-таблиці а потім повторювати через кожні зв'язаний список у хеш-таблиці а потім обчислити довжину, що, збільшуючи наш лічильник 1 на 1. Але кожен раз, що розмір називається, що збирається зайняти багато часу тому що ми збираємося бути лінійно зондування кожен зв'язаний список. Замість цього, він буде набагато легше, якщо вам відстежувати, скільки слів пройшло дюйма Отже, якщо ви включите лічильник у вашу навантаження функції , Що поновлення в міру необхідності, то лічильник, якщо ви встановите його в глобальній змінній, зможуть отримати доступ за розміром. Так що розмір може просто зробити це в одному рядку, просто повернути значення лічильника, розмір словника, який ви вже розглядається в навантаження. Ось що я мав на увазі, коли я сказав, що якщо ви реалізуєте навантаження в корисний спосіб, , То розмір буде досить легко. Так що тепер ми отримуємо для перевірки. Зараз ми маємо справу зі словами з файлу введення тексту, і тому ми збираємося перевіряти, чи всі з цих вхідних слів насправді в словнику чи ні. Подібний Scramble, ми хочемо, щоб забезпечити нечутливість до регістру. Ви хочете, щоб переконатися, що всі слова передається, навіть якщо вони змішані випадку, при виклику з рядком порівняння, еквівалентні. Слів у файли введення тексту насправді все в нижньому регістрі. Інша справа, що можна припустити, що кожне слово передається, кожен рядок, буде або алфавітному або містять апострофи. Апострофи буде дійсна слів в нашому словнику. Так що якщо у вас є слово з апострофом S, це фактичні законні слово в словнику що це буде один з вузлів в хеш-таблиці. Перевірте працює з якщо слово існує, то він повинен бути в нашому хеш-таблиці. Якщо слово є в словнику, то всі слова в словнику знаходяться в хеш-таблиці, так що давайте подивимося на це слово в хеш-таблиці. Ми знаємо, що, оскільки ми реалізували наш хеш-функції такі, що кожен унікальний слово завжди хешіруется те ж значення, Потім ми знаємо, що замість пошуку через всю нашу всій хеш-таблиці, ми дійсно можемо знайти пов'язаного списку, що це слово має належати. Якби це було в словнику, то це було б в цьому відрі. Що ми можемо зробити, якщо слово це ім'я нашої рядки передається, Ми можемо тільки хеш, що слово і погляд на зв'язаний список на значення хеш-таблиці [хеша (слово)]. Звідти, що ми можемо зробити, це у нас є менша підмножина вузлів для пошуку цього слова, і тому ми можемо пройти через зв'язаний список, використовуючи приклад із раніше в керівництві , А потім викликати порівняння рядків на слово там, де курсор вказує на, це слово, і подивитися, чи є ці порівняння. Залежно від способу, що Вам організувати свій хеш-функції, якщо вона сортується, ви могли б повернутися помилковим трохи раніше, але якщо це несортоване, то ви хочете, щоб продовжити обхід через зв'язаний список поки ви не знайдете останній елемент списку. І якщо ви все ще не знайшли слів до того часу, як ви дійшли до кінця пов'язаного списку, це означає, що ваші слова не існує в словнику, і так, що слово є недійсним, і чек повинен повернутися помилковим. Тепер ми підійшли до вивантаження, де ми хочемо, щоб звільнити всіх вузлів, які ми malloc'd, так вільно всі вузли усередині нашої хеш-таблиці. Ми збираємося хочете перебрати всі зв'язані списки і безкоштовно всі вузли в цьому. Якщо ви подивитеся вище в керівництві наприклад, де ми звільнитися пов'язаного списку, то ви хочете, щоб повторити цей процес для кожного елемента в хеш-таблиці. І я піду на це до кінця проходження гри, але Valgrind є інструментом, де ви можете побачити, якщо ви правильно звільнений кожен вузол, який ви malloc'd або що-небудь ще, що ви malloc'd, будь-який інший покажчик. Так от хеш-таблиці, де у нас є кінцеве число ковшів і хеш-функцію, яка буде приймати значення, а потім привласнити це значення в певному відро. Тепер ми підійшли до спроб. Намагається вид виглядає так, і я також витягнути приклад. В принципі, у вас є цілий ряд потенційних букви, а потім, коли ви створюєте слово, , Що лист може бути пов'язано для словника до широкого спектру можливостей. Кілька слів починаються з C, а потім продовжити, але інші продовжують з ущільнювальним, наприклад. Trie це спосіб візуалізувати всі можливі комбінації цих слів. Trie буде стежити за послідовністю букв, що становлять слова, відгалуження, коли це необхідно, коли одна літера може слідувати кілька листів, і в кінці вказати в кожній точці Чи це слово є дійсним чи ні тому що якщо ви правопис слова MAT, MA Я не думаю, що це дійсно слово, але мат. І тому у вашому Trie, це буде означати, що після MAT, що насправді це дійсно слово. Кожен вузол в нашій Trie насправді відбувається, щоб утримувати масив вузол покажчиків, і ми будемо мати, зокрема, 27 з цих вузлів покажчиків, по одному на кожну букву алфавіту, а також символ апострофа. Кожен елемент у цьому масиві сама збираюся вказувати на інший вузол. Так що, якщо вузол є NULL, якщо немає нічого після цього, Потім ми знаємо, що немає ніякої подальшої букви в цьому слові послідовності. Але якщо вузол не NULL, що означає, що є більше букв в цьому листі послідовності. І потім, крім того, кожен вузол вказує, чи є це останній символ слова чи ні. Підемо в приклад вигляді дерева. Перший у мене є кімната на 27 вузлах в цьому масиві. Якщо у мене є слово BAR - Якщо у мене є слово BAR, і я хочу, щоб вставити, що, перша буква B, так що якщо моя Trie порожній, B є другою букви алфавіту, так що я збираюся вибрати, щоб поставити це тут, на цьому індексі. Я хочу, щоб мати B тут. B буде вузол, який вказує на інший масив всіх можливих символів , Які можуть слідувати за буквою B. В даному випадку я маю справу зі словом BAR, так буде йти тут. Після того, у мене є буква R, так, то тепер вказує на її власні комбінації, , А потім R буде тут. BAR повне слово, і тоді я буду мати точку R на інший вузол який говорить, що це слово є дійсним. Це вузол також буде мати безліч вузлів, але ті, може бути NULL. Але в принципі, це може тривати подібне. Це стане трохи більш ясним, коли ми йдемо в іншу, наприклад, так що терпите мене там. Тепер у нас є бар всередині нашого словника. Тепер у нас є слово БАЗ. Почнемо з B, і ми вже маємо B якості однієї з букв, яка в нашому словнику. Це слід з А. У нас є вже. Але замість цього, ми маємо Z наступне. Отже елемента в масиві буде Z, і так, то, що ніхто не збирається вказувати на інший дійсний кінці слова. Отже, ми бачимо, що, коли ми як і раніше через B, а потім, Є два різних варіанти в даний час в нашому словнику слова, які починаються з B і A. Скажімо, ми хотіли, щоб вставити слово FOOBAR. Тоді ми хотіли б зробити запис в F. F це вузол, який вказує на весь масив. Ми хотіли б знайти O, перейдіть на O, O, то посилання на весь список. Ми б B, а потім продовжити, ми б і R. Отже FOOBAR проходить весь шлях вниз, поки FOOBAR це правильне слово. І ось тоді це було б дійсно слово. Тепер кажуть, що наші наступне слово в словнику насправді слово FOO. Ми б сказали, що слід F. F? Я насправді вже є простір для висновку, тому я збираюся продовжувати. Мені не потрібно, щоб зробити нову. Продовжити. FOO є дійсним слово в цьому словнику, так що потім я збираюся вказувати , Що є допустимим. Якщо я кину мою послідовність там, це було б правильно. Але якщо ми продовжили нашу послідовність з FOO до B і тільки що FOOB, FOOB ні слова, і це не зазначено в якості допустимим. У вигляді дерева, ви кожен вузол вказує, чи є це дійсно слово чи ні, , А потім кожен вузол також має масив з 27 вузлів покажчики що потім виберіть вузли самі. Ось спосіб, як ви можете визначити це. Однак, як і в хеш-таблицю-приклад, де у нас було головному вузлі * для позначення початку нашої зв'язаний список, ми також захочуть якимось чином знаючи, де початок нашої Trie є. Деякі люди називають намагається дерев, а от де корінь приходить. Тому ми хочемо, корінь нашого дерева, щоб переконатися, що ми залишаємося заземленням туди, де наші Trie є. Ми вже начебто підійшов як ви могли б подумати про завантаження кожного слова у словнику. По суті, за кожне слово ви збираєтеся хочете перебрати ваші Trie і знаючи, що кожен елемент в дітей - ми назвали його дітей у даному випадку - відповідає іншу букву, ви будете хотіти, щоб перевірити ці значення в даний індекс, який відповідає букві. Так думають всі шляхи назад на Цезаря і Віженер, знаючи, що кожен лист ви можете видів карту назад в алфавітному покажчику, Виразно через Z буде досить легко зіставити з алфавітним листом, але, на жаль, апострофи також прийнятих символів у словах. Я навіть не впевнений, що ASCII значення, так для цього, якщо ви хочете, щоб знайти індекс вирішити, чи хочете ви, щоб бути першим або останній, вам доведеться зробити важкий кодованих перевірки, що , А потім покласти, що в індекс 26, наприклад. І тоді ви перевіряєте значення у дітей [я] де [я] відповідає будь букві знаходимося. Якщо це NULL, що означає, що є в даний час не будь-які можливі букви випливають з цього попередньої послідовності, так що ви будете хотіти, щоб Танос і зробити новий вузол і є, що діти [я] вказують на це так що ви створюєте - коли ми вставили букву в прямокутник - щоб діти не-NULL і крапка в цей новий вузол. Але якщо це не NULL, як в нашому екземплярі FOO Коли ми вже були FOOBAR, ми як і раніше, і ми ніколи не робить новий вузол, а просто задавши is_word до істинного В кінці цього слова. Отже, як раніше, тому що тут ви маєте справу з кожною буквою в той час, це буде простіше для вас розміру, замість того, щоб розрахувати і пройти через все дерево і підрахувати, скільки дітей у мене , А потім відгалуження, згадуючи, як багато знаходиться на лівій стороні, а на правій стороні і тому подібні речі, це буде набагато простіше для вас якщо ви просто відстежувати, скільки слів ви додаєте в коли ви маєте справу з навантаженням. І ось тоді, що шлях розміру може просто повернути глобальну змінну розміру. Тепер ми підійшли, щоб перевірити. Те ж стандартами, як і колись, де ми хочемо, щоб забезпечити нечутливість до регістру. Крім того, ми припускаємо, що рядки є тільки букви і апостроф тому що діти це масив з 27 довгий, так що всі букви алфавіту плюс апостроф. Для перевірки, що ви хочете зробити, ви хочете, щоб почати в корені тому що корінь буде вказувати на масив, що містить всіх можливих початкових літер слова. Ви збираєтеся почати там, а потім ви збираєтеся перевірити це значення NULL або немає, тому що, якщо значення NULL, що означає, що словник не має значення , Які містять цю букву в цьому конкретному порядку. Якщо це NULL, то це означає, що слово написано з помилками відразу. Але якщо він не NULL, то ви можете продовжувати, сказати, що перша буква є можливим перша буква в слові, так що тепер я хочу перевірити, якщо другий лист, що послідовність, знаходиться в моєму словнику. Отже, ви збираєтеся піти в індексі дітей першого вузла і переконайтеся в тому, що другий лист існує. Тоді ви повторіть цей процес, щоб перевірити, що послідовність є дійсним чи ні у вашому Trie. Всякий раз, коли вузол дітей, що індекс вказує на NULL, Ви знаєте, що ця послідовність не існує, але потім, якщо ви дійдете до кінця слова, які ви вводиться, Потім ви хочете перевірити тепер, коли я завершив цю послідовність і знайшов його в моїй синтаксичного дерева, в тому, що слово дійсно чи ні? І таким чином ви хочете перевірити це, і ось тоді, якщо ви виявили, що послідовність, то ви хочете перевірити, чи є це слово є дійсним чи ні тому що пам'ятаю ще в попередньому випадку, що я намалював, де ми мали FOOB, , Що була дійсна послідовності, які ми знайшли, але не був фактично дійсно саме слово. Аналогічно, для вивантаження в спроб ви хочете вивантажити всі вузли в Trie. Вибачте. Як і хеш-таблиць, де в розвантажувати ми звільнили всіх вузлів, У спроб ми хочемо також звільнити всіх вузлів. Вивантаження дійсно буде працювати простим знизу вгору тому що це, по суті зв'язані списки. Таким чином, ми хочемо переконатися, що ми тримаємося за всі значення і безкоштовно всі з них в явному вигляді. Те, що ви захочете зробити, якщо ви працюєте з Trie , Щоб подорожувати на дно і безкоштовний мінімально можливих вузол першим , А потім піднятися на всі ці діти, а потім звільнити всіх тих, вгору, а потім вільно, і т.д. Ніби як справа з нижнім шаром Trie першого , А потім збирається нагорі, як тільки ви звільнили всі. Це хороший приклад того, де рекурсивна функція може стати в нагоді. Після того як ви звільнили нижній шар вашого Trie, Потім ви дзвоните вивантажити на інше, переконавшись, що ви позбавити всіх міні - Ви можете видів візуалізувати його в якості міні спроб. Таким чином, у Вас є корінь тут. Я просто спрощенні це так, я не привернути 26 з них. Так що у вас є ці, а потім вони являють собою послідовності слів де всі ці маленькі кола листи, які дійсні послідовності букв. Давайте продовжимо трохи більше. Те, що ви захочете зробити, це безкоштовно нижній тут, а потім безкоштовно цю , А потім звільнити цю внизу, перш ніж звільнити верхню тут тому що якщо ви щось безкоштовне другого рівня тут, Потім ви дійсно втратите це значення тут. Ось чому так важливо для вивантаження у вигляді дерева, щоб переконатися, що ви звільнити нижню першим. Що ви можете зробити, це сказати для кожного вузла Я хочу, щоб вивантажити все про дітей. Тепер, коли ми перейшли вивантаження для хеш-таблиці методів, а також методу синтаксичного дерева, ми збираємося хочете подивитися на Valgrind. Valgrind запуску за допомогою наступних команд. У вас є Valgrind-V. Ви перевіркою для всіх витоків при запуску правопису при такому певний текст тому що правопису необхідно прийняти в текстовий файл. Так Valgrind буде працювати ваша програма, сказати вам, скільки байтів виділяється, скільки байт ви звільнили, і він скаже вам чи ви звільнили достатньо або ви не досить вільно, або іноді ви можете навіть більш вільною, як вільний вузол, який вже був звільнений і тому він поверне вам помилок. Якщо ви використовуєте Valgrind, це дасть вам деякі повідомлення вказує, чи є ви звільнили або менше, ніж достатньо, достатньо, або більш ніж достатньо часу. Частина цієї PSET, це необов'язково, щоб кинути виклик Big Board. Але коли ми маємо справу з цими структурами даних це забавно бачити, як швидко і наскільки ефективні ваші дані структури могли б бути. Ваш хеш-функція в результаті багатьох зіткнень? Або ваш розмір даних дійсно великий? Чи означає це займе багато часу, щоб пройти? У журналі правопису, він виводить, скільки часу ви використовуєте для завантаження, , Щоб перевірити, провести розміру, і для розвантаження, і тому ті, розміщені в Великий рада, де ви можете конкурувати з однокласниками і деяких співробітників, щоб бачити, хто має найшвидші перевірки орфографії. Одна річ, яку я хотів би відзначити про хеш-таблиці те, що є деякі досить прості хеш-функції, які ми могли б подумати. Наприклад, у вас є 26 відер, і так кожен ківш відповідає першою літерою в слові, але це буде призводити до досить незбалансованим хеш-таблиці тому що є набагато менше слів, які починаються з X, ніж починати з M, наприклад. Один із способів йти про правопису, якщо ви хочете отримати всі інші функціональні вниз, потім просто використовувати простий хеш-функції, щоб мати можливість отримати код працює , А потім повернутися і змінити розмір хеш-таблиці і визначення. Є багато ресурсів в Інтернеті для хеш-функцій, і так для цього PSET вам дозволено для пошуку хеш-функції в Інтернеті для деяких натяків і натхнення тих пір, як ви переконаєтеся, щоб цитувати, де ви отримали його від. Ви завжди можете подивитися й інтерпретувати деякі хеш-функції, які ви знайдете в Інтернеті. Повернутися до цього, ви могли б побачити, якщо хтось використовував вигляді дерева Чи їх реалізація швидше, ніж ваш хеш-таблиці чи ні. Ви можете уявити Big Board кілька разів. Вона буде записувати самі останні записи. Тому, можливо, ви зміните своє хеш-функції, а потім зрозуміли, що це насправді набагато швидше або багато повільніше, ніж раніше. Це трохи кумедним способом. Там завжди 1 або 2 співробітників, які намагаються зробити мінімально можливий словник, так що це завжди цікаво дивитися. Використання для PSET є запуск правопису за допомогою додаткового словника , А потім обов'язкова текстовий файл. За замовчуванням при запуску правопису за допомогою всього лише текстовий файл і не вказати словник, він збирається використовувати файл словника текст, один великий в папці cs50/pset5/dictionaries. Це одна має більш 100000 слів. Вони також мають невеликий словник, який має значно менше слів CS50, що зробив для вас. Тим не менш, ви можете дуже легко просто зробити свій власний словник якщо ви просто хочете працювати в невеликих прикладів - Наприклад, якщо ви хочете використовувати GDB, і ви знаєте конкретні значення що ви хочете, щоб ваш хеш-таблиці, щоб намітити в. Так що ви просто можете зробити свій власний текстовий файл тільки з BAR, BAZ, FOO, і FOOBAR, зробити це в текстовому файлі, відокремити тих, кожна з 1 лінія, , А потім зробити свій власний текстовий файл, який містить тільки буквально, може бути 1 або 2 слів так що ви точно знаєте, що висновок повинен бути. Деякі файли зразків тексту, які Великої ради при запуску завданням буде перевірити є Війна і мир роману Джейн Остін або щось на зразок цього. Отже, коли ви починаєте, це набагато легше зробити свої власні текстові файли , Які містять лише кілька слів або, може бути 10 так що ви можете передбачити, який результат має бути , А потім перевірити його проти цього, так ще контрольованої приклад. І так, оскільки ми маємо справу з прогнозування та розроблення речей навколо, я знову хочу закликати вас використовувати ручку і папір тому що насправді відбувається, щоб допомогти вам з цим - малювати стрілки, як хеш-таблиці або як ваш Trie виглядає, коли ви щось звільнення де стрілки йдуть, Ви тримаючись досить, ви бачите всі посилання зникають і падіння в безодню витік пам'яті. Так що, будь ласка, спробуйте намалювати речі, навіть перш ніж потрапити до написання коду вниз. Нічия речі, щоб зрозуміти, як все буде працювати тому що тоді я гарантую, що ви будете працювати в меншій плутанини покажчик там. Добре. Я хочу побажати вам удачі з цим PSET. Це, напевно, один з найважчих. Тому постарайтеся, щоб почати рано, малювати речі, малювати речі, і удачі. Це було Покрокове керівництво 5. [CS50.TV]