数据结构学习笔记(六)散列之线性探测法、平方探测法

线性探测法:

线性探测法中函数是位置i的函数,这相当于当发生冲突的时候,逐个单元甚至回绕查询到一个空单元,也就是说数据都需要放置在这一个表格中,当发生冲突的时候就出发上面的机制,不过这样做,花费的时间是相当多的,这样单元会形成一些区域块,其结果称作为一次聚焦,也就是是说经过多次的查找才能找到一个空的单元:

    Hkey(x) = Hkey(n)+ i;

也就是当出现和n重复的hash值的时候,则需要逐个进行探测,因为可以回绕,所以可以只取一个方向继续查找空单元。不过分析一下可以看出,当表中元素多于一半的话,则需要查找的次数就更多了,这也就不再是一种好办法,耗费了大量的时间。

平法探测法:

平法探测法是消除线性探测法聚集问题的一种方法,流行的选择是f(i)= i^2.对于平方探测法,单元被填满,情况要比线性探测法更加严重,一旦表的大小超过一半,表的大小不是素数的时候,有可能在表被填充到一半之前就可能找不到空单元了,因此最多只有一半的空位置用来解决冲突问题。

平方探测法实现:

/**
 * Probing table implementation of hash table
 * Note that all "matching" is based on the equals methods
 * @author **********
 *
 */
public class QuadraticProbingHashTableExec <AnyType>{
	
	private static final int DEFAULT_TABLE_SIZE = 101; 
	private HashEntry<AnyType> [] array;// The array of elements
	private int occupied; //The number of occupied cells
	private int theSize; // Current size
	

	/**
	 * Constructor the hash table
	 */
	public QuadraticProbingHashTableExec(){
		this(DEFAULT_TABLE_SIZE);
	}
	
	/**
	 * Construct the hash table
	 * @param size the approximate initial size
	 */
	public QuadraticProbingHashTableExec(int size){
		allocateArray(size);
		doClear();
	}
	
	/**
	 * Insert into the hash table .if the item is
	 * already present, do nothing.
	 * @param x is the item to insert
	 * @return the result of insert
	 */
	public boolean insert(AnyType x){
		
		//Insert x as active
		int currentPos = findPos(x);
		if(isActive(currentPos))
			return false;
		
		if(array[currentPos] == null){
			++ occupied;
		}
		array[currentPos] = new HashEntry<>(x,true);
		theSize ++;
		
		//Rehash : see Section 
		
		if(occupied > array.length/2){
			rehash();
		}
		
		return true;
	}
	
	/**
	 * Expand the hash table
	 */
	private void rehash(){
		HashEntry<AnyType> [] oldArray = array;
		
		//Create a new double-sized ,empty table
		allocateArray(2 * oldArray.length);
		occupied = 0;
		theSize = 0;
		
		//Copy the table over
		for (HashEntry<AnyType> hashEntry : oldArray) {
			if(hashEntry != null && hashEntry.isActive)
				insert(hashEntry.element);
		}
	}
	
	/**
	 * Method that-performs quadratic probing resolution
	 * @param x the item to search for
	 * @return the position where the search terminates.
	 */
	private int findPos(AnyType x){
		int offset = 1;
		int currentPos = myhash(x);
		
		while(array[currentPos] != null &&
				! array[currentPos].element.equals(x)){
			currentPos += offset;//Compute the ith probe
			offset += 2;
			if(currentPos >= array.length){
				currentPos -= array.length;
			}
		}
		return currentPos;
	}
	
	public boolean remove(AnyType x){
		int currentPos = findPos(x);
		if(isActive(currentPos)){
			array[currentPos].isActive = false;
			theSize --;
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * Get current size
	 * @return the size
	 */
	public int size(){
		return theSize;
	}
	
	/**
	 * Get length of internal table
	 * @return the size 
	 */
	public int capacity(){
		return array.length;
	}
	
	/**
	 * Find an item in the hash table
	 * @param x the item to search for 
	 * @return the matching item
	 */
	public boolean contains(AnyType x){
		int currentPos = findPos(x);
		return isActive(currentPos);
	}
	
	/**
	 * Return true if currentPos exit and is active
	 * @param currentPos the result of a call to findPos
	 * @return true if currentPos is active
	 */
	private boolean isActive( int currentPos){
		return array[currentPos] != null && array[currentPos].isActive;
	}
	
	/**
	 * Method to obtain the hash code 
	 * @param x the element
	 * @return the hash code
	 */
	private int myhash(AnyType x){
		int hashVal = x.hashCode();
		
		hashVal %= array.length;
		if(hashVal < 0){
			hashVal += array.length;
		}
		return hashVal;
	}
	
	/**
	 * Internal method to allocate array
	 * @param arraySize arraySize the size of the array
	 */
	private void allocateArray(int arraySize){
		array = new HashEntry[nextPrime(arraySize)];
		String s = "nusjks";
		s.hashCode();
	}

	
	/**
	 * Internal method to find a prime number at least as large as n
	 * @param n the starting number (must be positive)
	 * @return a prime number larger than or equal to n
	 */
	private static int nextPrime(int n){
		if( n % 2 == 0)
			n++;
		for(;!isPrime(n) ; n += 2)
			;
		return n;
	}
	
	/**
	 * Internal method to test if a number is prime
	 * Not an efficient algorithm
	 * @param n the number to test
	 * @return the result of the test
	 */
	private static boolean isPrime(int n){
		if(n == 2 || n == 3)
			return true;
		if(n ==1 || n % 2 == 0)
			return false;
		for(int i = 3 ; i * i <= n; i += 2){
			if(n % 2 == 0)
				return false;
		}
		
		return true;
	}
	
	/**
	 * Make the hash table empty
	 */
	public void makeEmpty(){
		doClear();
	}

	private void doClear(){
		occupied = 0;
		for (int i = 0; i< array.length ; i ++){
			array[i] = null;
		}
	}
	
	
	/**
	 * to define a data structure to contains the data 
	 * @author Zhang tianlong
	 *
	 * @param <AnyType>  the type of elements
	 */
	private static class HashEntry<AnyType>{
		
		public AnyType element; //the elements
		public boolean isActive;// false if marked deleted
		/**
		 * constructor
		 * @param e 
		 */
		public HashEntry(AnyType e){
			this(e,true);
		}
		
		public HashEntry(AnyType e,boolean i){
			element = e;
			isActive = i;
		}
	}
}


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18870127/article/details/80319108
个人分类: 数据结构学习
上一篇数据结构学习笔记(五)散列、分离链接法
下一篇Java虚拟机Class装在系统初探(一)之类的加载
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