級別: ★☆☆☆☆
標籤:「算法」「Hash」「散列表」「哈希表」
做者: MrLiuQ
審校: QiShare團隊php
本篇將介紹散列表(哈希表)的相關基礎知識。html
散列表(Hash table,也叫哈希表)是根據關鍵碼值(Key value)而直接進行訪問的數據結構。也就是說,它經過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。 這個映射函數叫作散列函數,存放記錄的數組叫作散列表。(來源360百科)git
散列函數:簡單來講是一個函數,傳入一個Key
就返回一個固定的數。該數即爲散列表數組的下標。(用一句話描述:散列函數將「輸入」映射到「數字」。)github
對不一樣的關鍵字可能獲得同一散列地址,即k1≠k2
,而f(k1)=f(k2)
,這種現象稱爲衝突(碰撞)。算法
常見的解決哈希衝突方案有如下四種:(詳細細節見下篇講解)數組
開放定址法:爲產生衝突的地址H(key)
求得一個新的地址序列: Hi =(H(key)+ di)% m
(i=1,2,3,...,m-1) 其中H(key)
爲哈希函數,m
爲表長,di
稱爲增量序列。(其中增量di
的取值方法也有多種,詳細細節見下篇)微信
鏈地址法:將全部哈希地址相同的記錄都連接在同一鏈表中。數據結構
再哈希法:產生衝突時計算**另外一個哈希函數(散列函數)**的地址,直到衝突再也不發生爲止。函數
創建公共溢出區:把衝突的值都放在另外一個溢出表中,不把衝突的值存原表中。oop
先介紹一個散列表的專有名詞:填裝因子(負載因子)。
這裏列出了常見數據結構操做的時間複雜度。
/ | 散列表(最佳狀況) | 散列表(最壞狀況) | 數組 | 鏈表 |
---|---|---|---|---|
取值 | O(1) | O(n) | O(1) | O(n) |
插入 | O(1) | O(n) | O(n) | O(1) |
刪除 | O(1) | O(n) | O(n) | O(1) |
能夠看出散列表在最佳狀況下的性能是很出色的,雖然最壞狀況的性能很差,但咱們能夠經過一些手段避免掉最壞狀況。所以,散列表的最優狀況就是平均狀況,時間複雜度爲常數級O(1)。
所以,散列表在使用中須要注意兩點:
0.7
時,考慮散列表翻倍擴容)PS:Python的作法是,會設法保證大概還有三分之一的表元是空的,當快要達到這個閥值的時候,會進行擴容,將原散列表複製到一個更大的散列表裏。
例如,用散列表實現一個電話薄。
主要功能以下:
圖解以下:
代碼以下:
# 建立一個telBook的散列表
telBook = dict()
# 將A-Z的字母做爲telBook的Key,Value仍是一個散列表
for ch in xrange(0x41, 0x5A):
telBook[unichr(ch)] = dict()
# 將聯繫人加入telBook中,取首字母做爲第一個Key,名稱做爲第二個Key,電話做爲第二個Key的Value。
def addFriend(name, phoneNumber):
telBook[name[0:1]][name] = phoneNumber
addFriend("QiShare1", 13800000000)
addFriend("QiShare2", 13811111111)
addFriend("QiShare3", 13822222222)
addFriend("QiShare4", 13833333333)
addFriend("QiShare5", 13844444444)
addFriend("QiShare6", 13855555555)
addFriend("Police", 110)
addFriend("XiaoMing1", 1)
addFriend("XiaoMing2", 2)
addFriend("XiaoMing3", 3)
# 輸出結果:
for ch in xrange(0x41, 0x5A):
if telBook[unichr(ch)]:
print unichr(ch)+":"
print telBook[unichr(ch)]
複製代碼
打印結果以下:
小編微信:可加並拉入《QiShare技術交流羣》。
關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)
推薦文章:
iOS UIButton根據內容自動佈局
iOS 指定初始化方法
UIView中的hitTest方法
iOS關於tabBar的幾處筆記
A的女兒是B的女兒的媽媽,A是B的誰?
算法小專欄:選擇排序
iOS Runloop(一)
奇舞週刊