哈希--常見的演算法介紹
哈希(Hash)又稱為散列,它是一個很常見的演算法。在Java的HashMap資料結構中主要就利用了雜湊。哈希演算法包括了哈希函數和哈希表兩部分。我們陣列的特性可以知道,可以透過下標快速(O(1))的定位元素,同理在雜湊表中我們可以透過鍵(雜湊值)快速的定位某個值,這個哈希值的計算就是透過哈希函數(hash(key) = address )計算出來的。透過雜湊值即能定位元素[address] = value,原理同數組類似。
最好的雜湊函數當然是每個key值都能計算出唯一的雜湊值,但往往可能存在不同的key值的雜湊值,這就造成了衝突,評判一個雜湊函數是否設計良好的兩個面向:
## 1.衝突少。
2.計算快。
下面給出幾種常用的雜湊函數,它們的背後都有一定的數學原理且經過大量實踐,其數學原理不在這裡探究。BKDR雜湊函數(h = 31 * h + c)
# 這個雜湊函數被應用在Java的字串雜湊值計算。
//String#hashCodepublic int hashCode() {int h = hash;if (h == 0 && value.length > 0) {char val[] = value;for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; //BKDR 哈希函数,常数可以是131、1313、13131…… } hash = h; }return h; }
#DJB2 雜湊函數(#h = h << 5 + h + c = h = 33 * h + c)
ElasticSearch就利用了DJB2雜湊函數對要索引文件的指定key#進行雜湊。
SDBM雜湊函數(SDBM雜湊函數(h = h << 6 + h << 16 - h + c = 65;< 16 - h + c = 65;< 16 - h + c = 6555599999999999999 * h + c
)
# 在SDBM
(簡單的資料庫引擎)中被應用。 以上只是列舉了三種雜湊函數,我們做下試驗,看看它們的衝突情況是怎麼樣的。
##100萬、200萬的衝突數情況:
############### 反覆試驗實際上三種雜湊函數的衝突數差不多。 ###### ######Python######3############
1 package com.algorithm.hash; 2 3 import java.util.HashMap; 4 import java.util.UUID; 5 6 /** 7 * 三种哈希函数冲突数比较 8 * Created by yulinfeng on 6/27/17. 9 */10 public class HashFunc {11 12 public static void main(String[] args) {13 int length = 1000000; //100万字符串14 //利用HashMap来计算冲突数,HashMap的键值不能重复所以length - map.size()即为冲突数15 HashMap<String, String> bkdrMap = new HashMap<String, String>();16 HashMap<String, String> djb2Map = new HashMap<String, String>();17 HashMap<String, String> sdbmMap = new HashMap<String, String>();18 getStr(length, bkdrMap, djb2Map, sdbmMap);19 System.out.println("BKDR哈希函数100万字符串的冲突数:" + (length - bkdrMap.size()));20 System.out.println("DJB2哈希函数100万字符串的冲突数:" + (length - djb2Map.size()));21 System.out.println("SDBM哈希函数100万字符串的冲突数:" + (length - sdbmMap.size()));22 }23 24 /**25 * 生成字符串,并计算冲突数26 * @param length27 * @param bkdrMap28 * @param djb2Map29 * @param sdbmMap30 */31 private static void getStr(int length, HashMap<String, String> bkdrMap, HashMap<String, String> djb2Map, HashMap<String, String> sdbmMap) {32 for (int i = 0; i < length; i++) {33 System.out.println(i);34 String str = UUID.randomUUID().toString();35 bkdrMap.put(String.valueOf(str.hashCode()), str); //Java的String.hashCode就是BKDR哈希函数, h = 31 * h + c36 djb2Map.put(djb2(str), str); //DJB2哈希函数37 sdbmMap.put(sdbm(str), str); //SDBM哈希函数38 }39 }40 41 /**42 * djb2哈希函数43 * @param str44 * @return45 */46 private static String djb2(String str) {47 int hash = 0;48 for (int i = 0; i != str.length(); i++) {49 hash = hash * 33 + str.charAt(i); //h = h << 5 + h + c = h = 33 * h + c50 }51 return String.valueOf(hash);52 }53 54 /**55 * sdbm哈希函数56 * @param str57 * @return58 */59 private static String sdbm(String str) {60 int hash = 0;61 for (int i = 0; i != str.length(); i++) {62 hash = 65599 * hash + str.charAt(i); //h = h << 6 + h << 16 - h + c = 65599 * h + c63 }64 return String.valueOf(hash);65 }66 }
雜湊表是一種資料結構,它需要配合雜湊函數使用,用於建立索引,以便快速查找——#《演算法筆記》。一般來講它就是一個定長的儲存空間,例如HashMap預設的雜湊表就是定長為16#的Entry陣列。有了定長的儲存空間過後,剩下的問題就是如何將值放入哪個位置,通常如果雜湊值是m,長度為 n,那麼這個值就放到m mod n位置。
上圖是雜湊和雜湊表,以及產生衝突的解決方法(拉鍊法)。產生衝突後的解決辦法有很多,有再哈希一次直到沒有衝突,也有向上圖一樣採用拉鍊法利用鍊錶將相同位置的元素串聯。
想像一下,上面的例子哈希表的長度為10,產生了##1次衝突,如果哈希表長度為20,那麼就不會產生衝突查找更快但會浪費更多空間,如果雜湊表長度為2,將會倒置3次衝突查找更慢但這樣又會節省不少空間。 所以哈希表的長度選擇至關重要,但同時也是一個重要的難題。
補充:
哈希在很多方面有應用,例如在不同的值有不同的雜湊值,但也可以將雜湊演算法設計精妙使得相似或相同的值有相似或相同的雜湊值。也就是說如果兩個物件完全不同,那麼它們的雜湊值也完全不同;如果兩個物件完全相同,那麼它們的雜湊值也完全相同;兩個物件越相似,那麼它們的雜湊值也就越相似。這其實就是相似性問題,也就是說這個想法可以被推廣應用在相似性的計算(例如Jaccard距離問題),最後應用到廣告精準投放、商品推薦等。
另外,一致性雜湊也可應用在負載平衡,如何保證每台伺服器能均勻的分攤負載壓力,一個好的雜湊演算法也可做到。
以上是哈希--常見的演算法介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用C++中的雜湊搜尋演算法雜湊(Hash)搜尋演算法是一種高效的查找和儲存技術,它將關鍵字透過雜湊函數轉換為固定長度的索引,然後利用這個索引在資料結構中進行搜尋。在C++中,我們可以透過使用標準函式庫中的雜湊容器和雜湊函數來實作哈希搜尋演算法。本文將介紹如何使用C++中的雜湊搜尋演算法,並提供具體的程式碼範例。引入頭檔和命名空間首先,在使用C++中的雜湊搜尋算

如何用Python寫哈希查找演算法?哈希查找演算法,又稱為雜湊查找演算法,是一種基於哈希表的資料查找方法。相較於線性查找和二分查找等傳統查找演算法,哈希查找演算法具有更高的查找效率。在Python中,我們可以使用字典(dictionary)來實作雜湊表,進而實作雜湊查找。哈希查找演算法的基本想法是將待查找的關鍵字透過雜湊函數轉換成索引值,然後根據索引值在雜湊表中查

Python底層技術揭秘:如何實作雜湊演算法,需要具體程式碼範例摘要:雜湊演算法是電腦領域中常用的技術之一,用於快速確定資料的唯一識別。 Python作為一門高階語言,提供了許多內建的雜湊函數,如hash()函數以及各種雜湊演算法的實作。本文將揭示哈希演算法的原理和Python底層實現的細節,並提供具體的程式碼範例。哈希演算法簡介哈希演算法,又稱雜湊演算法,是一種將任意長度的

在了解比特幣投資和區塊鏈技術中,哈希演算法可以說經常出現,幣圈戲言饒舌有嘻哈,演算法有哈希。關於「演算法」一詞,目前國內用戶使用的比較模糊,有時指共識機制,有時指具體的Hash演算法,作為區塊鏈演算法,哈希演算法一直讓一般大眾感到晦澀難懂,那麼,什麼是哈希算法?接下來幣圈子小編就來跟大家通俗的講解一下哈希演算法是什麼?希望能夠讓投資人看完這篇文章就能讀懂哈希演算法。什麼是哈希演算法?哈希音譯自“Hash”,又稱為“雜湊”。本質上是一種電腦程序,可接收任意

在今天的數位時代中,隨著網路的發展和資訊的日益重要,資料的保密性和安全性變得越來越重要。為了確保資料在傳輸過程中不會被竊取或篡改,PHP開發人員通常使用加密和雜湊技術來保護敏感資料。本文將介紹PHP開發中最常用的加密和雜湊技術,以及它們的優缺點。一、加密技術加密是一種保護資料安全性的技術,它使用演算法將資料轉換為無意義的形式。只有持有密鑰的人才能將其還原為可讀

哈希函數是可用於將任意大小的資料映射到固定大小的資料的任何函數。哈希函數傳回的值稱為哈希值、哈希代碼、摘要或簡稱為哈希。語法stringhash(string$algo,string$data[,bool$raw_output=FALSE])參數algo所選雜湊演算法的名稱(如「md5」、「sha256」、「haval160,4」等)data要散列的消息。 raw_output設定為TRUE時,輸出原始二進位資料。 FALSE輸出小寫十六進位。範例<?php  

如何處理記帳系統中的雜湊和加密功能-使用PHP實現哈希和加密的開發方法引言:隨著數位化時代的到來,各種資訊系統的安全性變得越發重要。在設計和開發記帳系統時,保護用戶隱私資料是至關重要的。其中,使用哈希和加密功能可以有效地保護用戶的敏感資訊。本文將介紹如何使用PHP實作記帳系統中的雜湊和加密功能,並提供具體的程式碼範例。一、哈希功能的實作哈希是一種單向加密算

介紹在當今快節奏且互聯的數位化世界中,確保應用程式的高可用性至關重要。負載平衡技術使應用程式能夠在多個伺服器上分發傳入流量,從而提高效能和可靠性。 PHP提供了一系列負載平衡技術的支持,每種技術都具有其獨特的優勢和限制。輪詢(RoundRobin)輪詢是一種簡單而有效的負載平衡技術,它將請求按順序分發到伺服器池。這種方法易於實現,並且可以保證請求在伺服器之間均勻分佈。 $servers=array("server1","server2","server3");$index=0;while(true)
