迟到的Hash表

  本来已经躺在床上准备呼呼大睡了,突然想到hash表的博客还没发表,于是大半夜爬了起来发了这篇文章,希望没有扰人清梦就好了。本来一直以为是早就发了的,然后今天晚上躺在床上才忽然意识到还没有发,最近过的有点浑浑噩噩的,悲剧啊。
  这个代码是自己模拟哈希表实现的一个简单的学生统计系统,具体是实现的散列表中的开散列,即用数组保存一组数据,这一组数据中通过链表连结彼此,于是达到增加,查找,替换,删除的功能。
  hash的预映射算法比较简单,即将学生学号的各个位相加,得到的个位数数值即为散列值,因为个位数所以数组大小为10.
private int handdata(Student stu) {
		int num = stu.numb;
		while (num > 9) {//循环运算直到num变为个位数
			num = num / 10000 + num % 10000 / 1000 + num % 1000 / 100 + num
					% 100 / 10 + num % 10;//将各个位的值相加的运算
		}
		return num;
	}

  接下来要设计学生的类,这也是hash表中数组中保存的对象的类。
public class Student {
	public String name="11";
	public int numb=11111;
	public int gride=11;
	public Student before=null;
	public Student next=null;
	
	/**
	 * 重新构造方法以传入数值
	 * @param name
	 * @param numb
	 * @param gride
	 */
	public Student(String name,int numb,int gride){
		this.name=name;
		this.gride=gride;
		this.numb=numb;
	}
	
	//这个构造方法用来实现默认的对象
	public Student(){		
	}
	
	//改变对象下一个和上一下结点的方法
	public void changenext(Student s){
		next=s;
	}
	
	public void changebefore(Student s){
		before=s;
	}
}

  创建hash表和向其中加入元素的方法
  这里要注意的是在加入新对象时记得去掉默认的对象
	/**
	 * 创建hash表的方法
	 * @param stu
	 */
	public void createHash(Student stu) {
		for (int i = 0; i < 10; i++) {
			Student st = new Student();
			hash[i] = st;
		}//首先默认对数组每个下标值对应的加入一个对象
		int hashcode = handdata(stu);//获得散列值
		hash[hashcode] = stu;//加入对象
	}

	/**
	 * 向hash表内加入元素的方法
	 * @param stu
	 */
	public void addHash(Student stu) {
		int hashcode = handdata(stu);
		if (hash[hashcode] == null) {
			hash[hashcode] = stu;
		} else {//如果此散列值对应的不为空,那么去掉默认的对象(如果有),加入新对象
			Student stut = hash[hashcode];
			if (stut.name.equals("11")) {
				hash[hashcode] = stu;
			} else {
				while (stut.next != null) {
					stut = stut.next;
				}
				stut.next = stu;
			}
		}
	}

  查找表中已存在的元素很简单,即将它的学号处理得到散列值然后遍历hash表即可(这里给予的值可以是学生类的对象,也可以是学生的学号,大体上没什么区别)
public Student seekHash(Student stu) {
		int hashcode = handdata(stu);
		Student stu2 = hash[hashcode];
		while (stu2.numb != stu.numb) {//反复查找直到找到对应的对象
			stu2 = stu2.next;
		}
		System.out.println("姓名:" + stu2.name + "\t学号:" + stu2.numb + "\t分数:"
				+ stu2.gride);
		System.out.println("查找完成。");
		return stu2;
	}

  替换表中元素和删除表中元素其实差不多,都是找到这个对象然后改变它父结点和子结点中指针的指向来达到目的的,其中要注意的就是找到的这个结点可能没有父结点或子结点,这时需要分开讨论(由于删除牵涉到2个需要讨论的结点之间的操作,所以比替换略复杂)
/**
	 * 替换hash表元素的方法
	 * 
	 * @param stu1
	 * @param stu2
	 */
	public void changeHash(Student stu1, Student stu2) {
		int hashcode = handdata(stu1);
		Student stu = seekHash(stu1);
		if (stu.before != null) {//分before和next讨论
			Student stu3 = stu.before;
			stu3.next = stu2;
			stu2.before = stu3;
		} else {
			hash[hashcode] = stu2;
		}
		if (stu.next != null) {
			Student stu4 = stu.next;
			stu4.before = stu2;
			stu2.next = stu4;
		}
	}

	/**
	 * 删除hash表元素的方法
	 * 
	 * @param stu
	 */
	public void deleteHash(Student stu) {
		int hashcode = handdata(stu);
		Student stu0 = seekHash(stu);
		if (stu0.before != null && stu0.next != null) {//各种讨论
			Student stu1 = stu0.before;
			Student stu2 = stu0.next;
			stu1.next = stu2;
			stu2.before = stu1;
		} else if(stu0.before == null && stu0.next == null){
			hash[hashcode] = new Student();
		}else if(stu0.before == null && stu0.next != null){
			Student stu3=stu0.next;
			stu3.before=null;
		}else if(stu0.before != null && stu0.next == null){
			Student stu4=stu0.before;
			stu4.next=null;
		}
	}

  以上就是我的简单的开散列,下面附上实例结果,分别为创建添加,替换,删除后的遍历结果(查找已在替换和删除中体现)
引用
数组第0个中的元素:
姓名:lihao1 学号:0 分数:87
数组第1个中的元素:
姓名:lihao2 学号:1 分数:86
姓名:lihao3 学号:1 分数:85
数组第2个中的元素:
姓名:lihao4 学号:2 分数:84
数组第3个中的元素:
姓名:11 学号:11111 分数:11
数组第4个中的元素:
姓名:11 学号:11111 分数:11
数组第5个中的元素:
姓名:11 学号:11111 分数:11
数组第6个中的元素:
姓名:11 学号:11111 分数:11
数组第7个中的元素:
姓名:11 学号:11111 分数:11
数组第8个中的元素:
姓名:11 学号:11111 分数:11
数组第9个中的元素:
姓名:11 学号:11111 分数:11
一次遍历完成。

姓名:lihao4 学号:2 分数:84
一次查找完成。

数组第0个中的元素:
姓名:lihao1 学号:0 分数:87
数组第1个中的元素:
姓名:lihao2 学号:1 分数:86
姓名:lihao3 学号:1 分数:85
数组第2个中的元素:
姓名:lihao5 学号:2 分数:88
数组第3个中的元素:
姓名:11 学号:11111 分数:11
数组第4个中的元素:
姓名:11 学号:11111 分数:11
数组第5个中的元素:
姓名:11 学号:11111 分数:11
数组第6个中的元素:
姓名:11 学号:11111 分数:11
数组第7个中的元素:
姓名:11 学号:11111 分数:11
数组第8个中的元素:
姓名:11 学号:11111 分数:11
数组第9个中的元素:
姓名:11 学号:11111 分数:11
一次遍历完成。

姓名:lihao5 学号:2 分数:88
一次查找完成。

数组第0个中的元素:
姓名:lihao1 学号:0 分数:87
数组第1个中的元素:
姓名:lihao2 学号:1 分数:86
姓名:lihao3 学号:1 分数:85
数组第2个中的元素:
姓名:11 学号:11111 分数:11
数组第3个中的元素:
姓名:11 学号:11111 分数:11
数组第4个中的元素:
姓名:11 学号:11111 分数:11
数组第5个中的元素:
姓名:11 学号:11111 分数:11
数组第6个中的元素:
姓名:11 学号:11111 分数:11
数组第7个中的元素:
姓名:11 学号:11111 分数:11
数组第8个中的元素:
姓名:11 学号:11111 分数:11
数组第9个中的元素:
姓名:11 学号:11111 分数:11
一次遍历完成。

你可能感兴趣的:(java,hash)