MyHash总结

[size=medium] 前段时间因为自己的事情比较多,技术这块有些懈怠了,很多东西学得不扎实,常常产生眼高手低的情况。讲到Hash部分的时候,自认为听过课之后比较容易理解Hash的原理,于是放松了代码的练习,先进行一下自我检讨。
  Hash这部分原理其实不难理解,它也是数据结构的一种。数据结构最基础的有四种,分别是树、队列、Map、图,延伸之后产生数组、链表等对基础数据结构的应用。而Hash即是基础的数据结构组合而成的较为复杂的数据结构。
  Hash主要用到的数据结构是数组和链表,数组部分主要通过下标来查找,是连续的,而链表是指向性的,可以指向下一个结点,是非连续的。我对链表的掌握还是比较生疏,导致之后的应用出现一些问题。
  Hash结构是怎么来的呢?就像门上的珠帘一样,Hash是一个挂链式的结构,最上层是数组的分布,向Hash中添加元素的时候,总是会产生冲突的。我用到的将元素添加到数组方法还是value%size,即根据元素值除以数组大小的余数来将元素添加到与该余数相同下标的数组元素里。而这样就不可避免地会产生冲突,一个数组只能放一个数值,怎么办呢?这时我们就将余数相同的元素像链子一样一个一个地挂在数组元素的下方,这样一串一串地挂下来形成一个珠帘状的结构。
  实际写代码的时候,Hash函数里有四个基础的方法,也即函数要实现的效果:增加、删除、查找、修改。为了实现这四个目的,延伸出一些方法和属性,首先来说一下用到的属性:
  Size——Hash结构中处在珠帘顶端的数组容量
  Length——已存入的元素个数
  Local_factory——阀值,这里的阀值是一个临界点,当元素个数与数组容量的比值大于我们设置的阀值时,Hash结构就会进行重新散列。
  在主要的MyHash类中用到以下方法:
  1 构造方法,创建一个MyHash结构,主要是设置MyHash中数组的初始大小。
  2 增加:需要计算出该元素应放入的数组中的下标位置,即value%size,判断数组中该位置是否已经放入元素,如果该位置为空,就直接将要添加的元素放进去;如果该位置已有元素,就进行判断,该位置已存在的元素之后是否有元素,直到判断到nextElement为空的元素的时候,把要添加的元素挂在这个元素的后面,也就是像排队一样依次排下去。最后要进行阀值的判断,就是说将已存入的元素个数与Hash结构的数组容量进行比较,如果大于阀值则调用重散列方法。
  3 重散列:在该Hash结构中放入的数据越来越多,就会使得之后的查找、删除越来越麻烦,效率越来越低,因此我们需要把数组的size扩大,将Hash结构进行重新散列,也就是说把这些数据放入一个全新的Hash结构中,而这个新的Hash结构的数组容量将比旧Hash结构的数组容量要大,这样就可以使得查找、删除效率得到提高。当重散列方法被调用的时候,建立一个新数组,容量是原数组容量的两倍,然后找出原Hash结构中的各个元素并将它们添加到新的Hash结构中。
  4 删除:在Hash结构中进行循环查找,找到需要删除的元素,将该元素之后的元素挂链上方移动一位,把该元素删除。如果该元素之后未挂其他元素,直接把该元素的位置设置为空。
  5 查找:在Hash结构中进行循环,首先查找数组中每一个下标的位置里所储存的元素,如果该下标位置有元素,就在该元素后面继续进行查找,查找该下标的挂链。如果该位置未储存元素,则查找下一位置。直到将所有的元素都查找完毕。
  6 修改:在Hash结构中进行循环查找,找到需要修改的元素,并把该元素的值修改成需要修改的数据。
  另外,我自己写了Element类,是数组中储存的结点元素的类,该类中主要用到了设置本结点、返回本结点、设置下一结点、返回下一结点、设置结点中数据、返回结点中数据六种方法。
  MyHash中难点不在于理解,而在于动手操作。在实际写代码的时候我遇到一些问题,比如说数组越界、空指针等情况,都是思路中没有预料到的,而在删除结点时,也遇到了学习链表结构时候的老问题,即删除时思路被阻塞,总是无法删除到元素本身,而是在查找时用的临时元素,即将Hash结构中的元素赋值到临时元素上以便于循环的元素上进行操作。
  学习是一个不能眼高手低的过程,“想”与“做”是有很大不同的,只有真正“做”过了,才是真正的学到了,而眼高手低会导致一知半解,知其然而不知其所以然。所以在以后的学习中还是应该把重心有所转移,尽量在代码上多下功夫,不能掉以轻心!
  (我电脑不管怎么发都发不上去代码……总是在缓冲中……望见谅。。。)[/size]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,我们可以了解到线性探测法是散列表中的一种解决冲突的方法,但是容易造成元素聚集,导致元素无法均匀存入表中,增加了运算的复杂度。因此,我们可以使用平方探测法来解决这个问题。 以下是Java中平方探测法实现散列表的代码示例: ```java public class MyHash { private DataItem[] hashArray; private int arraySize; private DataItem nonItem; public MyHash(int size) { arraySize = size; hashArray = new DataItem[arraySize]; nonItem = new DataItem(-1); } public void displayTable() { System.out.print("Table: "); for (int j = 0; j < arraySize; j++) { if (hashArray[j] != null) { System.out.print(hashArray[j].getKey() + " "); } else { System.out.print("** "); } } System.out.println(""); } public int hashFunc(int key) { return key % arraySize; } public void insert(DataItem item) { int key = item.getKey(); int hashVal = hashFunc(key); int stepSize = 1; while (hashArray[hashVal] != null && hashArray[hashVal].getKey() != -1) { hashVal += stepSize * stepSize; hashVal %= arraySize; stepSize++; } hashArray[hashVal] = item; } public DataItem delete(int key) { int hashVal = hashFunc(key); int stepSize = 1; while (hashArray[hashVal] != null) { if (hashArray[hashVal].getKey() == key) { DataItem temp = hashArray[hashVal]; hashArray[hashVal] = nonItem; return temp; } hashVal += stepSize * stepSize; hashVal %= arraySize; stepSize++; } return null; } public DataItem find(int key) { int hashVal = hashFunc(key); int stepSize = 1; while (hashArray[hashVal] != null) { if (hashArray[hashVal].getKey() == key) { return hashArray[hashVal]; } hashVal += stepSize * stepSize; hashVal %= arraySize; stepSize++; } return null; } } class DataItem { private int iData; public DataItem(int ii) { iData = ii; } public int getKey() { return iData; } } ``` 以上代码实现了平方探测法的散列表,其中包括插入、删除和查找操作。在插入操作中,我们使用平方探测法来解决冲突,即每次增加的步长为1的平方,直到找到空的位置为止。在删除和查找操作中,我们也使用相同的探测方式来查找对应的元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值