这是我在初步接触后,写的关于哈希表的插入、查找、删除、遍历、更改几个基本操作的java代码思路。
哈希表是种数据结构,它可以提供快速的插入操作和查找操作,其余优缺点不加以讨论。但一般的操作必须是根据key值进行。所谓的key值,是唯一标识数据信息的特殊数据,不可重复,如学生的学号,人民的身份证号码。在计算机中,key值可是内存地址,亦可自我设定。下面是关于哈希表的其中一个方式。
在数据就是key值的情况下,将要存放的数据除以某个整数,所得的余数作为放置位置的依据。如上图,设一个哈希表数组中有13个位置,取除数为13,由取余数法知:01数据放置在1号位置,55放置在3号,同时,有时余数可能重复,如14,余数为1,我也将其放置在1号位置,以此类推,可将整数放入一个与其本身有所联系的位置。这就是一种哈希表的简单介绍。
在用java代码实现时,思路是:
key值自我设定,由0开始递增,
在同一个位置只可放置最多三个数据,多的建立下一个数组(一组位置的设定)。
数组间的元素联系采用单向链表,同一个位置的数据亦采用单向链表的方法
先进行一些设置:
public class HashLinkArray {
private int hashLALength = 10;//链表数组的长度
private int hashLALLength = 3;//同一个位置最多可放置的数据个数
}
因为链表数组是由结点相互联系,它在不同的数组指示我们按一定的顺序进行查找。要先写一个结点类:
public class HashLinkNode {
public Object[] hlla_Next;//结点数组
public HashLinkNode parent;//父结点
public HashLinkNode child;//子结点
/**
* 设置结点数组
* @param hlla_c 结点数组
*/
public void setHashLinkNode_Array(Object[] hlla_c){
this.hlla_Next=hlla_c;
}
/**
* 得到数组
* @return
*/
public Object[] getHashLinkNode_Array(){
return hlla_Next;
}
}
在用此个结点类中,我们可以开始建立链表数组
public void setHashLinkArray() {
HashLinkNode hln = null;
//第一次建立哈希数组
if (hashLinkArrayNum == 0) {
//哈希数组
Object[] hla = new Object[hashLALength];
hln = new HashLinkNode();
hln.parent = hln;
first_Node = hln;
//设置数组
hln.setHashLinkNode_Array(hla);
hashLinkArrayNum++;
} else {///非第一次建立/
hln = first_Node;
while (true) {
if (hln.child != null) {
hln = hln.child;
} else {
HashLinkNode newNode = new HashLinkNode();
newNode.parent = hln;
hln.child = newNode;
Object[] hla = new Object[hashLALength];
newNode.setHashLinkNode_Array(hla);
hashLinkArrayNum++;
break;
}
}
}
}
此前说过,在同一个位置,可最多放置三个数据,这三个数据之间的关系也用单向链表进行表示,再写一个结点类:
public class HashElemNode {
HashElemNode p;//父结点
HashElemNode c;//子结点
int key;//key值
Object newelem;//数据信息
/**
* 得到数据信息
* @return
*/
public Object getElem(){
return newelem;
}
}
增加数据时,首先要计算余数,然后遍历,从第一个数组开始,先得到它的位置,再判断能否放在这个位置,如果不能,再尝试下一个数组,如果没有下一个数组,则建立一个。
/**
* 增加哈希表中的元素
*
* @param newelem
* 新的元素
*/
//key值自定义
public static int key = 0;
public void addHashelem(Object newelem) {
//取余
int lo_key = key % hashLALength;
//首先建立第一个数组
if (hashLinkArrayNum == 0) {
setHashLinkArray();
}
//数据元素的结点
HashElemNode newelemnode = new HashElemNode();
newelemnode.key = key;
newelemnode.newelem = newelem;
//从第一个数组开始遍历
HashLinkNode node = first_Node;
while (true) {
//若此位置没有元素
if (node.getHashLinkNode_Array()[lo_key] == null) {
key++;
node.getHashLinkNode_Array()[lo_key] = newelemnode;
newelemnode.p = newelemnode;
System.out.println("第n组" + hashLinkArrayNum + "key0 is"
+ newelemnode.key + "数据:" + newelemnode.newelem);
break;
} else {
HashElemNode elemnode = (HashElemNode) node
.getHashLinkNode_Array()[lo_key];
if (elemnode.c == null) {//只有一个元素
key++;
newelemnode.p = elemnode;
elemnode.c = newelemnode;
System.out.println("第n组" + hashLinkArrayNum + "key1 is"
+ newelemnode.key + "数据:" + newelemnode.newelem);
break;
} else {//只有两个元素
if (elemnode.c.c == null) {
key++;
newelemnode.p = elemnode.c;
elemnode.c.c = newelemnode;
System.out
.println("第n组" + hashLinkArrayNum + "key2 is"
+ newelemnode.key + "数据:"
+ newelemnode.newelem);
break;
} else {
//前面的数组的此位置都满了,建立一个新的数组
if (node.child == null) {
setHashLinkArray();
System.out.println("第n组" + hashLinkArrayNum
+ "======================================");
}
//有三个元素,遍历下一个数组
node = node.child;
}
}
}
}
}
接下来可以进行元素的遍历:
/**
* 遍历哈希表
*/
public int travelHash() {
//从第一个数组开始
HashLinkNode arraynode = first_Node;
int arraynum = 1;//数组个数
int elemnum = 0;//元素个数
while (true) {
for (int i = 0; i < hashLALength; i++) {
//该位置的第一个元素,如果有
if (arraynode.getHashLinkNode_Array()[i] != null) {
HashElemNode elemnode = (HashElemNode) arraynode
.getHashLinkNode_Array()[i];
System.out.println(elemnum + "第" + arraynum + "组" + "key是"
+ elemnode.key + "%后是" + elemnode.key
% hashLALength + "数据是" + elemnode.newelem);
elemnum++;
if (elemnode.c != null) {//第二个
System.out.println(elemnum + "第" + arraynum + "组"
+ "key是" + elemnode.c.key + "%后是"
+ elemnode.c.key % hashLALength + "数据是"
+ elemnode.c.newelem);
elemnum++;
if (elemnode.c.c != null) {//第三个
System.out.println(elemnum + "第" + arraynum + "组"
+ "key是" + elemnode.c.c.key + "%后是"
+ elemnode.c.c.key % hashLALength + "数据是"
+ elemnode.c.c.newelem);
elemnum++;
}
}
}
}
if (arraynode.child != null) {
//遍历下一个数组
arraynode = arraynode.child;
} else {
//退出循环
break;
}
}
return elemnum;
}
通过遍历,我们已经可以找到方法,查到表中每一个元素,删除操作就是把父子结点的更替,或是去掉,只要在遍历的条件上增加key值的判断。查找也是,只需返回这个数据的结点,便可得到数据,不再介绍。