cs61b homework6
终于能实现HashTable了!!之前看书一直没搞懂compression那的质数是什么意思,看lecture才明白,对prime求余数可以避免keys的hashcode均可被某一数整除从而造成collision过多的情况(这个概念好难形容啊感觉,具体参见lecture哈),compression算法:((a*hashcode+b)%p)%N,其中p为略大于N的质数。不过a和b我不知道有啥要求没,我是随便取的。
part1:
注意数组内的list要初始化,makeEmpty()后应重新初始化。
HashTableChains代码:
1 import java.text.DecimalFormat; 2 import java.util.Random; 3 4 import list.DList; 5 import list.InvalidNodeException; 6 import list.List; 7 import list.ListNode; 8 9 10 public class HashTableChained implements Dictionary { 11 private List[]listarray; 12 private int size; 13 14 private boolean isPrime(int n){ 15 if(n>2&&n%2==0) 16 return false; 17 for(int i=3;i*i<=n;i+=2){ 18 if(n%i==0) 19 return false; 20 } 21 return true; 22 } 23 24 public HashTableChained(int sizeEstimate) { 25 while(!isPrime(sizeEstimate)){ 26 sizeEstimate++; 27 } 28 listarray=new List[sizeEstimate]; 29 for(int i=0;i<sizeEstimate;i++) 30 listarray[i]=new DList(); 31 } 32 33 34 public HashTableChained() { 35 listarray=new List[127]; 36 for(int i=0;i<127;i++) 37 listarray[i]=new DList(); 38 } 39 40 41 42 int compFunction(int code) { 43 Random rand=new Random(); 44 int a=7; 45 int b=13; 46 int p=listarray.length+1; 47 while(!isPrime(p)) 48 p++; 49 int comp=((code*a+b)%p)%(listarray.length-1); 50 return comp; 51 52 } 53 54 55 public int size() { 56 // Replace the following line with your solution. 57 return size; 58 } 59 60 /** 61 * Tests if the dictionary is empty. 62 * 63 * @return true if the dictionary has no entries; false otherwise. 64 **/ 65 66 public boolean isEmpty() { 67 // Replace the following line with your solution. 68 return(size==0); 69 } 70 71 72 public Entry insert(Object key, Object value) { 73 int comp=compFunction(key.hashCode()); 74 Entry entry=new Entry(); 75 entry.key=key; 76 entry.value=value; 77 listarray[comp].insertBack(entry); 78 size++; 79 return entry; 80 } 81 82 public Entry find(Object key) { 83 int comp=compFunction(key.hashCode()); 84 if(listarray[comp]==null||listarray[comp].isEmpty()) 85 return null; 86 else if(listarray[comp].length()==1) 87 try { 88 return ((Entry)(listarray[comp].front().item())); 89 } catch (InvalidNodeException e) { 90 e.printStackTrace(); 91 return null; 92 } 93 else{ 94 try{ 95 Random rand=new Random(); 96 int r=rand.nextInt(listarray[comp].length()); 97 ListNode node=listarray[comp].front(); 98 for(int i=0;i<r-1;i++) 99 node=node.next(); 100 return (Entry)(node.item());} 101 catch(InvalidNodeException e){ 102 e.printStackTrace(); 103 return null; 104 } 105 } 106 } 107 108 109 public Entry remove(Object key) { 110 int comp=compFunction(key.hashCode()); 111 if(listarray[comp]==null||listarray[comp].isEmpty()) 112 return null; 113 else if(listarray[comp].length()==1){ 114 try { 115 Entry entry=new Entry(); 116 entry.key=((Entry)(listarray[comp].front().item())).key; 117 entry.value=((Entry)(listarray[comp].front().item())).value; 118 listarray[comp].front().remove(); 119 size--; 120 return entry; 121 } catch (InvalidNodeException e) { 122 e.printStackTrace(); 123 return null; 124 } } 125 else{ 126 try{ 127 Random rand=new Random(); 128 int r=rand.nextInt(listarray[comp].length()); 129 ListNode node=listarray[comp].front(); 130 for(int i=0;i<r-1;i++) 131 node=node.next(); 132 Entry entry=new Entry(); 133 entry.key=((Entry)(node.item())).key; 134 entry.value=((Entry)(node.item())).value; 135 node.remove(); 136 size--; 137 return entry; 138 } 139 catch(InvalidNodeException e){ 140 e.printStackTrace(); 141 return null; 142 } 143 } 144 } 145 146 public void makeEmpty() { 147 listarray=new List[listarray.length]; 148 for(int i=0;i<listarray.length;i++) 149 listarray[i]=new DList(); 150 size=0; 151 // Your solution here. 152 } 153 public void histograph(){ 154 double collisions=this.size-listarray.length+listarray.length*Math.pow((1-(double)(1.0/(double)listarray.length)),(double) size); 155 DecimalFormat df=new DecimalFormat("#.00"); 156 System.out.println("The expected collisions are: "+df.format(collisions)); 157 int count=1; 158 int realCollisions=0; 159 for(int i=0;i<listarray.length;i++){ 160 System.out.print("["+listarray[i].length()+"]"); 161 if(listarray[i].length()>1) 162 realCollisions+=listarray[i].length()-1; 163 if(count%10==0){ 164 System.out.println(); 165 count=0; 166 } 167 count++; 168 } 169 System.out.println(); 170 System.out.println("The real collisions are: "+realCollisions); 171 } 172 173 }
part2:主要是hashcode的算法,按任务上建议的是将每一格点的值化成3进制数的一位,最后内存会存在溢出,所以要强制转换为int。
代码:
public int hashCode() { int b=0; for(int i=0;i<DIMENSION;i++){ for(int j=0;j<DIMENSION;j++){ int k=8*i+j; int g=grid[i][j]; b+=(int)(g*(int)(3^k)); } } return b; }
运行结果:每个格子代表该位置存的Entry的个数,collisions和预估的结果还蛮一致。
ps:lab8让设计project2的interface,lab9让证明时间复杂度,都不是编程的task就不打卡了,准备直接开始project2啦。