本次作业重点是hascode和compress function,评价一个compress function好坏的标准是能否实现keys在buckets中的随机分布
作业要求Load Factor(=keys/buckets)在0.5-1之间,我记得书上说0.75比较好,然后就直接让buckets的length用size除以0.75:
length=(int)(getPrime(sizeEstimate)/0.75);
几个注意的点:
- 第二个HashTableChained的constructor可以直接利用this关键字生成
- SList and SListNode 可以直接从homework5中import
- Compression Function我用的是h(i) = ((ai + b) mod p) mod N),但是换了几个尝试之后发现每次collisions的相差都不大。
- Insert(), remove(), find()等方法中调用front()头节点是返回的是ListNode,要强制类型转化成SListNode, item要强制转化成Entry才能调用key进行比较
以下为Homework6Test.java
package com.homework6;/* Homework6Test.java */ import com.dict.*; /** * Initializes a hash table, then stocks it with random SimpleBoards. **/ public class Homework6Test { /** * Generates a random 8 x 8 SimpleBoard. **/ private static SimpleBoard randomBoard() { SimpleBoard board = new SimpleBoard(); for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { double fval = Math.random() * 12; int value = (int) fval; board.setElementAt(x, y, value); } } return board; } /** * Empties the given table, then inserts "numBoards" boards into the table. * @param table is the hash table to be initialized. * @param numBoards is the number of random boards to place in the table. **/ public static void initTable(HashTableChained table, int numBoards) { table.makeEmpty(); for (int i = 0; i < numBoards; i++) { table.insert(randomBoard(), new Integer(i)); } } /** * Creates a hash table and stores a certain number of SimpleBoards in it. * The number is 100 by default, but you can specify any number at the * command line. For example: * * java Homework6Test 12000 **/ public static void main(String[] args) { int numBoards; if (args.length == 0) { numBoards = 100; } else { numBoards = Integer.parseInt(args[0]); } HashTableChained table = new HashTableChained(numBoards); initTable(table, numBoards); // To test your hash function, add a method to your HashTableChained class // that counts the number of collisions--or better yet, also prints // a histograph of the number of entries in each bucket. Call this method // from here. System.out.println("number of buckets is "+table.length+",number of entries is "+table.size); System.out.println(table.toString()); System.out.println("Expect collision:"+table.collision()); System.out.println("Real collision:"+table.sizeDup); System.out.println("=============================="); numBoards = 200; table = new HashTableChained(numBoards); initTable(table, numBoards); System.out.println("number of buckets is "+table.length+",number of entries is "+table.size); System.out.println(table.toString()); System.out.println("Expected collision:"+table.collision()); System.out.println("Real collision:"+table.sizeDup); } }
package com.homework6;/* SimpleBoard.java */ /** * Simple class that implements an 8x8 game board with three possible values * for each cell: 0, 1 or 2. * * DO NOT CHANGE ANY PROTOTYPES IN THIS FILE. **/ public class SimpleBoard { private final static int DIMENSION = 8; private int[][] grid; /** * Invariants: * (1) grid.length == DIMENSION. * (2) for all 0 <= i < DIMENSION, grid[i].length == DIMENSION. * (3) for all 0 <= i, j < DIMENSION, grid[i][j] >= 0 and grid[i][j] <= 2. **/ /** * Construct a new board in which all cells are zero. */ public SimpleBoard() { grid = new int[DIMENSION][DIMENSION]; } /** * Set the cell (x, y) in the board to the given value mod 3. * @param value to which the element should be set (normally 0, 1, or 2). * @param x is the x-index. * @param y is the y-index. * @exception ArrayIndexOutOfBoundsException is thrown if an invalid index * is given. **/ public void setElementAt(int x, int y, int value) { grid[x][y] = value % 3; if (grid[x][y] < 0) { grid[x][y] = grid[x][y] + 3; } } /** * Get the valued stored in cell (x, y). * @param x is the x-index. * @param y is the y-index. * @return the stored value (between 0 and 2). * @exception ArrayIndexOutOfBoundsException is thrown if an invalid index * is given. */ public int elementAt(int x, int y) { return grid[x][y]; } /** * Returns true if "this" SimpleBoard and "board" have identical values in * every cell. * @param board is the second SimpleBoard. * @return true if the boards are equal, false otherwise. */ public boolean equals(Object board) { // Replace the following line with your solution. Be sure to return false // (rather than throwing a ClassCastException) if "board" is not // a SimpleBoard. if (board instanceof SimpleBoard){ for (int i = 0; i < DIMENSION; i++){ for (int j = 0; j < DIMENSION; j++){ if (this.grid[i][j] != ((SimpleBoard) board).grid[i][j]){ return false; } } } return true; } else { return false; } } /** * Returns a hash code for this SimpleBoard. * @return a number between Integer.MIN_VALUE and Integer.MAX_VALUE. */ public int hashCode() { // Replace the following line with your solution. // return 99; int code = 0; for (int i = 0; i < DIMENSION; i++){ for (int j = 0; j < DIMENSION; j++){ code = (int)(code * 3 + grid[i][j] * 3 ^ (i*3+j)); } } return code; } }