ROB BOWDEN:你好。 我搶,讓我們散 這個解決方案了。 所以在這裡我們要實現 一般的哈希表。 我們看到,我們的散列的結構節點 表是要這個樣子。 因此,這將有一個char字 數組大小長度加1。 不要忘了,因為最大的1 字在字典中是45 字符,然後我們要 需要一個額外的字符 反斜杠0。 然後在我們的每一個哈希表 鬥將要存儲 節點鍊錶。 我們沒有做線性探測在這裡。 所以為了鏈接到下一個 在桶的元素,我們需要一個 結構節點*未來。 所以,這就是一個節點的樣子。 現在,這裡是聲明 我們的哈希表。 這將有16,384桶,但 這個數字其實並不重要。 最後,我們將有 全局變量hashtable_size,這 即將為0開始關閉,它的 要跟踪多少字 是在我們的字典。 好的。 因此,讓我們來看看負荷。 所以請注意,負載, 它返回一個布爾值。 您將返回true,如果它是成功的 加載,否則為false。 它需要一個為const char *星級 字典,它是詞典 我們要打開。 所以這是第一件事情 我們要做的。 我們要去給fopen的字典 讀,我們將有 以確保它成功,所以如果 它返回NULL,那麼我們就沒有 成功打開詞典 我們需要返回false。 但假設它確實成功 開放的,那麼我們要讀取的 字典。 因此,保持循環,直到我們找到了一些 理由打破這種 循環,我們拭目以待。 因此,保持循環,現在我們要去 將malloc的單個節點。 當然,我們需要錯誤檢查 再所以,如果mallocing沒有成功 我們要卸載的任何節點,我們 碰巧的malloc之前,請關閉 字典和返回false。 但是忽略了,假設我們 成功了,那麼我們要使用的fscanf 從讀一個字我們 字典到我們的節點。 因此請記住入門>字是字符 大小長度的字緩衝區加 一個我們要去 字存儲英寸 所以的fscanf會返回1,只要 因為它能夠成功讀取 字從該文件。 如果任何一個錯誤發生,否則我們到達 該文件的結束時,它不會 返回1在這種情況下,如果它不 返回1,我們終於要打破 出這個while循環的。 所以我們看到,一旦我們成功 讀一個字到 入門>字,那麼我們將散列 使用我們的哈希函數這個詞。 讓我們來看看 散列函數。 所以,你並不真的需要 要理解這一點。 而實際上,我們只是拉這 從互聯網散列函數。 你需要認識到的唯一一件事就是 這需要為const char *的話, 所以它採取一個字符串作為輸入,並 返回一個unsigned int作為輸出。 所以這就是所有的散列函數,它是 發生在一個輸入,它給你一個 索引的哈希表。 請注意,我們通過NUM_BUCKETS改裝 所以返回的哈希值 實際上是一個索引,哈希表 並沒有索引超出了 陣列的界限。 因此,考慮到哈希函數,我們將 散列,我們讀單詞 從字典中,然後我們要去 使用具有插入 進入哈希表。 現在,哈希表散列是當前 鍊錶哈希表中,並 這是非常可能的,僅僅是NULL。 我們要插入我們在入口 開始這個鍊錶,等等 我們將有我們的當前條目 指向什麼樣的哈希表現 點,然後我們要存儲 在哈希哈希表中 當前條目。 所以,這兩條線插入成功 在本月初的入口 鍊錶的索引處 在哈希表。 一旦我們與該做的,我們知道 我們發現了另一個字的 字典和我們增加了。 因此,我們繼續這樣做,直到的fscanf 最後返回非的東西在1 這一點請記住,我們需要 免費入場,所以在這裡,我們malloced的 進入我們試著讀的東西 從字典。 我們沒有成功地讀 從字典的東西在其中 情況下,我們需要釋放進入我們 從來沒有真正投入到哈希表 終於攻破。 一旦我們突破了,我們需要看到,好了, 我們沒有打出來,因為有 從該文件中讀出錯誤,或 我們沒有打出來,因為我們到達 該文件的末尾? 如果出現了錯誤,那麼我們要 返回false,因為負載沒有 成功,並在這個過程中,我們要 卸載所有我們讀的話 在並關閉字典文件。 假設我們沒有成功,那麼我們就 仍然需要關閉字典 文件,最後返回,因為真正的 我們已經成功地加載了 字典。 這就是它的負載。 所以,現在檢查,給出一個加載哈希表, 是要這個樣子。 因此,檢查時,它返回一個布爾值,它 將要指示是否 傳入的char *的話,是否 傳入的字符串是在我們的字典。 因此,如果它是在字典中,如果是 在我們的哈希表,我們將返回 真的,如果不是的話, 我們將返回false。 鑑於這種傳入的字,我們 要哈希的話。 現在,認識到一個重要的事情是 在負載時,我們知道,所有的 的話打算是小寫, 但在這裡,我們不是那麼肯定。 如果我們看一看我們的哈希函數, 我們的哈希函數實際上 是小寫的每個字符 的話。 所以不管資本化 總之,我們的哈希函數是要 返回相同的指數無論 資本是因為它會 返回一個完全小寫 版的字。 好的。 所以這是我們的索引。 這是這個詞的哈希表。 現在,這個for循環是怎麼回事 過度鍊錶 這是該索引。 所以請注意,我們初始化入口 指向該索引。 我們將繼續,而不會進入 不等於NULL,並且記住, 更新指針在我們的鍊錶 入門等於入門>下一個,所以有 我們目前的入口點 在鍊錶中下一個項目。 好的。 因此,對於在該鏈接的表的每個條目, 我們將使用strcasecmp。 這不是strcmp函數,因為我們再次 想要做的事情的情況下不區分大小寫。 因此我們使用strcasecmp比較字 被傳遞給這個函數 對詞 在這個條目。 如果返回0,這意味著有 一個匹配,在這種情況下,我們希望 返回true。 我們成功地找到了 字在我們的哈希表。 如果有不匹配,那麼我們 再次要循環,並期待在 下一個條目。 我們將繼續循環,同時有 在此鍊錶條目。 如果我們分手會發生什麼 出這個for循環? 這意味著我們沒有發現一個條目, 匹配這個詞,在這種情況下, 我們返回false,表明我們的 哈希表中沒有包含這個詞。 就是這樣的檢查。 好的。 因此,讓我們來看看大小。 現在,大小將是非常簡單的 因為記得在負載,每個字 我們發現,我們增加一個全球性的 變量hashtable_size。 因此,大小的功能僅僅是 要返回全球 變量,就是這樣。 現在,終於,我們需要卸載 字典曾經的一切的完成。 那麼我們如何做到這一點? 在這裡,我們遍歷所有 我們的哈希表的桶。 因此,有NUM_BUCKETS桶。 並為每個鍊錶在我們的散列 表中,我們要遍歷所有的 鍊錶的全部 釋放每個元素。 現在,我們需要小心,所以在這裡我們 有一個臨時變量,它是 存儲指針指向下一個 元件中的鍊錶。 然後我們將免費 當前元素。 我們需要確保我們做到這一點,因為我們 不能只釋放當前元素 然後再試著訪問下一個指針 因為一旦我們釋放它 內存變為無效。 因此,我們需要保持周圍的指針 下一個元素,那麼我們就可以釋放 當前元素,然後我們就可以更新 我們目前的元素指向 下一個元素。 我們將循環而有元素 在此鍊錶。 我們將做到這一點的所有鏈接的列表中 哈希表,有一次我們就大功告成了 這樣,我們已經完全卸載 哈希表,我們就大功告成了。 所以這是不可能卸載到永遠 返回false,而當我們完成後,我們 剛剛返回true。