Day27——哈希表

由昨天的顺序表和折半查找知道,查找的效率取决于关键字比较的次数。哈希表是根据关键字而进行直接访问的数据结构,建立了关键字和存储地址之间的一种直接映射关系。
但哈希表都避免不了地址冲突,处理冲突的方法:
1、开放定址法:存放新表项的空闲地址既向它的同义词表项开放,又向它的非同义词表项开放,公式为: H i = ( H ( k e y ) + d i ) % m ( m 表 示 哈 希 表 表 长 , d i 为 增 量 序 列 ) H_i=(H(key)+d_i) \%m(m表示哈希表表长,d_i为增量序列) Hi=(H(key)+di)%m(mdi)。开放地址的常用方法:

  • 线性探测法: d i = 0 , 1 , 2 , ⋯   , k ( k ≤ m − 1 ) d_i=0,1,2,\cdots,k(k\le m-1) di=0,1,2,,k(km1),发生冲突时,依次探测哈希表表项,一共最多探测 m m m次。
  • 平方探测法: d i = 0 2 , 1 2 , − 1 2 , 2 2 , − 2 2 , ⋯   , k 2 , − k 2 ( k ≤ m 2 ) d_i=0^2,1^2,-1^2,2^2,-2^2,\cdots,k^2,-k^2(k\le \frac{m}{2}) di=02,12,12,22,22,,k2,k2(k2m),为了尽可能的探测所有表项,应设置 m m m 4 k + 3 4k+3 4k+3
  • 伪随机序列法:构造 d i d_i di为伪随机序列
  • 再散列法:多设置几个哈希函数,当前面的哈希函数发生冲突时,用下一个哈希函数计算一个新地址,直到不发生冲突为止。

2、 把所有的同义词存储在一个线性链表中,这个线性链表由其散列地址唯一标识,其结构和图的邻接表一模一样。

今天的代码中使用线性探测法处理地址冲突,这个代码不适合动态查找,因为在添加元素时使用的是while,并没有对增量 d i d_i di进行判断,当表满的时候,会发生死循环。
代码:

	/**
	 * 
	 *********************
	 * The second constructor. For Hash code only.It is assumed that
	 * paraKeyArray.length<=paraLength.
	 *
	 * @param paraKeyArray
	 * @param paraContentArray
	 * @param paraLength
	 *********************
	 *
	 */
	public DataArray(int[] paraKeyArray, String[] paraContentArray, int paraLength) {
		// Step 1. Initialize
		length = paraLength;
		data = new DataNode[length];

		for (int i = 0; i < length; i++) {
			data[i] = null;
		} // Of for i

		// Step 2. Fill the data.
		int tempPosition;

		for (int i = 0; i < paraKeyArray.length; i++) {
			// Hash
			tempPosition = paraKeyArray[i] % paraLength;

			// Find an empty position
			while (data[tempPosition] != null) {
				tempPosition = (tempPosition + 1) % paraLength;
				System.out.println("Collison,move forward for key " + paraKeyArray[i]);
			} // Of while

			data[tempPosition] = new DataNode(paraKeyArray[i], paraContentArray[i]);
		} // Of for i

	}// Of the second constructor

	/**
	 * 
	 *********************
	 * @Title: hashSearch
	 * @Description: TODO(Hash search.)
	 *
	 * @param paraKey The given key.
	 * @return The content of the key.
	 *********************
	 *
	 */
	public String hashSearch(int paraKey) {
		int tempPosition = paraKey % length;
		while (data[tempPosition] != null) {
			if (data[tempPosition].key == paraKey) {
				return data[tempPosition].content;
			} // Of if
			System.out.println("Not this one for " + paraKey);
			tempPosition = (tempPosition + 1) % length;
		} // Of while

		return "null";
	}// Of hashSearch

	/**
	 * 
	 *********************
	 * @Title: hashSearchTest
	 * @Description: TODO(Test the method.)
	 *
	 *********************
	 *
	 */
	public static void hashSearchTest() {
		int[] tempUnsortedKeys = { 16, 33, 38, 69, 57, 95, 86 };
		String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" };

		DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents, 19);

		System.out.println(tempDataArray);

		System.out.println("Search resulf of 95 is: " + tempDataArray.hashSearch(95));
		System.out.println("Search resulf of 38 is: " + tempDataArray.hashSearch(38));
		System.out.println("Search resulf of 57 is: " + tempDataArray.hashSearch(57));
		System.out.println("Search resulf of 4 is: " + tempDataArray.hashSearch(4));

	}//Of hashSearchTest

	/**
	 * 
	 *********************
	 * @Title: main
	 * @Description: TODO(The entrance of the program.)
	 *
	 * @param args Not used now.
	 *********************
	 *
	 */
	public static void main(String args[]) {
		System.out.println("\r\n----------sequentialSearchTest----------");
		sequentialSearchTest();

		System.out.println("\r\n----------binarySearchTest----------");
		binarySearchTest();

		System.out.println("\r\n----------hashSearchTest----------");
		hashSearchTest();

	}// Of main

运行结果:
Day27——哈希表_第1张图片

你可能感兴趣的:(Java,java)