簡體   English   中英

哈希:內部如何運作?

[英]Hash : How does it work internally?

這聽起來可能是一個非常模糊的問題,但事實並非如此。 我在維基上經歷過Hash函數描述,但理解它並不是很有幫助。

我正在尋找像Hashing這樣相當復雜的主題的簡單答案。 這是我的問題:

  1. 哈希是什么意思? 它在內部如何運作?
  2. 它遵循什么算法?
  3. HashMapHashTableHashList什么HashList
  4. “恆定時間復雜度”是什么意思?為什么哈希的不同實現會給出恆定的時間操作?
  5. 最后,為什么在大多數面試問題HashLinkedList被問到,是否有任何特定的邏輯來測試受訪者的知識?

我知道我的問題清單很大但我真的很感激,如果我能夠對這些問題得到一些明確的答案,我真的想了解這個主題。

  1. 是關於散列的一個很好的解釋。 例如,您希望存儲字符串“Rachel”,您將哈希函數應用於該字符串以獲取內存位置。 myHashFunction(key: "Rachel" value: "Rachel") --> 10 該函數可能會為輸入“Rachel”返回10,因此假設您有一個大小為100的數組,則將“Rachel”存儲在索引10處。如果要檢索該元素,只需調用GetmyHashFunction("Rachel") ,它將返回10注意,對於此示例,鍵是“Rachel”,值是“Rachel”,但您可以使用該鍵的另一個值,例如出生日期或對象。 您的哈希函數可能會為兩個不同的輸入返回相同的內存位置,在這種情況下,如果您要實現自己的哈希表,則可能會發生沖突,您可能需要使用鏈表或其他技術來處理此問題。

  2. 以下是一些常用的哈希函數。 良好的散列函數滿足:每個鍵同樣可能散列到n個內存插槽中的任何一個,與任何其他鍵散列到的位置無關。 其中一種方法稱為除法。 我們通過將k的余數除以n,將密鑰k映射到n個時隙之一。 h(k) = k mod n 例如,如果您的數組大小為n = 100且您的密鑰是整數k = 15那么h(k) = 10

  3. Hashtable是同步的,Hashmap不是。 Hashmap允許將空值作為鍵,但Hashtable不允許。

  4. 哈希表的目的是在添加和獲取元素時具有O(c)恆定的時間復雜度。 在大小為N的鏈表中,如果要獲取最后一個元素,則必須遍歷所有列表,直到獲得它為止,因此復雜度為O(N)。 使用哈希表如果要檢索元素,只需傳遞密鑰,哈希函數將返回所需的元素。 如果哈希函數很好地實現,它將處於恆定時間O(c)這意味着你不必遍歷存儲在哈希表中的所有元素。 您將立即獲得該元素。

  5. 程序員/開發人員計算機科學家需要了解數據結構和復雜性=)

  1. 散列意味着生成表示值的(希望)唯一數字。
  2. 不同類型的值( IntegerString等)使用不同的算法來計算哈希碼。
  3. HashMap和HashTable是地圖 ; 它們是unqiue鍵的集合,每個鍵都與一個值相關聯。
    Java沒有HashList類。 is a set of unique values. 哈希是一組唯一值。
  4. 從哈希表中獲取項目是關於表的大小的恆定時間。
    對於被散列的值,計算散列不一定是恆定時間。
    例如,計算字符串的散列涉及迭代字符串,而不是關於字符串大小的常量時間。
  5. 這些是人們應該知道的事情。
  1. Hashing正在將給定實體(在java術語中 - 一個對象)轉換為某個數字(或序列)。 哈希函數是不可逆的 - 即您無法從哈希中獲取原始對象。 在內部實現它(對於java.lang.Object ,通過JVM獲取一些內存地址)。

  2. JVM地址是不重要的細節。 每個類都可以使用自己的算法覆蓋hashCode()方法。 Modren Java IDE允許生成好的hashCode方法。

  3. Hashtable和hashmap是一回事。 它們是鍵值對,其中鍵是經過哈希處理的。 散列列表和散列集不存儲值 - 僅存儲鍵。

  4. 常量時間意味着無論哈希表(或任何其他集合)中有多少條目,通過其鍵查找給定對象所需的操作數是不變的。 那是-1,或接近1

  5. 這是基本的計算機科學材料,並且假設每個人都熟悉它。 我認為谷歌已經指定哈希表是計算機科學中最重要的數據結構。

我將嘗試簡單解釋散列及其用途。

首先,考慮一個簡單的清單。 此類列表上的每個操作(插入,查找,刪除)都具有O(n)復雜性,這意味着您必須解析整個列表(或平均一半)才能執行此類操作。

散列是一種非常簡單有效的加速方法:考慮我們將整個列表分成一組小列表。 一個這樣的小列表中的項目將有一些共同點,這個東西可以從密鑰中推斷出來。 例如,通過列出名稱,我們可以使用第一個字母作為質量,選擇要在哪個小列表中查找。 通過這種方式,通過按鍵的第一個字母對數據進行分區,我們獲得了一個簡單的哈希,它可以將整個列表拆分成~30個較小的列表,這樣每個操作都需要O(n)/ 30次。

但是,我們可以注意到結果並不完美。 首先,它們只有30個,我們無法改變它。 其次,有些字母的使用頻率高於其他字母,因此帶有YZ的集合將遠小於帶有A的集合。 為了獲得更好的結果,最好找到一種方法來分割大小相同的項目。 我們怎么能解決這個問題? 這是您使用哈希函數的地方。 這是一個能夠創建任意數量的分區的功能,每個分區的項目數大致相同。 在我們的名字示例中,我們可以使用類似的東西

int hash(const char* str){
    int rez = 0;
    for (int i = 0; i < strlen(str); i++)
        rez = rez * 37 + str[i];
    return rez % NUMBER_OF_PARTITIONS;
};

這將確保非常均勻的分布和可配置數量的集合(也稱為桶)。

Hashing是什么意思,它在內部如何運作?

散列是字符串較短的固定長度值或表示原始字符串的鍵的轉換。 它沒有索引。 哈希的核心是哈希表。 它包含一系列項目。 散列表包含數據項密鑰的索引,並使用此索引將數據放入數組中。

它遵循什么算法?

簡單來說,大多數哈希算法都使用邏輯“index = f(key,arrayLength)”

最后,為什么在大多數面試問題Hash和LinkedList被問到,是否有任何特定的邏輯來測試受訪者的知識?

它是關於你在邏輯推理上有多好。 這是每個程序員都知道的最重要的數據結構。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM