雜湊表的查詢
引入雜湊表
前面查詢方法共同特點:通過將關鍵字值與給定值比較,來確定位置。效率取決比較次數。
理想的方法是:不需要比較,根據給定值能直接定位記錄的儲存位置。
這樣,需要在記錄的儲存位置與該記錄的關鍵字之間建立一種確定的對應關係,使每個記錄的關鍵字與一個儲存位置相對應。
1.雜湊表的結構和特點
hashtable 也叫散列表
特點:快 很快 神奇的快
結構:結構有多種
最流行、最容易理解:順序表+連結串列
主結構:順序表
每個順序表的節點在單獨引出一個連結串列
雜湊表初始操作狀態
2.雜湊表是如何新增資料的
1.計算雜湊碼(呼叫hashCode(),結果是一個int值,整數的雜湊碼取自身即可)
2.計算在雜湊表中的儲存位置 y=k(x)=x%11 x:雜湊碼 k(x) 函式 y:在雜湊表中的儲存位置
3.存入雜湊表
情況1:一次新增成功
情況2:多次新增成功(出現了衝突,呼叫equals()和對應連結串列的元素進行比較,
比較到最後,結果都是false,建立新節點,儲存資料,並加入連結串列末尾)
情況3:不新增(出現了衝突,呼叫equals()和對應連結串列的元素進行比較,
經過一次或者多次比較後,結果是true,表明重複,不新增)
結論1:雜湊表新增資料快(3步即可,不考慮衝突)
結論2:唯一
結論2:無序
3.雜湊表是如何查詢資料的
和新增資料的過程是相同的
情況1:一次找到 23 86 76
情況2:多次找到 67 56 78
情況3:找不到 100 200
結論1:雜湊表查詢資料快
結論2:雜湊表刪除資料快
結論3:雜湊表更新資料快(如果更新後影響到雜湊碼值,就比較繁瑣了,比如要刪除再添加了)
4.hashCode和equals到底有什麼神奇的作用
hashCode():計算雜湊碼,是一個整數,根據雜湊碼可以計算出資料在雜湊表中的儲存位置
equals():新增時出現了衝突,需要通過equals進行比較,判斷是否相同
查詢時也需要使用equals進行比較,判斷是否相同
5.各種型別資料的雜湊碼應該如何獲取 hashCode()
1.int 取自身 看Integer的原始碼
2.double 3.14 3.15 3.145 6.567 9.87 取整不可以 看Double的原始碼
3.String java oracle j+a+v+a 將各個字元的編碼值相加不可以
abc cba bac a:97 b:98 c:99
abc 1*97+2*98+3*99
cba 1*99+2*98+3*97
4.Student 先各個屬性的雜湊碼,進行某些相加相乘的運算
int id
String name
int age
double score;
6.如何減少衝突
1)雜湊表的長度和表中的記錄數的比例--裝填因子:
如果Hash表的空間遠遠大於最後實際儲存的記錄個數,則造成了很大的空間浪費,
如果選取小了的話,則容易造成衝突。
在實際情況中,一般需要根據最終記錄儲存個數和關鍵字的分佈特點來確定Hash表的大小。
還有一種情況時可能事先不知道最終需要儲存的記錄個數,則需要動態維護Hash表的容量,此時可能需要重新計算Hash地址。
裝填因子=表中的記錄數/雜湊表的長度,
如果裝填因子越小,表明表中還有很多的空單元,則添加發生衝突的可能性越小;
而裝填因子越大,則發生衝突的可能性就越大,在查詢時所耗費的時間就越多。
有相關文獻證明當裝填因子在0.5左右的時候,Hash的效能能夠達到最優。
因此,一般情況下,裝填因子取經驗值0.5。
2)雜湊函式的選擇
直接定址法 平方取中法 摺疊法 除留取餘法(y = x%11)
查詢相關資料
3)處理衝突的方法
鏈地址法 開放地址法 再雜湊法 建立一個公共溢位區
Java中TreeSet和TreeMap底層就使用了紅黑樹
package doubleTree;
import java.util.Set;
import java.util.TreeSet;
public class LinkedBinaryTree{
public static void main(String[] args) {
Set set=new TreeSet();
set.add(2);
set.add(5);
set.add(6);
set.add(4);
set.add(5);
set.add(1);
set.add(9);
System.out.println(set);
}
}
(感覺這個底層是按照某一個順序進行了排序,我知道了,因為紅黑樹底層本來就是有序的)
新增結點過程中會通過旋轉等方法,保證每次新增前後都是平衡樹。
Java中HashSet和HashMap底層就使用了雜湊表 Hashtable