摘要:哈希表也是種數(shù)據(jù)結(jié)構(gòu),它可以提供快速的插入操作和查找操作。一個(gè)更好的散列函數(shù)為了避免碰撞,首先要確保散列表中用來(lái)存儲(chǔ)數(shù)據(jù)的數(shù)組其大小是個(gè)質(zhì)數(shù),這和計(jì)算散列值時(shí)使用的取余運(yùn)算有關(guān)。散列函數(shù)將學(xué)生里的數(shù)字相加,使用函數(shù)計(jì)算出散列值。
什么是字典結(jié)構(gòu)?
字典是以鍵值對(duì)形式存儲(chǔ)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),就像電話號(hào)碼薄里的名字和電話號(hào)碼那樣的一一對(duì)應(yīng)的關(guān)系。
javascript的Object類就是以這樣的一種字典形式設(shè)計(jì)的。
鍵值對(duì)在字典中以這樣的方式標(biāo)記:d = {key1 : value1, key2 : value2 }。字典中的鍵/值對(duì)是沒(méi)有順序的。如果你想要一個(gè)特定的順序,那么你應(yīng)該在使用前自己對(duì)它們排序。
Dictionary類Dictionary類的基礎(chǔ)是Array類,而不是Object類。我們想對(duì)字典中的鍵排序,而在js中是不能對(duì) 對(duì)象 的屬性進(jìn)行排序的。話雖如此,但在js中一切皆對(duì)象,數(shù)組也是對(duì)象。以下面的代碼開始定義Dictionary類:
先來(lái)定義add()方法。該方法接受兩個(gè)參數(shù):鍵和值。鍵是值在字典中的索引,代碼如下:
function add(key,value){ this.datastore[key] = value; }
接下來(lái)定義find()方法,該方法以 鍵 做為參數(shù),返回和其關(guān)聯(lián)的值。代碼如下:
function find(key){ return this.datastore[key]; }
從字典中刪除鍵-值對(duì) 需要使用js中的delete函數(shù)。該函數(shù)是Object類的一部分,該函數(shù)同時(shí)刪掉鍵和與其關(guān)聯(lián)的值:
function remove(key){ delete this.datastore[key]; }
最后,我們希望可以顯示字典中所有的鍵-值對(duì),可以使用如下的方法:
function showAll(){ for(var key in Object.keys(this.datastore)){ print(key + "->" + this.datastore[key]); } }Dictionary類的輔助方法
我們可以定義一些在特定情況下有用的輔助方法。比如要知道字典中的元素個(gè)數(shù)可以定義一個(gè)count()方法,代碼如下:
function count(){ var n=0; for(var key in Object.keys(this.datastore)){ ++n; } return n; }
為什么不使用length屬性?這是因?yàn)楫?dāng)鍵的類型為字符串時(shí),length屬性就不管用了
還可以定義一個(gè)clear清除方法:
function clear(){ for each(var key in Object.keys(this.datastore)){ delete this.datastore[key]; } }備注:
for each in(IE6,7,8不支持)無(wú)法獲得對(duì)象的屬性名,只能獲取到屬性值。
另外,遍歷對(duì)象也盡量使用for in 而不是for each,而遍歷數(shù)組的話還是使用for循環(huán)吧
for each in無(wú)法獲得對(duì)象的屬性名,只能獲取到屬性值。
散列(hash) 什么是哈希表?哈希表(Hash table,也叫散列表),是根據(jù)關(guān)鍵碼值(Key value)而直接進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)構(gòu)。也就是說(shuō),它通過(guò)把關(guān)鍵碼值映射到表中一個(gè)位置來(lái)訪問(wèn)記錄,以加快查找的速度。這個(gè)映射函數(shù)叫做散列函數(shù),存放記錄的數(shù)組叫做散列表。
哈希表的做法其實(shí)很簡(jiǎn)單,就是把Key通過(guò)一個(gè)固定的算法函數(shù)既所謂的哈希函數(shù)轉(zhuǎn)換成一個(gè)整型數(shù)字,然后就將該數(shù)字對(duì)數(shù)組長(zhǎng)度進(jìn)行取余,取余結(jié)果就當(dāng)作數(shù)組的下標(biāo),將value存儲(chǔ)在以該數(shù)字為下標(biāo)的數(shù)組空間里。
而當(dāng)使用哈希表進(jìn)行查詢的時(shí)候,就是再次使用哈希函數(shù)將key轉(zhuǎn)換為對(duì)應(yīng)的數(shù)組下標(biāo),并定位到該空間獲取value,如此一來(lái),就可以充分利用到數(shù)組的定位性能進(jìn)行數(shù)據(jù)定位
散列表的查找步驟當(dāng)存儲(chǔ)記錄時(shí),通過(guò)散列函數(shù)計(jì)算出記錄的散列地址 當(dāng)查找記錄時(shí),我們通過(guò)同樣的是散列函數(shù)計(jì)算記錄的散列地址,并按此散列地址訪問(wèn)該記錄
在js中,散列函數(shù)會(huì)將每個(gè)鍵值映射為一個(gè)唯一的數(shù)組索引。然而,鍵的數(shù)量是無(wú)限的,數(shù)組的長(zhǎng)度是有限的,所以,應(yīng)該讓散列函數(shù)盡量將鍵均勻地映射到數(shù)組中。
哈希表也是種數(shù)據(jù)結(jié)構(gòu),它可以提供快速的插入操作和查找操作。哈希表運(yùn)算速度極快,哈希表的速度明顯比樹快,樹的操作通常需要O(N)的時(shí)間級(jí)。哈希表不僅速度快,編程實(shí)現(xiàn)也相對(duì)容易。
哈希表算法哈希表最常見(jiàn)的例子是以學(xué)生學(xué)號(hào)為關(guān)鍵字的成績(jī)表,1號(hào)學(xué)生的記錄位置在第一條,10號(hào)學(xué)生的記錄位置在第10條...
如果我們以學(xué)生姓名為關(guān)鍵字,如何建立查找表,使得根據(jù)姓名可以直接找到相應(yīng)記錄呢?
用上述得到的數(shù)值作為對(duì)應(yīng)記錄在表中的位置,得到下表:
上面這張表即哈希表。
如果將來(lái)要查李秋梅的成績(jī),可以用上述方法求出該記錄所在位置:
李秋梅:lqm 12+17+13=42 取表中第42條記錄即可。
HashTable類我們使用一個(gè)類來(lái)表示散列表,該類包含計(jì)算散列值的方法、向散列中插入數(shù)據(jù)的方法、從散列表中讀取數(shù)據(jù)的方法、顯示散列表中數(shù)據(jù)分布的方法等。
HashTable類的構(gòu)造函數(shù)定義如下:
function HashTable(){ this.table = new Array(137);//設(shè)定數(shù)組長(zhǎng)度為137,質(zhì)數(shù) this.simpleHash = simpleHash; this.showDistro = showDistro; this.put = put; }
散列函數(shù)的選擇依賴于鍵值的數(shù)據(jù)類型。如果鍵是整形,最簡(jiǎn)單的散列函數(shù)就是以數(shù)組的長(zhǎng)度對(duì)鍵取余。
使用一個(gè)簡(jiǎn)單的散列函數(shù)做散列:
load("HashTable.js"); var someNames = ["David","Jennifer","Donnie","Raymond","Cynthia","Mike","Clayton","Danny","Jonathan"]; var hTable = new HashTable(); for(var i = 0;i < someNames.length;i++){ hTable.put(someNames[i]); } hTable.showDistro();
輸出如下:
35:Cynthia 45:Clayton 57:Donnie 77:David 95:Danny 116:Mike 132:Jennifer 134:Jonathan
simpleHash()函數(shù)通過(guò)使用js的charCodeAt()函數(shù),返回每個(gè)字符的ASCII碼值,然后再將它們相加得到散列值。put方法通過(guò)調(diào)用simpleHash()函數(shù)得到數(shù)組的索引,然后將數(shù)據(jù)存儲(chǔ)到該索引對(duì)應(yīng)的位置上。
一個(gè)更好的散列函數(shù)為了避免碰撞,首先要確保散列表中用來(lái)存儲(chǔ)數(shù)據(jù)的數(shù)組其大小是個(gè)質(zhì)數(shù),這和計(jì)算散列值時(shí)使用的取余運(yùn)算有關(guān)。數(shù)組的長(zhǎng)度應(yīng)該在100以上,這是為了讓數(shù)據(jù)在散列表中分布得更均勻
散列化整型鍵這里我們使用一個(gè)展示學(xué)生成績(jī)的數(shù)據(jù)集,將隨機(jī)產(chǎn)生一個(gè)9位數(shù)的鍵,用以識(shí)別學(xué)生身份和一門成績(jī),下面是產(chǎn)生學(xué)生數(shù)據(jù)(包含ID和成績(jī))的函數(shù):
function getRandomInt(min,max){ return Math.floor(Math.random()*(max-min+1))+min; } function genStuData(arr){ for(var i = 0;i使用getRandomInt()函數(shù)時(shí),可以指定隨機(jī)數(shù)的最值。genStuData()函數(shù)生成學(xué)生的數(shù)據(jù)。里層的循環(huán)用來(lái)生成學(xué)生的ID,緊跟在循環(huán)后面的代碼生成一個(gè)隨機(jī)的成績(jī),并把成績(jī)弄在ID的后面。主程序會(huì)把ID和成績(jī)分離。散列函數(shù)將學(xué)生ID里的數(shù)字相加,使用simpleHash()函數(shù)計(jì)算出散列值。
對(duì)散列表排序put方法同時(shí)接受鍵和數(shù)據(jù)作為參數(shù),對(duì)鍵值散列后,將數(shù)據(jù)存儲(chǔ)到散列表中:
function put(key,data){ var pos = this.betterHash(key); this.table[pos] = data; }put方法將鍵值散列化后,將數(shù)據(jù)存儲(chǔ)到散列化后的鍵值對(duì)應(yīng)在數(shù)組中的位置上。
從散列表中取值定義get()方法,用以讀取存儲(chǔ)在散列表中的數(shù)據(jù)。該方法同樣需要對(duì)鍵值進(jìn)行散列化,然后才能知道數(shù)據(jù)存儲(chǔ)在數(shù)組的什么位置,代碼如下:
function get(key){ return this.table[this.betterHash(key)]; }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/85444.html
摘要:小結(jié)實(shí)現(xiàn)了字典和哈希表感覺(jué)沒(méi)有想象中那么困難,當(dāng)然這還是開始。 本系列所有文章:第一篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之棧與隊(duì)列第二篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之鏈表第三篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之集合第四篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之字典和散列表第五篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之二叉搜索樹 字典 不是新華字典哦,這里的字典也稱作_映射_,是一種數(shù)據(jù)結(jié)構(gòu),跟set集合很相似的一種數(shù)據(jù)結(jié)構(gòu),都可以用來(lái)...
摘要:在字典中,存儲(chǔ)的是鍵,值,集合可以看作值,值的形式存儲(chǔ)元素,字典也稱為映射方法描述備注向字典中添加新元素通過(guò)某個(gè)鍵值從字典中移除對(duì)應(yīng)的數(shù)據(jù)值判斷某個(gè)鍵值是存在于這個(gè)字典中通過(guò)鍵值獲取對(duì)應(yīng)的數(shù)據(jù)值返回字典所有元素的數(shù)量刪除字典中所有元素將字典 在字典中,存儲(chǔ)的是[鍵,值],集合可以看作[值,值]的形式存儲(chǔ)元素,字典也稱為映射 方法 描述 備注 set(key,...
摘要:我經(jīng)常在業(yè)務(wù)代碼中把數(shù)據(jù)處理成這種字典的數(shù)據(jù)結(jié)構(gòu)獲取的方法哈希表在學(xué)習(xí)了類之后,我們會(huì)學(xué)習(xí)散列表,也就是哈希表。 《Javascript數(shù)據(jù)結(jié)構(gòu)和算法》筆記-「字典和散列表」 集合、字典、散列表存儲(chǔ)的都是「不重復(fù)」的數(shù)據(jù)結(jié)構(gòu) 集合:我們更關(guān)注每一個(gè)元素的值,并把其作為主要元素 字典:我們用[鍵,值]的形式來(lái)存儲(chǔ)數(shù)據(jù) 散列表: 跟字典類似,也會(huì)是用[鍵,值]的形式來(lái)存儲(chǔ)數(shù)據(jù) 但是「字...
摘要:什么是散列表和散列函數(shù)哈希表,也叫散列表,是根據(jù)關(guān)鍵碼值而直接進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)構(gòu)。根據(jù)鍵值從散列表中移除值。請(qǐng)實(shí)現(xiàn)散列表將和存在一個(gè)對(duì)象中即可定義一個(gè)包含和屬性的類并分配到散列表。 showImg(https://segmentfault.com/img/remote/1460000019005270); 這是第五周的練習(xí)題,上周忘記發(fā)啦,這周是復(fù)習(xí) Dictionary 和 Hash...
摘要:什么是散列表和散列函數(shù)哈希表,也叫散列表,是根據(jù)關(guān)鍵碼值而直接進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)構(gòu)。將字典的所有鍵名以數(shù)組的形式返回。根據(jù)鍵值從散列表中移除值。這是第五周的練習(xí)題,上周忘記發(fā)啦,這周是復(fù)習(xí) Dictionary 和 HashTable。 下面是之前分享的鏈接: 1.每周一練 之 數(shù)據(jù)結(jié)構(gòu)與算法(Stack) 2.每周一練 之 數(shù)據(jù)結(jié)構(gòu)與算法(LinkedList) 3.每周一練 之 數(shù)據(jù)結(jié)構(gòu)...
閱讀 2757·2023-04-25 15:22
閱讀 2886·2021-10-11 10:58
閱讀 1113·2021-08-30 09:48
閱讀 1913·2019-08-30 15:56
閱讀 1789·2019-08-30 15:53
閱讀 1169·2019-08-29 11:16
閱讀 1114·2019-08-23 18:34
閱讀 1706·2019-08-23 18:12