目錄
散列的一些術語(可以簡單的看一下)
常用的雜湊函數
建構散列表
散列表的組成
初始化
雜湊函數
加上
刪除
找出
总结
补充一个小知识点
首頁 web前端 js教程 JavaScript中散列表(哈希表)的詳細介紹(程式碼範例)

JavaScript中散列表(哈希表)的詳細介紹(程式碼範例)

Jan 02, 2019 am 09:37 AM
javascript node.js 資料結構

這篇文章帶給大家的內容是關於JavaScript中散列表(哈希表)的詳細介紹(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

散列表

散列表(Hash table,也叫雜湊表),是根據鍵(Key)而直接存取在記憶體儲存位置的資料結構。也就是說,它透過計算一個關於鍵值的函數,將所需查詢的資料映射到表中一個位置來存取記錄,這加快了查找速度。這個映射函數稱做雜湊函數,存放記錄的數組稱為做散列表。

JavaScript中散列表(哈希表)的詳細介紹(程式碼範例)

我們從上圖開始分析

  • #有一個集合U,裡面分別是1000,10,152, 9733,1555,997,1168

  • #右邊是一個10個插槽的列表(散列表),我們需要把集合U中的整數存放到這個列表中

  • 怎麼存放,分別存在哪個槽裡?這個問題就是需要透過一個雜湊函數來解決了。我的存放方式是取10的餘數,我們對應這張圖來看

    • #1000 =0,10 =0 那麼1000和10這兩個整數就會被儲存到編號為0的這個槽中

    • #152 =2那麼就存放到2的槽中

    • 9733 =3存放在編號為3的槽中

透過上面簡單的例子,應該會有幾個大致的理解

  • #集合U,就是可能會出現在散列表中的鍵

  • #散列函數,就是你自己設計的一種如何將集合U中的鍵值透過某種計算存放到散列表中,如例子中的取餘數

  • 散列表,存放著通過計算後的鍵

那我們在接著看一般我們會怎麼去取值呢?

例如我們儲存一個key為1000,value為'張三' ---> {key:1000,value:'張三'}
從我們上述的解釋,它是不是應該存放在1000 的這個插槽。
當我們透過key想要找到value張三,是不是到key 這個插槽裡找就可以了呢?你到了這裡可以停下來思考一下。

散列的一些術語(可以簡單的看一下)

  • 散列列表中所有可能出現的鍵稱作全集U

  • #用M表示槽的數量

  • 給定一個鍵,由雜湊函數計算它應該出現在哪個槽中,上面例子的雜湊函數h=k% M,散列函數h就是鍵k到槽的一個映射。

  • 1000和10都被存到了編號0的這個槽中,這種情況稱之為碰撞。

看到這裡不知道你是否大致理解了雜湊函數是什麼了沒。透過例子,再透過你的思考,你可以回頭在讀一遍文章頭部關於散列表的定義。如果你能讀懂了,那我估計你應該是懂了。

常用的雜湊函數

處理整數h=>k%M (也就是我們上面所舉的例子)

處理字串:

    function h_str(str,M){
        return [...str].reduce((hash,c)=>{
            hash = (31*hash + c.charCodeAt(0)) % M
        },0)
    }
登入後複製

hash演算法不是這裡的重點,我也沒有很深入的去研究,這裡主要還是去理解散列表是個怎樣的資料結構,它有哪些優點,它具體做了怎樣一件事。
而hash函數它只是透過某種演算法把key映射到列表中。

建構散列表

透過上面的解釋,我們在這裡做一個簡單的散列表

散列表的組成

  • M個槽

  • 有個hash函數

  • #有一個add方法去把鍵值加到散列表中

  • #有一個delete方法去做刪除

  • 有一個search方法,根據key去找到對應的值

初始化

- 初始化散列表有多少個槽
- 用一個陣列來建立M個槽

    class HashTable {
        constructor(num=1000){
            this.M = num;
            this.slots = new Array(num);
        }
    }
登入後複製

雜湊函數

處理字串的雜湊函數,這裡使用字串是因為,數值也可以傳換成字串比較通用一些

先將傳遞過來的key值轉為字串,為了能夠嚴謹一些

將字串轉換為數組, 例如'abc' => [...'abc'] => ['a','b','c']

分別對每個字元的charCodeAt進行計算,取M餘數是為了剛好對應插槽的數量,你總共就10個槽,你的數值 肯定會落到0-9的槽裡

    h(str){
        str = str + '';
        return [...str].reduce((hash,c)=>{
            hash = (331 * hash + c.charCodeAt()) % this.M;
            return hash;
        },0)
    }
登入後複製

加上

呼叫hash函數得到對應的儲存位址(就是我們之間類比的槽)

因為一個槽中可能會存多個值,所以需要用一個二維數組去表示,例如我們計算得來的槽的編號是0,也就是slot[0],那麼我們應該往slot[0] [0]裡存,後面進來的同樣是編號為0的槽的話就接著往slot[0] [1]裡存

    add(key,value) {
        const h = this.h(key);
        // 判断这个槽是否是一个二维数组, 不是则创建二维数组
        if(!this.slots[h]){
            this.slots[h] = [];
        }
        // 将值添加到对应的槽中
        this.slots[h].push(value);
    }
登入後複製

刪除

透過hash演算法,找到所在的槽

透過過濾來刪除

    delete(key){
        const h = this.h(key);
        this.slots[h] = this.slots[h].filter(item=>item.key!==key);
    }
登入後複製

找出

透過hash演算法找到對應的槽

用find函數去找同一個key的值

傳回對應的值

    search(key){
        const h = this.h(key);
        const list = this.slots[h];
        const data = list.find(x=> x.key === key);
        return data ? data.value : null;    
    }
登入後複製

总结

讲到这里,散列表的数据结构已经讲完了,其实我们每学一种数据结构或算法的时候,不是去照搬实现的代码,我们要学到的是思想,比如说散列表它究竟做了什么,它是一种存储方式,可以快速的通过键去查找到对应的值。那么我们会思考,如果我们设计的槽少了,在同一个槽里存放了大量的数据,那么这个散列表它的搜索速度肯定是会大打折扣的,这种情况又应该用什么方式去解决,又或者是否用其他的数据结构的代替它。

补充一个小知识点

v8引擎中的数组 arr = [1,2,3,4,5] 或 new Array(100) 我们都知道它是开辟了一块连续的空间去存储,而arr = [] , arr[100000] = 10 这样的操作它是使用的散列,因为这种操作如果连续开辟100万个空间去存储一个值,那么显然是在浪费空间。


以上是JavaScript中散列表(哈希表)的詳細介紹(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1325
25
PHP教程
1272
29
C# 教程
1252
24
使用Java函數比較進行複雜資料結構比較 使用Java函數比較進行複雜資料結構比較 Apr 19, 2024 pm 10:24 PM

Java中比較複雜資料結構時,使用Comparator提供靈活的比較機制。具體步驟包括:定義比較器類,重寫compare方法定義比較邏輯。建立比較器實例。使用Collections.sort方法,傳入集合和比較器實例。

Java資料結構與演算法:深入詳解 Java資料結構與演算法:深入詳解 May 08, 2024 pm 10:12 PM

資料結構與演算法是Java開發的基礎,本文深入探討Java中的關鍵資料結構(如陣列、鍊錶、樹等)和演算法(如排序、搜尋、圖演算法等)。這些結構透過實戰案例進行說明,包括使用陣列儲存分數、使用鍊錶管理購物清單、使用堆疊實現遞歸、使用佇列同步執行緒以及使用樹和雜湊表進行快速搜尋和身份驗證等。理解這些概念可以編寫高效且可維護的Java程式碼。

深入了解Go語言中的引用類型 深入了解Go語言中的引用類型 Feb 21, 2024 pm 11:36 PM

引用類型在Go語言中是一種特殊的資料類型,它們的值並非直接儲存資料本身,而是儲存資料的位址。在Go語言中,引用型別包括slices、maps、channels和指標。深入了解引用類型對於理解Go語言的記憶體管理和資料傳遞方式至關重要。本文將結合具體的程式碼範例,介紹Go語言中引用類型的特點和使用方法。 1.切片(Slices)切片是Go語言中最常用的引用類型之一

PHP資料結構:AVL樹的平衡之道,維持高效有序的資料結構 PHP資料結構:AVL樹的平衡之道,維持高效有序的資料結構 Jun 03, 2024 am 09:58 AM

AVL樹是一種平衡二元搜尋樹,確保快速且有效率的資料操作。為了實現平衡,它執行左旋和右旋操作,調整違反平衡的子樹。 AVL樹利用高度平衡,確保樹的高度相對於節點數始終較小,從而實現對數時間複雜度(O(logn))的查找操作,即使在大型資料集上也能保持資料結構的效率。

Java集合框架全解析:解剖資料結構,揭秘高效率儲存之道 Java集合框架全解析:解剖資料結構,揭秘高效率儲存之道 Feb 23, 2024 am 10:49 AM

Java集合框架概述Java集合框架是Java程式語言的重要組成部分,它提供了一系列可以儲存和管理資料的容器類別庫。這些容器類別庫具有不同的資料結構,可以滿足不同場景下的資料儲存和處理需求。集合框架的優點在於它提供了統一的接口,使得開發人員可以使用相同的方式來操作不同的容器類別庫,從而降低了開發難度。 Java集合框架的資料結構Java集合框架中包含多種資料結構,每種資料結構都有其獨特的特性和適用場景。以下是幾種常見的Java集合框架資料結構:1.List:List是一個有序的集合,它允許元素重複。 Li

基於哈希表的資料結構優化PHP數組交集和並集的計算 基於哈希表的資料結構優化PHP數組交集和並集的計算 May 02, 2024 pm 12:06 PM

利用雜湊表可最佳化PHP數組交集和並集計算,將時間複雜度從O(n*m)降低到O(n+m),具體步驟如下:使用雜湊表將第一個數組的元素映射到布林值,以快速找出第二個陣列中元素是否存在,提高交集計算效率。使用雜湊表將第一個陣列的元素標記為存在,然後逐一新增第二個陣列的元素,忽略已存在的元素,提高並集計算效率。

PHP SPL 資料結構:為你的專案注入速度與彈性 PHP SPL 資料結構:為你的專案注入速度與彈性 Feb 19, 2024 pm 11:00 PM

PHPSPL資料結構庫概述PHPSPL(標準php庫)資料結構庫包含一組類別和接口,用於儲存和操作各種資料結構。這些資料結構包括數組、鍊錶、堆疊、佇列和集合,每個資料結構都提供了一組特定的方法和屬性,用於操縱資料。數組在PHP中,數組是儲存一系列元素的有序集合。 SPL數組類別提供了對原生的PHP數組進行加強的功能,包括排序、過濾和映射。以下是使用SPL陣列類別的範例:useSplArrayObject;$array=newArrayObject(["foo","bar","baz"]);$array

Golang 和 Node.js 在後端開發的對比 Golang 和 Node.js 在後端開發的對比 Jun 03, 2024 pm 02:31 PM

Go和Node.js在類型化(強/弱)、並發(goroutine/事件循環)、垃圾收集(自動/手動)上有差異。 Go具備高吞吐量、低延遲,適用於高負載後端;Node.js擅長異步I/O,適合高並發、短請求。兩者的實戰案例包括Kubernetes(Go)、資料庫連線(Node.js)、網路應用程式(Go/Node.js)。最終選擇取決於應用程式需求、團隊技能和個人偏好。

See all articles