散列表:这是一个比较有用的数据结构,比较详细的用法还需要参考具体的书籍
这里只是简单的介绍一下,了解一下其比较强大的功能。肯定还有很多比较使用改进方法,需要多学习才行。
在进行查找的过程中,无论是线性查找还是二分查找,其对都是时间的函数一个是O(n),一个是O(log2n);
而散列表进行查找的时候,时间函数是O(1),其对时间来说是个常数,跟数据的规模没有关系。
其主要通过直接索引来实现的(我是这样理解的)
比如有31个在0-999中的数,我们要查询这31个数中的一个数。
可以通过数组存储这31个数,然后顺序搜索,或者排序,二分查找。
随着数据规模的曾加,时间也在增加。
散列表则不同,散列表是申请一个1000大小的数组,然后用数组的下表表示所存储的数字
table[1000]。比如里面有一个数330,则有table[330] = 330。这31个数都是这样存储,但是1000大小的数组存储31个数的话是没办法填满的。这个可以根据自己的需要自行填充。这样在查询330的时候,直接就是判断table[330]是不是330。一次查询就可以得出结果,而且不论数据规模有多大。但是仔细想就会发现,有不好的地方,就是对存储空间太浪费了,1000中只用了31,这中浪费实在是奢侈。
这个时候有一种方法可以解决,就是只申请31个存储空间来存储这31个数,然后每个数用num = number%31,table[num] = num来存储。这样避免了空间的浪费。但是会有冲突产生。比如number = num+31*k的数按照上面的式子计算出来都是num。所以这时候都用table[num]来存储就会产生冲突。
这时候有一种冲突处理策略就是,在冲突发生的时候,在num点向下进行循环扫描空位置,然后把这个数字填充过去。这个时候实际上是降低了时间效率来获取空间效率。
当进行一个数查询的时候,实际是上先用table[num]进行判断此时存不存在,或这个位置是不是所要查询的数。如果不是,就从这个位置向下进行循环线性搜索。
这个算法的效率在前两步体现出来,可以快速判断这个数存不存在。