学习散列表
回顧一下簡單查找和二分查找
雜貨店商品對應的價格舉例:
簡單查找就是拿出商品價目本,這個價目本并不是有序的,顧客問蘋果多少錢,需要一個一個去查找某一個商品的價格,需要O(n)時間。
同樣是一個價目本,但是按商品名稱字母排序的,這樣需要的時候更短為O(logn)。
但這樣我還是覺得查找太慢,怎么辦,這時候需要一名能記住所有商品價格的員工,這樣一問評價價格便知,只需要O(1)。
從數據結構的角度來看
你可使用數組來實現記錄商品價格的本子,的每個元素包含兩項內容:商品名和價格。
如果將這個數組按商品名排序,就可使用二分查找在其中查找商品的價格。這樣查找價格的時間將為O(log n)。
然而,我希望查找商品價格的時間為O(1),這是散列函數的用武之地。
散列函數
無論你給散列函數什么數據,它都還你一個數字,專業點說:散列函數“將輸入映射到數字”
特點:
- 一致的,比如輸入蘋果得到的是4,之后的每一次輸入蘋果最后得到的都是4。
- 不同的輸入映射不同的數字。
簡單實現商品價目本:
準備一個空列表,將蘋果輸入散列函數,輸出4,那么列表的索引4就存蘋果價格¥2.1,依次類存。。。行程價目本。
這樣我們想知道商品名(蘋果)價格,直接把蘋果給散列函數,輸出的就是價目表的索引4位置的價格(¥2.1)。
注意: 散列函數知道數組有多大,只返回有效的索引。如果數組包含5個元素,散列函數就不會
返回無效索引100。
散列表
復雜數據結構中,散列表可能是最有用的,也被稱為散列映射、映射、字典和關聯數組。散列表的速度很快!和數組一樣快。
Python提供的散列表實現為字典,你可使用函數dict來創建散列表。
散列表的應用
將散列表用于查找
比如電話本
比如DNS解析(DNS resolution):網址映射到ip地址
我想瀏覽www.baidu.com 需要先進行DNS解析成ip地址192.168.0.0(隨便寫的ip地址)然后再進行訪問百度服務器。
防止重復
比如投票機制:已經投過票的不能再投了
如果將已投票者的姓名存儲在列表中,這個函數的速度終將變得非常慢,因為它必須使用簡單查找搜索整個列表。
作為緩存
你登錄了Facebook,你看到的所有內容都是為你定制的。你每次訪問facebook.com,其服務器都需考慮你感興趣的是什么內容。但如果你沒有登錄,看到的將是登錄頁面。每個人看到的登錄頁面都相同。 Facebook被反復要求做同樣的事情:“當我注銷時,請向我顯示主頁。”有鑒于此,它不讓服務器去生成主頁,而是將主頁存儲起來,并在需要時將其直接發送給用戶。
- 用戶能夠更快地看到網頁,網站已經記住了用戶的訪問頻次或喜好等行為。
- Facebook需要做的工作更少。
Facebook不僅緩存主頁,還緩存About頁面、 Contact頁面等眾多其他的頁面。因此,它需要將頁面URL映射到頁面數據。
也就是一個字典中key是url,value是網頁數據data
僅當URL不在緩存中時,你才讓服務器做些處理,并將處理生成的數據存儲到緩存中,再返回它。這樣,當下次有人請求該URL時,你就可以直接發送緩存中的數據,而不用再讓服務器進行處理了。
這里總結一下,散列表適合用于:
- 模擬映射關系;
- 防止重復;
- 緩存/記住數據,以免服務器再通過處理來生成它們。
tips:本篇文章參考算法圖解
總結
- 上一篇: udp协议的服务器是哪种类型,UDP协议
- 下一篇: java8新特性(1)--- lambd