JAVA數據結構--哈希表的實現(分離鏈接法)


哈希表(散列)的定義

散列表(Hash table,也叫哈希表),是根據關鍵碼值(Key value)而直接進行訪問的數據結構。也就是說,它通過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。這個映射函數叫做散列函數,存放記錄的數組叫做散列表。

哈希表的特點是采用以常數平均時間執行插入、刪除和查找。

一個通俗的例子是,為了查找電話簿中某人的號碼,可以創建一個按照人名首字母順序排列的表(即建立人名x到首字母F(x)的一個函數關系),在首字母為W的表中查找“王”姓的電話號碼,顯然比直接查找就要快得多。這里使用人名作為關鍵字,“取首字母”是這個例子中散列函數的函數法則F(),存放首字母的表對應散列表。關鍵字和函數法則理論上可以任意確定。

分離鏈接法定義

將散列到同一個值得所有元素保留到一個表中。

基本思想是采用N個鏈表組成鏈表數組,N為哈希表的長度。

哈希表構造實現

1 public SeparateChainingHashTable() {
2         this(DEFAULT_TABLE_SIZE);
3     }
4 public SeparateChainingHashTable(int size) {
5     theLists=new LinkedList[nextPrime(size)];
6     for(int i=0;i<theLists.length;i++) {
7         theLists[i]=new LinkedList<>();//初始化鏈表數組
8     }
9 }

基本操作實現

 1 /*
 2      * 哈希表插入元素
 3      * */
 4     public void insert(T x) {
 5         List<T> whichList=theLists[myhash(x)];
 6         /*
 7          * 如果當前哈希地址的鏈表不含有元素,則鏈表中添加該元素
 8          * */
 9         if(!whichList.contains(x)) {
10             whichList.add(x);
11             if(++currentSize>theLists.length)//如果表長度不夠,則擴容
12                 rehash();
13         }
14     }
15     public void remove(T x) {
16         List<T> whichList=theLists[myhash(x)];
17         if(whichList.contains(x)) {
18             whichList.remove(x);
19             currentSize--;
20         }
21     }
22     public boolean contains(T x) {
23         List<T> whilchList=theLists[myhash(x)];
24         return whilchList.contains(x);
25     }
26     public void makeEmpty() {
27         for(int i=0;i<theLists.length;i++)
28             theLists[i].clear();
29         currentSize=0;
30     }

哈希表相關實現

 1 private void rehash() {
 2         List<T>[] oldLists=theLists;
 3         theLists=new List[nextPrime(2*theLists.length)];
 4         for(int j=0;j<theLists.length;j++)
 5             theLists[j]=new LinkedList<>();
 6         
 7         currentSize=0;
 8         /*
 9          * 更新哈希表
10          * */
11         for(List<T> list:oldLists)
12             for(T item:list)
13                 insert(item);
14     }
15     /*
16      * myhash()方法獲得哈希表的地址
17      * */
18     private int myhash(T x) {
19         int hashVal=x.hashCode();//hashCode()方法返回該對象的哈希碼值
20         hashVal%=theLists.length;//對哈希表長度取余數
21         if(hashVal<0)
22             hashVal+=theLists.length;
23         return hashVal;
24     }

全部代碼

  1 import java.util.LinkedList;
  2 import java.util.List;
  3 
  4 public class SeparateChainingHashTable<T>{
  5     public SeparateChainingHashTable() {
  6         this(DEFAULT_TABLE_SIZE);
  7     }
  8     public SeparateChainingHashTable(int size) {
  9         theLists=new LinkedList[nextPrime(size)];
 10         for(int i=0;i<theLists.length;i++) {
 11             theLists[i]=new LinkedList<>();//初始化鏈表數組
 12         }
 13     }
 14     
 15     /*
 16      * 哈希表插入元素
 17      * */
 18     public void insert(T x) {
 19         List<T> whichList=theLists[myhash(x)];
 20         /*
 21          * 如果當前哈希地址的鏈表不含有元素,則鏈表中添加該元素
 22          * */
 23         if(!whichList.contains(x)) {
 24             whichList.add(x);
 25             if(++currentSize>theLists.length)//如果表長度不夠,則擴容
 26                 rehash();
 27         }
 28     }
 29     public void remove(T x) {
 30         List<T> whichList=theLists[myhash(x)];
 31         if(whichList.contains(x)) {
 32             whichList.remove(x);
 33             currentSize--;
 34         }
 35     }
 36     public boolean contains(T x) {
 37         List<T> whilchList=theLists[myhash(x)];
 38         return whilchList.contains(x);
 39     }
 40     public void makeEmpty() {
 41         for(int i=0;i<theLists.length;i++)
 42             theLists[i].clear();
 43         currentSize=0;
 44     }
 45     
 46     private static final int DEFAULT_TABLE_SIZE=101;
 47     
 48     private List<T> [] theLists;
 49     private int currentSize;
 50     
 51     /*
 52      * 哈希表擴容,表長度為下一個素數
 53      * */
 54     private void rehash() {
 55         List<T>[] oldLists=theLists;
 56         theLists=new List[nextPrime(2*theLists.length)];
 57         for(int j=0;j<theLists.length;j++)
 58             theLists[j]=new LinkedList<>();
 59         
 60         currentSize=0;
 61         /*
 62          * 更新哈希表
 63          * */
 64         for(List<T> list:oldLists)
 65             for(T item:list)
 66                 insert(item);
 67     }
 68     /*
 69      * myhash()方法獲得哈希表的地址
 70      * */
 71     private int myhash(T x) {
 72         int hashVal=x.hashCode();//hashCode()方法返回該對象的哈希碼值
 73         hashVal%=theLists.length;//對哈希表長度取余數
 74         if(hashVal<0)
 75             hashVal+=theLists.length;
 76         return hashVal;
 77     }
 78     //下一個素數
 79     private static int nextPrime(int n) {
 80         if( n % 2 == 0 )
 81             n++;
 82 
 83         for( ; !isPrime( n ); n += 2 )
 84             ;
 85 
 86         return n;
 87     }
 88     //判斷是否是素數
 89     private static boolean isPrime(int n) {
 90          if( n == 2 || n == 3 )
 91                 return true;
 92 
 93             if( n == 1 || n % 2 == 0 )
 94                 return false;
 95 
 96             for( int i = 3; i * i <= n; i += 2 )
 97                 if( n % i == 0 )
 98                     return false;
 99 
100             return true;
101     }
102 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM