查找算法之哈希查找

哈希查找是通过计算数据元素的存储地址进行查找的一种方法。O(1)的查找,即所谓的秒杀。哈希查找的本质是先将数据映射成它的哈希值。哈希查找的核心是构造一个哈希函数,它将原来直观、整洁的数据映射为看上去似乎是随机的一些整数。

哈希查找的操作步骤:

1)       用给定的哈希函数构造哈希表;

2)       根据选择的冲突处理方法解决地址冲突;

3)       在哈希表的基础上执行哈希查找。

建立哈希表操作步骤:

1)       step1 取数据元素的关键字key,计算其哈希函数值(地址)。若该地址对应的存储空间还没有被占用,则将该元素存入;否则执行step2解决冲突。

2)       step2 根据选择的冲突处理方法,计算关键字key的下一个存储地址。若下一个存储地址仍被占用,则继续执行step2,直到找到能用的存储地址为止。

哈希查找步骤为:

1)       Step1 对给定k值,计算哈希地址 Di=Hk);若HST为空,则查找失败;若HST=k,则查找成功;否则,执行step2(处理冲突)。

2)       Step2 重复计算处理冲突的下一个存储地址 Dk=RDk-1),直到HST[Dk]为空,或HST[Dk]=k为止。若HST[Dk]=K,则查找成功,否则查找失败。

 

比如说:”5“是一个要保存的数,然后我丢给哈希函数,哈希函数给我返回一个”2",那么此时的”5“和“2”就建立一种对应关系,这种关系就是所谓的“哈希关系”,在实际应用中也就形成了”2“是key,”5“是value

那么有的朋友就会问如何做哈希,首先做哈希必须要遵守两点原则:

: key尽可能的分散,也就是我丢一个“6”和“5”给你,你都返回一个“2”,那么这样的哈希函数不尽完美。

②:哈希函数尽可能的简单,也就是说丢一个“6”给你,你哈希函数要搞1小时才能给我,这样也是不好的。

其实常用的做哈希的手法有“五种”:

第一种:”直接定址法“。

很容易理解,key=Value+C;这个“C"是常量。Value+C其实就是一个简单的哈希函数。

第二种:“除法取余法”。

很容易理解, key=value%C;解释同上。

第三种:“数字分析法”。

这种蛮有意思,比如有一组value1=112233value2=112633value3=119033

针对这样的数我们分析数中间两个数比较波动,其他数不变。那么我们取key的值就可以是

key1=22,key2=26,key3=90

第四种:“平方取中法”。此处忽略,见名识意。

第五种:“折叠法”。

这种蛮有意思,比如value=135790,要求key2位数的散列值。那么我们将value变为13+57+90=160,然后去掉高位“1,此时key=60,哈哈,这就是他们的哈希关系,这样做的目的就是key与每一位value都相关,来做到“散列地址”尽可能分散的目地。

影响哈希查找效率的一个重要因素是哈希函数本身。当两个不同的数据元素的哈希值相同时,就会发生冲突。为减少发生冲突的可能性,哈希函数应该将数据尽可能分散地映射到哈希表的每一个表项中。

解决冲突的方法有以下两种:  

(1)   开放地址法  

如果两个数据元素的哈希值相同,则在哈希表中为后插入的数据元素另外选择一个表项。当程序查找哈希表时,如果没有在第一个对应的哈希表项中找到符合查找要求的数据元素,程序就会继续往后查找,直到找到一个符合查找要求的数据元素,或者遇到一个空的表项。  

(2)   链地址法

将哈希值相同的数据元素存放在一个链表中,在查找哈希表的过程中,当查找到这个链表时,必须采用线性查找方法。

 

实现哈希函数为“除法取余法”,解决冲突为“开放地址线性探测法”,代码如下:

 

public class HashSearch {

