标签:
哈希表和哈希函数
在记录的存储位置和它的关键字之间是建立一个确定的对应关系(映射函数),使每个关键字和一个存储位置能唯一对应。这个映射函数称为哈希函数,根据这个原则建立的表称为哈希表(Hash Table),也叫散列表。
以上描述,如果通过数学形式来描述就是:
若查找关键字为 key,则其值存放在 f(key) 的存储位置上。由此,不需比较便可直接取得所查记录。
注:哈希查找与线性表查找和树表查找最大的区别在于,不用数值比较。
冲突
若 key1 ≠ key2 ,而 f(key1) = f(key2),这种情况称为冲突(Collision)。
根据哈希函数f(key)和处理冲突的方法将一组关键字映射到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这一映射过程称为构造哈希表。
构造哈希表这个场景就像汽车找停车位,如果车位被人占了,只能找空的地方停。
构造哈希表
由以上内容可知,哈希查找本身其实不费吹灰之力,问题的关键在于如何构造哈希表和处理冲突。
常见的构造哈希表的方法有 5 种:
(1)直接定址法
说白了,就是小学时学过的一元一次方程。
即 f(key) = a * key + b。其中,a和b 是常数。
(2)数字分析法
假设关键字是R进制数(如十进制)。并且哈希表中可能出现的关键字都是事先知道的,则可选取关键字的若干数位组成哈希地址。
选取的原则是使得到的哈希地址尽量避免冲突,即所选数位上的数字尽可能是随机的。
(3)平方取中法
取关键字平方后的中间几位为哈希地址。通常在选定哈希函数时不一定能知道关键字的全部情况,仅取其中的几位为地址不一定合适;
而一个数平方后的中间几位数和数的每一位都相关, 由此得到的哈希地址随机性更大。取的位数由表长决定。
(4)除留余数法
取关键字被某个不大于哈希表表长 m 的数 p 除后所得的余数为哈希地址。
即 f(key) = key % p (p ≤ m)
这是一种最简单、最常用的方法,它不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。
注意:p的选择很重要,如果选的不好,容易产生冲突。根据经验,一般情况下可以选p为素数。
(5)随机数法
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即 f(key) = random(key)。
通常,在关键字长度不等时采用此法构造哈希函数较为恰当。
解决冲突
设计合理的哈希函数可以减少冲突,但不能完全避免冲突。
所以需要有解决冲突的方法,常见有两类
(1)开放定址法
如果两个数据元素的哈希值相同,则在哈希表中为后插入的数据元素另外选择一个表项。
当程序查找哈希表时,如果没有在第一个对应的哈希表项中找到符合查找要求的数据元素,程序就会继续往后查找,直到找到一个符合查找要求的数据元素,或者遇到一个空的表项。
例子
若要将一组关键字序列 {1, 9, 25, 11, 12, 35, 17, 29} 存放到哈希表中。
采用除留余数法构造哈希表;采用开放定址法处理冲突。
不妨设选取的p和m为13,由 f(key) = key % 13 可以得到下表。
需要注意的是,在上图中有两个关键字的探查次数为 2 ,其他都是1。
这个过程是这样的:
a. 12 % 13 结果是12,而它的前面有个 25 ,25 % 13 也是12,存在冲突。
我们使用开放定址法 (12 + 1) % 13 = 0,没有冲突,完成。
b. 35 % 13 结果是 9,而它的前面有个 9,9 % 13也是 9,存在冲突。
我们使用开放定址法 (9 + 1) % 13 = 10,没有冲突,完成。
(2)拉链法
将哈希值相同的数据元素存放在一个链表中,在查找哈希表的过程中,当查找到这个链表时,必须采用线性查找方法。
在这种方法中,哈希表中每个单元存放的不再是记录本身,而是相应同义词单链表的头指针。
例子
如果对开放定址法例子中提到的序列使用拉链法,得到的结果如下图所示:
![技术分享](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAhYAAAFcCAIAAAAbDmATAAAgAElEQVR4nO2dS2wcV7rfe6kACTIXCAIhi8C73KWXzl0MEmRzgQuT9u7iJk6cZAJ4FXk2gW8AQiSbZL8fpCi+1ZRJSpTopmhLtGxzTF4PTXFawgxl8xJsjwWQFxyJhqYDEAIFEDAXJ4tDlZr9rDpdj646vx8KAllddf7nO/Wd71+vpkICAABAiZDXHQAAAL+ChQAAgCJYCAAAKIKFAACAIlgIAAAogoUAAIAiWAgAACiChQAAgCJYCAAAKIKFAACAIlgIAAAogoUAAIAiWAgAACiChQAAgCJYCLhHKBQKhUKN15j8tPGOVjcOhUIffPCBydasalmN2kyb1Z9Wb1BvfSs9AaiA7IHmhExjph0zK6s/qtis3l5WJYwNPvjgg8ZBmQy8WsvMmsaYH1u5mcnDodATgArIHmiOmfLtnIWUV0bjWqHpXub7VlF5zexoXt1SyOXxVkRqyRLMjGdjmgoBSMgVaE4rZdHqNo11610rNFYxWfFN1tPGKxs3+Pbbb9dcX92ItJCanzYIpLwPDTY2MzIAZiB7oDlN66wwUaYNkslkzUbq1dOaDVY/uqjY3pJEea8atFlzKKqbqhdCKBR6++23a/azZiPm+xMKhe7evVtvBGqOYb0GASxB9kBzqktbxXphrhhZKlg1i77xkXE5YqZ9M5W0gbE1aKdiZITdFtJgWBTCFFWj2jhegKaQLtCcivpisrw2bafmp8bP8rS64s5PeQmubkettpqsmw1qbvkVTEUU1UPUoM/ljbT4eL/eXmqxA9SD7IHmNC589dbUa6e61DZoU1pI+a9N66OlvlV3yUz9LV8ZsmIh5Y5Ys6lQmYXUGcXaNBhYM3sBqEH2QHOqy5xx571euazXSIPtqz+tKOKhKkepqdjACaobrOhVvf40/ahmBa8WNfrfYHth3UIaD6ylYWkwIADVkCjQnAbFpeZHT7J/Zaz5q+wT+UO9573VP5dvUH0VUnP3VlYqlNQGaxoEFbJoIWZ6Yqb/ohZNNwAwA9kDzakuhY2raoWFNG6n5kfGymrPqFcl69XEplWy3gb1mmqg3jioinDqDYLE5PsC1VE3HdUG2zQdK4AKSBdoTs3KUl0fm1afBrvUk2jxKsRSr8zv26C4t24h4vxViJnoLFlCheWUr8E/wCpkDDSnuio1rd1N2xH1a3f5BhWvYFmyEJOWYKn+WvrIqoU0/chMV40DVH3nUNR3C/wD1CBpoDkNKlGDbcy0Y2Z9uc00LfEV25sRstqris40GIfqzWy0kHrr641A9WDW623NzgDUhHSB5lSXwno0aKH8JS6TjYTqvwXbYBer/ay5psGXvesFW71XvXDqSZgc9nrb1wunccv1PmrcAoCERIHm2FK5XC5M9eTMWIillZY2aLE12y3EZFcB6kEOAQCAIlgIAAAogoUAAIAiWAgAACiChQAAgCJYCAAAKIKFAACAIlgIAAAogoUAAIAiWAgAACiChQAAgCJYCAAAKIKFAACAIlgIAAAogoUAAIAiWAgAACiChQAAgCJYCAAAKIKFAACAIlgIAAAogoUAAIAiWAgAACiChQAAgCJYCAAAKIKFAACAIlgIAAAogoUAAIAiWAgAACiChQAAgCKKFjJy+7dvvRdnYbG6/Je/n0bR9uU//1+3FVmCsYQn7ntjIZ5HzsLCwsLS+uKlhXT2rLq2oBgARSNrUQyAomtyKDqqiIWg6BtFfcqrDoquyaHoqCIWgqJvFPUprzoouiaHoqOKWAiKvlHUp7zqoOiaHIqOKmIhKPpGUZ/yqoOia3IoOqqIhaDoG0V9yqsOiq7JoeioIhaCom8U9SmvOii6Joeio4pYCIq+UdSnvOqg6Jocio4qYiEo+kZRn/Kqg6Jrcig6qoiFoOgbRX3Kqw6Krsmh6KgiFoKibxT1Ka86KLomh6KjilgIir5R1Ke86qDomhyKjipiISj6RlGf8qqDomtyKDqq6BsL6egp5EtGA8/TroxvuqiipabYMbb/1IivuOO2Ymn/kvOKrw7lTkEIIV7mx1TkLCmmi+cS7+l6wWnFFgfWquI5LaUwFWJ8dQTdm4znFK3nqiXF6lmvUHxaVGy83pEYrdcfn1lIuvg6dcp/diKHOs+lrBsW0tGzU3glJI+l1WJnXbGQL50VcRms04rGcmn9pSi9fOqahSj5sbKiPHyFRfcUq9StDaxl05L19NWoujYZZX5WqNurWG/WKxSfFhUV6k8rimr1x08WUjExlOeJ+e3PEmXxuWtXIZXq1gufLxTPjt2i5SPY6RMLcV+xRXXrFrJTKPPIDutzxPL0Py/hnGLNWa9WfFpRbLDeOcXKbUxkka8spOKgnk9iG8e3sa6lxRcF/SxM1RNntavJp+sFhZOATj8UdIXMbD3GFo+j4lVIaf+Sw9cErxUb1nTbFRs7lslD3Ipi0/XOKcolgBZyaf3l+aNYyJdUbvia317hENqi2OliQS+/+6lW9ZQUn6eVqkCnsoUYqN5Dt/hk4mWh+NLQdOfpi1wurb90IcbO888GXLj/WXFrpWPxudUHaa2UV7Xi418LMV9/sJCWBtopRaXTulYUO43bow5f95QfNdcspHJgXXm43XqxU8ocxQsgFQuRJx/FfWkkatc91qJbfP66fFh/kIaFmFW0Un/8ZCH63MhSeDjZomIrkVrO2lehuW8hna4U9IozOOVEVYixotK5F6PD1wR1jqODT190vpFlqf74ykJcf5yucAhbV2zlHWLlGFuJ1JJixfu1Z1i59LHDQlRKj9VnIa+vQtyyEOV36lRi9Oh8zliUXxlQDNDJx+k1FZuud0jRav3xlYVUv0fo8BM8hUPYomKL/mE5h8b2nxrXBKp3z9RvK7lyFdKx+NwISu1mnUJBLz+PU7gyULQQ65cC6qN6/irk0vpLN69C1CJtzSNVio/vLESh/vjJQjrd/W5RZ41TZoeztsYXxJxVrIzR5acv7ljIuW+EqT/4VTndOUPxwq6VEyw3Yix/MuF8op7/JqOKU5pUrDfrFYpPi4oK9acVRbX64zMLaXFBMQCKLd7IQrGtFF2TQ9FRRSwERd8o6lNedVB0TQ5FRxWxEBR9o6hPedVB0TU5FB1VxEJQ9I2iPuVVB0XX5FB0VBELQdE3ivqUVx0UXZND0VFFLARF3yjqU151UHRNDkVHFbEQFH2jqE951UHRNTkUHVXEQlD0jaI+5VUHRdfkUHRUEQtB0TeK+pRXHRRdk0PRUUUsBEXfKOpTXnVQdE0ORUcVsRAUfaOoT3nVQdE1ORQdVcRCUPSNoj7lVQdF1+RQdFQRC0HRN4r6lFcdFF2TQ9FRRS8thIWFhYXF14s3FvL2/x7xPHIWPy7//r+i6IRiwmVFlmAs//F/Zb2xEM8jZ2FhYWFpffHSQnS4UYii7XIoBkPRNTkUHVXEQlD0jaI+5VUHRdfkUHRUEQtB0TeK+pRXHRRdk0PRUUUsBEXfKOpTXnVQdE0ORUcVsRAUfaOoT3nVQdE1ORQdVcRCUPSNoj7lVQdF1+RQdFQRC0HRN4r6lFcdFF2TQ9FRRSwERd8o6lNedVB0TQ5FRxWxEBR9o6hPedVB0TU5FB1VxEJQ9I2iPuVVB0XX5FB0VBELQdE3ivqUVx0UXZND0VFFLARF3yjqU151UHRNDkVHFbEQFH2jqE951UHRNTkUHVXEQlD0jaI+5VUHRdfkUHRU0WcW0tGzUxBCFHf8Mr6uBeijGFuUc3NUUXRO0eperSwUHOcU/WYhi8+FEEI8T/tkfF0L0Ecxtijn5qii6JyiVblWFgqOc4rK5iFx1UI6egr5kigsyn/9Mb6uBeiXGFuXc3NUUXRO0dIuLS4UHOcUfWUhi89Faf9Sz+ql9Zfyh/YfX9cC9EuMrcu5OaooOqdoSa7FhYLjnKJvLESeETxdL3T2rHaM7T8VL/NjboyvCIVEKOTCEW0xQF/E2IpWp1KxsyVtUHRC0fz2rS8UHOdG1T8WMrb/tOyOZLp4dnQDc0RbDNAXMbai1alW7OxIGxSdUDS/ffmilj8UHOcUfWMhFYewY/G5pWdc7X9EWwzQFzG2otWpVOxsSRsUnVA0L1e+uGYhgS84din6w0KqLyTly3bmn3G1+RFtPcD2j7FFrU7rxc6utEHRCUWTG1cs7lhI4AuOjYr+sJB0scar2TVXttv4uhZg+8fYolan9WJnV9qg6ISiyY0rFncsJPAFx0ZFf1hI64uPjmiwY3T5RpYtQ4qiE4pq+7p2I8urGLEQLKRVxWDHiIWgiIXYHqCHilhI2x3RYMeIhaCIhdgeoIeKWEjbHdFgx4iFoIiF2B6gh4pYSNsd0WDHiIWgiIXYHqCHilhI2x3RYMeIhaCIhdgeoIeKWEjbHdFgx4iFoIiF2B6gh4pYSNsd0WDHiIWgiIXYHqCHilhI2x3RYMeIhaCIhdgeoIeKWEjbHdFgx4iFoIiF2B6gh4pYSNsd0WDHiIWgiIXYHqCHilhI2x3RYMeIhaCIhdgeoIeKWEjbHdFgx4iFoIiF2B6gh4peWogvFjm+nncjMDHqMJ4szi2Bzx/3A2xR0RsL+VXPnOeHqm2PaLBjbFHrl/8j7fLgaKH4391WVF4CPx/9ZSHv/nrcGwvxE6GQCAU9TDdj1GE8wTkCnz/uB+jpkAb6WEoCn7ICCwH/EPj8wUKCRuBTVmAh4B8Cnz9YSNAIfMoKLAT8Q+DzBwsJGoFPWYGFgH8IfP5gIUEj8CkrsBDwD4HPHywkaAQ+ZQUWAv4h8PmDhQSNwKeswELAPwQ+f7CQoBH4lBVYCPiHwOcPFhI0Ap+yAgsB/xD4/MFCgkbgU1ZgIeAfAp8/WEjQCHzKCiwE/EPg8wcLCRqBT1mBhYB/CHz+YCFBI/ApK7AQ8A+Bzx8sJGgEPmUFFgL+IfD5g4UEjcCnrMBCwD8EPn+wkKAR+JQVWAj4h8DnDxYSNAKfsgILAf8Q+PzBQoJG4FNWYCHgHwKfP1hI0Ah8ygosBPxD4PMHCwkagU9ZgYWAfwh8/mAhQSPwKSuwEPAPgc8fLCRoBD5lBRYC/iHw+YOFBI3Ap6zAQsA/BD5/sJCgEfiUFVgI+IfA5w8WEjQCn7ICCwH/EPj8wUJ8z/S0CIXE/PzZr+Xj+/ix+MUvxAcfeNU123AzRh3GE1wjeBbi+QTBQmxmfl6EQuLiRXFyIsT58X3rLREKiY8+8rB39uBmjDqMJziH5xXWadyfIO00pEG0ECHEm2+KUEh8+KEQZeNbcaT9jpsx6jCe4BA6nIK4PEHaaUgDaiGPH4tQSFy4IIrFs/E9OREXL4pQSExPe905m3AzRh3GE5wj8Kcg7k+QthnSgFqIEOL990UoJN5552x8P/pIhELizTe97patuBmjDuMJDqHDKYjLE6RthjS4FvLTT+LChbPBlWMdConHj73ulq24GaMO4wnOEfhTEPcnSHsMaXAtRAgRibw+oqGQeP99rzvkAG7GqMN4gkPocAri8gRpjyENtIWcnIg33ng9vj/95HWHHMDNGHUYT3COwJ+CuD9B2mBIA20hQoilpbPBzWS87opjuBmjDuMJDqHDKYjLE6QNhjToFiKE+Ou/Fn/5l0F466MBbsaow3iCQ+hwCuLyBPF6SH1jISO3f/vWe3GF5b2/+fDD//Q/FXYMT9wPfIyeaLk/sGA7yrn6u3/z7/7pX/7rX/7dQPunjVqMbk7GFofUllH1jYW4eUiMRYcYdRhYsB3lQ99KhfVLjC4vLZpWi6PkMwvp7Fl1Z/EwZV2L0QjTfUWXBxZsh/nIZJRgIfqmrH+zFjyH+chklGAh+qasf7MWPIf5yGSUYCH6pqx/sxY8h/nIZJRgIfqmrH+zFjyH+chklGAh+qasf7MWPIf5yGSUYCH6pqx/sxY8h/nIZJRgIfqmrH+zFjyH+chklGAh+qasf7MWPIf5yGSUYCH6pqx/sxY8h/nIZJRgIfqmrH+zFjyH+chklGAh+qasf7MWPIf5yGSUYCH6pqx/sxY8h/nIZJQE3ELSRSHE83SwUrZjbP+psU9x5/X6np2Csb60f8nurK0YzHPdeMXT9UIbDizYjtX5qJCcnqeN+Rjr1RlL9afF6Z8unut805lo16gG1kLKUjZQFtLRs1N4FZFMJpkrMt5XPxfypXPp1WrWmhjMjrH9p+JlfqwdBxZsx9J8VEtOz9PG9HyUnJsaCvWnlenfKS3Ei1ENrIWki0KU9i8tPg+YhdQIs7jT2bPacT7SDnOBm1Q0M5gmMxgLCQbWLEQpOT1PGzMx1psaCvWnlelvfgLaPqqBtRDlZG3zlK2XQ5Wz1Mo1QeuDKU+ICottOrBgOy1ZiLnk9DxtzMdYb2pYqj9YiLNgITWiKyvcFVe1HYvPhYsWcmn9paWnLy4PLNiOtcxRSk7P06bNLaTivO3csxAXJyMW4suU7ax1T7lj8fnrtkovXbsKkbd9zVyCeDWwYDuW65315PQ8bdrZQho8Ujr7yISLYCHqh9bvKdtp3GxtLXBbLOTS+kur88TlgQXbUZuPyrOyzeej+xZiYvq79G4LFuLLlG36sqClh9utDGb5yzZtO7BgO61YiFd37Z2L0WULaTr9LZ1BtjhKWIj/UtZcApm6UWCDhVi8r42FBANlC1F4ENLm87FBnXHCQmpO/47F54Yrn71P7NbrkYG1kIov2gTm8V2tL/S9zI+d/+qW6WCtZG2lYqfSO/5YSDCweONeJTk9TxszMdabGgr1p7XpX8iXXq8yeVcAC3FwaduUdSJM9xVdHliwHeYjk1GCheibsv7NWvAc5iOTUYKF6Juy/s1a8BzmI5NRgoXom7L+zVrwHOYjk1GCheibsv7NWvAc5iOTUYKF6Juy/s1a8BzmI5NRgoXom7L+zVrwHOYjk1GCheibsv7NWvAc5iOTUYKF6Juy/s1a8BzmI5NRgoXom7L+zVrwHOYjk1GCheibsv7NWvAc5iOTUYKF6Juy/s1a8BzmI5NRgoXom7L+zVrwHOYjk1HiMwtxedEhRh0GFmxHh7TxfJr4YlR9YyG/6plzeWTf/fV44GP0ZHF/YMF2lHP18J//hQiF3n3379s/bfwyH0UoJEIhryajbywEAILAG2+IUEjs73vdjwARComQZ5UcCwEAF8FCbAcLAQBdwEJsBwsBAF3AQmwHCwEAXcBCbAcLAQBdwEJsBwsBAF3AQmwHCwEAXcBCbAcLAQBdwEJsBwsBAF3AQmwHCwEAXcBCbAcLAQBdwEJsBwsBAF3AQmwHCwEAXcBCbAcLAQBdwEJsBwsBAF3AQmwHCwEAXcBCbAcLAQBdwEJsBwsBAF3AQmwHCwEAXcBCbAcLAQBdwEJsBwsBAF3AQmwHCwEAXcBCbAcLAQBdwEJsBwsBAF3AQmwHCwEAXcBCbAcLAYDAsrQkLlwQS0tnv5ZbSLEoLl4UH33kXef8iRzSf/iHs1/LLcT1IcVCAMBJRkdFKCQuXhQnJ0Kct5B33hGhEBZiGTmkb7xxNqTlFuL6kGIhAOAkJyfizTdFKCQuXxaizEKWlkQoJC5cED/95HEPfYcxpJmMEGUW4sWQYiEA4DBffPG6tEkLKRbPFUGwSvmQSgup8BW3wEIAwHnkDZa//dszC/nwQxEKiTffPLsVAwrIIX3//TMLyWQ8GVIsBACcZ39fXLhwduJs/PvFF153y88YQyqXX/zCkyHFQgDAFT766HW9C4XEO+943SH/0wZDioUAgCucnIiLF8+KHU/RbaENhhQLAQC3mJ8/q3fy7SxoHa+HFAsBAMuM3P7tW+/FFZZ//Ff/9v/9s3/xy78bsLpjeOK+10E7i/tDasuoYiEAYBm1YvfWe/H3/ubD//Mf/pvavl4H7SyeDGnro4qFAIBlZPXp7Fl1Z9HHQlwbUrtGFQsBAMtgIbaDhQCALmAhtoOFAIAuYCG2g4UAgC5gIbaDhQCALmAhtoOFAIAuYCG2g4UAgC5gIbaDhQCALmAhtoOFAIAuYCG2g4UAgC5gIbaDhQCALmAhtoOFAIAuYCG2g4UAgC5gIbaDhQCALpipdx1j+0+NHUr7l16tTxfPNfV0vYCFCIsWki4KIZ6n6412cQcLAYD2pWm96+gp5Esv82Py551CmVWki2ZrHBZSa2B3Cmd7vLaQjp6dwqtfpZe4ZsxYCABYxupdl3LbwEJqYnJI00UhSvuXFp9XXIXUG20sBADaDksWIs+LC4vWChwW0mhIsRAA8C9Wn4UY/tFZ8Syk7BkJFmKLhVQYNhYCAG2HtXonb99XnRd39BTyJVMugoWYtJCzIeVxOgC0M1afhdQteYvPhTh76o6FtG4hZ09KzDWChQCAN9hqIXXv6WMhlsaz+k1fLAQA2pHmL/WO7T99dTpcfnelY/G5cZul3g0uLETBQqz6BxYCAJ5hpt6de2z+2jYK+dLr1Wa+voCF1B1VIeRtwHPfKyxbj4UAQDvCHzixHf7ACQDoAhZiO1gIAOgCFmI7WAgA6AIWYjtYCADoAhZiO1gIAOgCFmI7WAgA6AIWYjtYCADoAhZiO1gIAOgCFmI7WAgA6AIWYjtYCADoAhZiO1gIAOgCFmI7WAgA6IKsPi4vXgftLJ4MKRYCAB7wq545lyvdu78e9zpoZ3F/SG0ZVSwEAAAUwUIAAEARLAQAABTBQgAAQBEsBAAAFMFCAABAESwEAAAUwUIAAEARLAQAABTBQgAAQBEsBAAAFMFCAABAESwEAAAUwUIAAEARLAQAABTBQgAAQBEsBAAAFMFCAABAESwEAAAUwUIAAEARLAQAABTBQgAAQBEsBAAAFMFCAABAESwEAAAUwUKgLTg+Pj46OvK6F/bw448/rq2tra2t7e7uet0XAGfBQsBOTk5Otra21tbWtra2Tk5Oam5zfHy8vb0ttxFCnJ6eTk5ORiKRWCw2Ozvrbn8tcHx8vNeQ09NTIcTR0VEkErl169atW7fC4fDx8bHXHQdwECwE7GR+fn50dHR2dnZ8fHxiYqJ6g9PT03Q6PTExMTs7OzQ0tLm5ubq6+vHHHxcKhUKhEIvF2vNaRHZ7uD7pdPqTTz4RQmxvb09MTBQKhc3Nze7ubq87DuAsWAjYyfz8/Pz8/Nra2tdff12zgD548GBqakre50mn04eHhyMjI0tLS3KXcDgsz+XNMDMz09XV1dXVFY/HnT7Z397eHh0dXavPJ598ksvlhBDLy8szMzNra2tLS0sjIyOO9grAc7AQsJO1tbXx8fHl5eXl5eXe3t6Ke1mnp6exWGxpaWl5eXl2dnZmZkbukkwms9lsJBL5/vvvTQodHh4mk0kpFIlEnL522d3dzWQy41V89tlnsg8TExOrq6tCiPHx8Zs3by4vL09NTS0vLzvaKwDPwULATra2toaGhhYWFhYWFhKJxOHhYfmnGxsbw8PDCwsLt2/fTiaTpVJJrj88PNzb26tnA6enp3t7exVutL29PTg4uLCwMD8/Hw6H6/VH7msINUY+7WgQWvllx8LCQiwWm5+fX1hYuHHjRiaTkT0Mh8Ny5dDQkHzY07hZycHBgfnLLyHE0dHRwcGBvW0CKICFgJ3s7e0lk8nr169fv349lUr9+OOPxkenp6fRaPTatWvXr18fGhq6e/euXHn16lV5P2p+fr68qZOTk8XFxd7e3suXLyeTyd7e3mw2e3h4eHh42N/f39XVdeXKlevXr4+Pj8vdu7u7f/jhB2Pf3/zmN8a+kUikq6vrxo0b5fe7Tk5OhoeH5Y4//vjjrVu3+vr6kslkLBar9yJA+b6Dg4OTk5PXr1+fnp5Op9OyoJdKpUgkIsOPRCKbm5vZbFY2293d/e2331a0c3R0NDU11dXVlUgkLl++PDU1dXx8PDk5KXv13XffVfRzb29vd3c3Go0ODAwkEomabZZKpaZtAtgFFgJ2cnx8HA6HR0ZGRkZGEomEPA2XbGxsJJPJkZGRq1evDgwMyGq+vb1trLx8+bKx8d7e3sDAQDqdvnr16sgrBgcHBwYGxsfH0+n0SBWpVOr27dviVR1PpVLl+8oNYrGYcUViSCcSiXA4bLRp5jWqycnJwcFBo1mjLhttyqKfSCSMza5evRqPxwuFgtHIDz/8kEgkMpmM0cNMJtPf359IJGSv7t27V95mPB5PJBKJROLKlSv12vzuu+/i8XjTNgHsAgsBm5En/slksr+/f21tTa48PT2NRCKJRCKZTEaj0c8++0yuv3fv3sDAgFx55coVufLo6EiWy2QymUgkBgYG+vv7o9FoMpkMh8Pd3d2RSCQej0uVeDwejUaj0WgkEtna2jo6OspkMvLTRCLR39/f398fiUTkxuUqhnR/f38sFitvrXGAn376qbF9LBb79NNPjY+MNgcGBmSHY7FYRVfllqVSKRaLyRjldZLsZDwel41Ho1FpwOVtyu0btynXJxKJBm0C2AUWAjYTj8d7e3t7e3u7u7tv3bolV25sbPT19cn10WjUuFM0MjLS3d0tN5a3toQQQ0NDcmVvb288Hr9169ba2trQ0FA4HB4aGvr666+z2Wx/f3/vK+Tp9tLSkhAik8n09PQY+3755Zdra2ujo6PhcFiu7OvrkxcihrRE3uy6fPly+Ul9NY8fP45EInKXcDg8Pj5e/ml1m5lMJhKJGCu7uroqRkkOyOzs7MTERDQaNVYODAzIJ0lGmzIuk23G4/EGbQLYBRYCNjMxMWG4gvxqyOnp6cDAgFHBNzY2jI2N6tbf3y9PkHd3d42NBwYGyh8aP3r0SHrP1tZWuYUYGxQKhZr7lkolw8AGBgbkl8Z7y4hGo48fPxZCNL6FdXBwUF6RjUfo1eGUt1neW3mzrl6MKysrRj+N23o123z06FHFluVtRiIR4wF+uXmX3yoEsAUsBGzm3r170Wg0m82mUqlEIiGE2NjYiMfj2Ww2nU5HIhHjNaFSqTQwMJDNZrPZbDQalSfIo6OjiUQim83GYrG5ubnGEvF4fHJy0lhv7Fux/ujoqHAQswgAAAaKSURBVK+vTwrF4/Ht7e1y6UQikc/nm8Z1fHycSCTS6XQ2m5X3yipeIavX5traWiQSyWazyWQyk8k06Ofq6mosFpO7yxtu5tucnp6Wg1zR5ldffSW3NNoEsBEsBGxmc3MznU7ncrmpqane3l75Itbk5GQul8tkMuWXINvb23LLa9euye8hnp6e9vb2Xrt2LZfLpdPpejfuh4eHR0ZGZINfffWVXNlgX/mAPZfL5XK5ZDK5t7dnSOdyuf7+/qZfKzk9PZW3y2RvM5lM9Xu69dq8cePG0NBQLpcbGhqSD/x7e3unpqZkPx89emS0MDY2dvXq1Vwul81mjWfpRpt9fX3GRVIrbQLYCBYCNrO7uzs4OJjP5/P5fG9v7+rq6tWrV/P5/Ozs7ODgYPmWy8vLo6Oj+XxevpsrhDg4OEilUnLf8renKgiHw7dv387n84ODg8afMjw8PJTn6dX7bm1tXblyJZ/Pf/LJJ9LVqqUbMzc3l8vlZOMjIyPVr9LWDEeSTCZv3LiRz+eHh4c3NzflQ2/ZVPlXZ46Pj/v6+uT6K1euSAu0sc2hoaHt7e2mkQJYAgsBmymVSvF4fGVlZWVlJR6Ph8Ph5eXllZWV4eHhir9cOzExsbCwsLKyMj09Lb/Ivbu7Ozw8LPeNRqM1Lw7K2y/fZm9vb3BwsOa+htDCwoJ8PFMt3YCNjY2pqSnZ8tzc3J07d2puVrPNk5OTcDgs981kMgcHB/X6eefOnZmZGbk+lUpJG7CxzXg8bvIrlgDmwULAZk5PT7u7ux8+fPjw4UP57b+HDx+urKxU34gPh8MbGxsPHz6cmJiQJ8i7u7tjY2NyX2OlXD86OirvHW1tbU1NTcltjJeRhBCHh4eZTEauHxwcNJ5R/+EPf5icnJTrx8bGpI1VS9fjj3/84+joqNz9/v37uVyu3le+a7a5t7c3PDwsd+/u7pbfljfWZDIZaRWFQsFQ+d3vfmf8eTG72tzY2GjwHX4AZbAQsJ9IJPL48eNisfj73/9+Z2enWCyOj4+Xf1NdCFEqlVKpVLFYLBaLqVRKniCXr9zc3IzH46Ojo5FIZGpqSv5xRiGE/OMicpupqanh4eG+vr7V1dWTk5O+vj65/ptvvkmn0/l8fnR0dGpqSvbhyy+/lF+Aryldk5OTE/n4XW6czWa7quju7j44OKjX5vr6+q1bt2Q4w8PDFeryb01GIpG5ubnt7e3V1dVisfjtt9+Ojo426GfTNuWXQubm5h4/fiw7/80335Q/YwewCywE7GdsbGxra+vZKzY2Nqrfrdre3p6ZmXn27Nn+/n5fX1+9fbe2tp48efLs2bOpqSlpQru7u9PT08YG33///fLysvyu4ueff/7ll1/K9T/88IP8L0nkrw8ePJidnZUXEPWkqzG2bMDMzMz29na9Nufm5jY2Np49e7a2tra4uChXDg8Pf//990Y/ZYAzMzMyri+++OLzzz9v0M+mbT558uTJkycHBwfj4+NffPFFeZsA9oKFgP3cvXv33r17O68YHh6u/kbb/fv38/n8zs7O+vr6tWvXjPWlUimbza6vr+/v77948eLFixc7Ozu3b9/++OOP5Qbyz2o9ePDg8PDwxYsX+/v709PT8vaU/OjTTz/d2dmR+x4eHn733XfT09M3btwwbkDVk67m0aNHN2/e3GlIMpk8Pj6u12Y2m33w4MHOzs7Nmzc3Nzflyr29PXltJDv58OHD4eHhwcHBGzdu7OzszMzMyGfpVtscGxuTbf75z39++PCh/EtZf/rTn168eHHz5k2epYMTYCFgP0dHRzdv3sy9ombxOjw8nJmZyeVyMzMzFY/Nj4+P7969Ozg4KO8U5XK5ird7j4+P79y5E4vFurq6BgcHjTIq2dzczOVyct9YLDYzM1NxD62BdAWnp6fy+UcDZN/qtbm1tSU3u3v3bvlDlMPDQ6OTCwsL8s9Hyi3v37/fuJ9N2+zv719YWNje3k6lUj///PPPP/+cSqXa8//yAr+DhQAEgc3NzZWVFeMlgqOjozt37khzPTg4qPk/SAK0DhYC4HtKpdLg4OD6+vrExIS8skmlUsbFmbwi8baHEFSwEADfs7W1VfPbKvKOIn+dF5wDCwHwPUdHR6lUKpfLGf+p4t27d3O5XCqVqvg6J4C9YCEAAWFvb8+wkEePHjX933YBWgcLAQAARbAQAABQBAsBAABFsBAAAFAECwEAAEWwEAAAUAQLAQAARbAQAABQ5P8DSB29XViT27wAAAAASUVORK5CYII=)
实现一个哈希表
假设要实现一个哈希表,要求
a. 哈希函数采用除留余数法,即 f(key) = key % p (p ≤ m)
b. 解决冲突采用开放定址法,即 f2(key) = (f(key)+i) % size (p ≤ m)
(1)定义哈希表的数据结构
class HashTable {
public int key = 0; // 关键字
public int data = 0; // 数值
public int count = 0; // 探查次数
}
(2)在哈希表中查找关键字key
根据设定的哈希函数,计算哈希地址。如果出现地址冲突,则按设定的处理冲突的方法寻找下一个地址。
如此反复,直到不冲突为止(查找成功)或某个地址为空(查找失败)。
/**
* 查找哈希表
* 构造哈希表采用除留取余法,即f(key) = key mod p (p ≤ size)
* 解决冲突采用开放定址法,即f2(key) = (f(key) + i) mod p (1 ≤ i ≤ size-1)
* ha为哈希表,p为模,size为哈希表大小,key为要查找的关键字
*/
public int searchHashTable(HashTable[] ha, int p, int size, int key) {
int addr = key % p; // 采用除留取余法找哈希地址
// 若发生冲突,用开放定址法找下一个哈希地址
while (ha[addr].key != NULLKEY && ha[addr].key != key) {
addr = (addr + 1) % size;
}
if (ha[addr].key == key) {
return addr; // 查找成功
} else {
return FAILED; // 查找失败
}
}
(3)删除关键字为key的记录
在采用开放定址法处理冲突的哈希表上执行删除操作,只能在被删记录上做删除标记,而不能真正删除记录。
找到要删除的记录,将关键字置为删除标记DELKEY。
public int deleteHashTable(HashTable[] ha, int p, int size, int key) {
int addr = 0;
addr = searchHashTable(ha, p, size, key);
if (FAILED != addr) { // 找到记录
ha[addr].key = DELKEY; // 将该位置的关键字置为DELKEY
return SUCCESS;
} else {
return NULLKEY; // 查找不到记录,直接返回NULLKEY
}
}
(4)插入关键字为key的记录
将待插入的关键字key插入哈希表
先调用查找算法,若在表中找到待插入的关键字,则插入失败;
若在表中找到一个开放地址,则将待插入的结点插入到其中,则插入成功。
public void insertHashTable(HashTable[] ha, int p, int size, int key) {
int i = 1;
int addr = 0;
addr = key % p; // 通过哈希函数获取哈希地址
if (ha[addr].key == NULLKEY || ha[addr].key == DELKEY) { // 如果没有冲突,直接插入
ha[addr].key = key;
ha[addr].count = 1;
} else { // 如果有冲突,使用开放定址法处理冲突
do {
addr = (addr + 1) % size; // 寻找下一个哈希地址
i++;
} while (ha[addr].key != NULLKEY && ha[addr].key != DELKEY);
ha[addr].key = key;
ha[addr].count = i;
}
}
(5)建立哈希表
先将哈希表中各关键字清空,使其地址为开放的,然后调用插入算法将给定的关键字序列依次插入。
public void createHashTable(HashTable[] ha, int[] list, int p, int size) {
int i = 0;
// 将哈希表中的所有关键字清空
for (i = 0; i < ha.length; i++) {
ha[i].key = NULLKEY;
ha[i].count = 0;
}
// 将关键字序列依次插入哈希表中
for (i = 0; i < list.length; i++) {
this.insertHashTable(ha, p, size, list[i]);
}
}
完整代码
![技术分享](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![技术分享](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 class HashTable {
2 public int key = 0; // 关键字
3 public int data = 0; // 数值
4 public int count = 0; // 探查次数
5 }
6
7 public class HashSearch {
8
9 private final static int MAXSIZE = 20;
10 private final static int NULLKEY = 1;
11 private final static int DELKEY = 2;
12 private final static int SUCCESS = 0;
13 private final static int FAILED = 0xFFFFFFFF;
14
15 /**
16 * 查找哈希表
17 * 构造哈希表采用除留取余法,即f(key) = key mod p (p ≤ size)
18 * 解决冲突采用开放定址法,即f2(key) = (f(key) + i) mod p (1 ≤ i ≤ size-1)
19 * ha为哈希表,p为模,size为哈希表大小,key为要查找的关键字
20 */
21 public int searchHashTable(HashTable[] ha, int p, int size, int key) {
22 int addr = key % p; // 采用除留取余法找哈希地址
23
24 // 若发生冲突,用开放定址法找下一个哈希地址
25 while (ha[addr].key != NULLKEY && ha[addr].key != key) {
26 addr = (addr + 1) % size;
27 }
28
29 if (ha[addr].key == key) {
30 return addr; // 查找成功
31 } else {
32 return FAILED; // 查找失败
33 }
34 }
35
36 /**
37 * 删除哈希表中关键字为key的记录
38 * 找到要删除的记录,将关键字置为删除标记DELKEY
39 */
40 public int deleteHashTable(HashTable[] ha, int p, int size, int key) {
41 int addr = 0;
42 addr = searchHashTable(ha, p, size, key);
43 if (FAILED != addr) { // 找到记录
44 ha[addr].key = DELKEY; // 将该位置的关键字置为DELKEY
45 return SUCCESS;
46 } else {
47 return NULLKEY; // 查找不到记录,直接返回NULLKEY
48 }
49 }
50
51 /**
52 * 将待插入的关键字key插入哈希表
53 * 先调用查找算法,若在表中找到待插入的关键字,则插入失败;
54 * 若在表中找到一个开放地址,则将待插入的结点插入到其中,则插入成功。
55 */
56 public void insertHashTable(HashTable[] ha, int p, int size, int key) {
57 int i = 1;
58 int addr = 0;
59 addr = key % p; // 通过哈希函数获取哈希地址
60 if (ha[addr].key == NULLKEY || ha[addr].key == DELKEY) { // 如果没有冲突,直接插入
61 ha[addr].key = key;
62 ha[addr].count = 1;
63 } else { // 如果有冲突,使用开放定址法处理冲突
64 do {
65 addr = (addr + 1) % size; // 寻找下一个哈希地址
66 i++;
67 } while (ha[addr].key != NULLKEY && ha[addr].key != DELKEY);
68
69 ha[addr].key = key;
70 ha[addr].count = i;
71 }
72 }
73
74 /**
75 * 创建哈希表
76 * 先将哈希表中各关键字清空,使其地址为开放的,然后调用插入算法将给定的关键字序列依次插入。
77 */
78 public void createHashTable(HashTable[] ha, int[] list, int p, int size) {
79 int i = 0;
80
81 // 将哈希表中的所有关键字清空
82 for (i = 0; i < ha.length; i++) {
83 ha[i].key = NULLKEY;
84 ha[i].count = 0;
85 }
86
87 // 将关键字序列依次插入哈希表中
88 for (i = 0; i < list.length; i++) {
89 this.insertHashTable(ha, p, size, list[i]);
90 }
91 }
92
93 /**
94 * 输出哈希表
95 */
96 public void displayHashTable(HashTable[] ha) {
97 int i = 0;
98 System.out.format("pos:\t", "pos");
99 for (i = 0; i < ha.length; i++) {
100 System.out.format("%4d", i);
101 }
102 System.out.println();
103
104 System.out.format("key:\t");
105 for (i = 0; i < ha.length; i++) {
106 if (ha[i].key != NULLKEY) {
107 System.out.format("%4d", ha[i].key);
108 } else {
109 System.out.format(" ");
110 }
111 }
112 System.out.println();
113
114 System.out.format("count:\t");
115 for (i = 0; i < ha.length; i++) {
116 if (0 != ha[i].count) {
117 System.out.format("%4d", ha[i].count);
118 } else {
119 System.out.format(" ");
120 }
121 }
122 System.out.println();
123 }
124
125 public static void main(String[] args) {
126 int[] list = { 3, 112, 245, 27, 44, 19, 76, 29, 90 };
127 HashTable[] ha = new HashTable[MAXSIZE];
128 for (int i = 0; i < ha.length; i++) {
129 ha[i] = new HashTable();
130 }
131
132 HashSearch search = new HashSearch();
133 search.createHashTable(ha, list, 19, MAXSIZE);
134 search.displayHashTable(ha);
135
136 }
137
138 }
哈希查找之JAVA实现
查找三 哈希表的查找
标签:
原文地址:http://www.cnblogs.com/jingmoxukong/p/4332252.html