	public static void main(String[] args) {
		//“除法取余法”
        int hashLength = 13;

        int [] array  = { 13, 29, 27, 28, 26, 30, 38 };

        //哈希表长度
        int[] hash = new int[hashLength];
        //创建hash
        for (int i = 0; i < array.length; i++)
        {
            insertHash(hash, hashLength, array[i]);
        }
        
        int result = searchHash(hash,hashLength, 29);

		if (result != -1)
			System.out.println("已经在数组中找到,索引位置为:" + result);
		else
			System.out.println("没有此原始");
	}

	/****
	 * Hash表检索数据
	 * 
	 * @param hash
	 * @param hashLength
	 * @param key
	 * @return
	 */
	public static int searchHash(int[] hash, int hashLength, int key) {
		// 哈希函数
		int hashAddress = key % hashLength;

		// 指定hashAdrress对应值存在但不是关键值,则用开放寻址法解决
		while (hash[hashAddress] != 0 && hash[hashAddress] != key) {
			hashAddress = (++hashAddress) % hashLength;
		}

		// 查找到了开放单元,表示查找失败
		if (hash[hashAddress] == 0)
			return -1;
		return hashAddress;

	}

	/***
	 * 数据插入Hash表
	 * 
	 * @param hash 哈希表
	 * @param hashLength
	 * @param data
	 */
	public static void insertHash(int[] hash, int hashLength, int data) {
		// 哈希函数
		int hashAddress = data % hashLength;

		// 如果key存在,则说明已经被别人占用,此时必须解决冲突
		while (hash[hashAddress] != 0) {
			// 用开放寻址法找到
			hashAddress = (++hashAddress) % hashLength;
		}

		// 将data存入字典中
		hash[hashAddress] = data;
	}
}

运行结果:
已经在数组中找到,索引位置为:3


 

  • 15
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
哈希查找算法是一种高效的查找算法,它通过将关键字映射到哈希表中的位置来实现查找。下面是一个简单的Python实现: ```python # 定义哈希表类 class HashTable: def __init__(self): self.size = 11 self.slots = [None] * self.size self.data = [None] * self.size # 哈希函数 def hashfunction(self, key, size): return key % size # 插入数据 def put(self, key, data): hashvalue = self.hashfunction(key, len(self.slots)) if self.slots[hashvalue] == None: self.slots[hashvalue] = key self.data[hashvalue] = data else: if self.slots[hashvalue] == key: self.data[hashvalue] = data # 更新数据 else: nextslot = self.rehash(hashvalue, len(self.slots)) while self.slots[nextslot] != None and self.slots[nextslot] != key: nextslot = self.rehash(nextslot, len(self.slots)) if self.slots[nextslot] == None: self.slots[nextslot] = key self.data[nextslot] = data else: self.data[nextslot] = data # 更新数据 # 查找数据 def get(self, key): startslot = self.hashfunction(key, len(self.slots)) data = None stop = False found = False position = startslot while self.slots[position] != None and not found and not stop: if self.slots[position] == key: found = True data = self.data[position] else: position = self.rehash(position, len(self.slots)) if position == startslot: stop = True return data # 重新哈希 def rehash(self, oldhash, size): return (oldhash + 1) % size ``` 上述代码中,我们定义了一个哈希表类`HashTable`,并实现了哈希函数`hashfunction`、插入数据方法`put`、查找数据方法`get`和重新哈希方法`rehash`。我们可以通过以下代码来测试这个哈希表类: ```python H = HashTable() H.put(54, "cat") H.put(26, "dog") H.put(93, "lion") H.put(17, "tiger") H.put(77, "bird") H.put(31, "cow") H.put(44, "goat") H.put(55, "pig") H.put(20, "chicken") print(H.slots) print(H.data) print(H.get(20)) ``` 输出结果为: ``` [77, 44, 55, 20, 26, 93, None, None, 17, None, 31] ['bird', 'goat', 'pig', 'chicken', 'dog', 'lion', None, None, 'tiger', None, 'cow'] chicken ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值