哈希表——线性探测

/**
 * 哈希表是根据关键码值来进行访问的数据结构
 * 也就是说 他通过关键码值映射到表中的一个位置来访问记录,来加快查找的速度,
 * 这个映射叫做散列函数,这个存放记录的数组叫做散列表
 * 1、哈希表可以快速的插入,查找,删除
 * 2、哈希表基于数组实现,一旦确定,不容易维护
 * 3、没有一种简单的方式实现遍历,因此若是需要这个功能,那么需要选择其他的数据结构
 * @author hp
 *
 */

public class DataItem {
  private int iData;
  public DataItem(int i){
	  iData = i;
  }
  public int getkey(){
	  return iData;
  }
}



public class HashTable {
/**
 * 完成哈希存储的查找的功能
 * 开放地址法之线性探测
 * 线性探测就是按照当前的位置冲突,它会按照数组的下标一步步的查找空白的单元
 * 缺点:当哈希表越来越满的时候,聚集会变的越来越严重,这会导致产生非常长的探测长度
 * 意味着存储序列的最会单元会非常耗时
 */
	private DataItem [] hashArray; 
	private int arraySize;
	private DataItem nonItem;
	//hashtabe 的初始化
	public HashTable(int size){
	  arraySize = size;
	  hashArray = new DataItem[arraySize];
	  nonItem = new DataItem(-1);
	}
	//用来遍历整个哈希表
	public void displayTable(){
		System.out.println("table: ");
		for(int i=0;i<hashArray.length;i++){
			if(hashArray[i]!=null){
				System.out.println(hashArray[i].getkey()+" ");
			}else{
				System.out.println("** ");
			}
		}
	}
	//hash映射函数
	public int hashFun(int key){
		return key%arraySize;
	}
	//哈希插入
	public void insert(DataItem item){
		int key = item.getkey();  //将存储对象的数据的键值传递给映射函数,得到数字的下标
		int hashVal= hashFun(key);
		
		while(hashArray[hashVal] !=null && hashArray[hashVal].getkey() !=-1){ //判断得到的位置上有没有数据,如果有数据就执行此循环
			++hashVal;
			hashVal %=arraySize;
		}
		hashArray[hashVal] = item;
	}
	//哈希删除
	public DataItem delete(int key){
		int hashVal = hashFun(key);
		while(hashArray[hashVal] != null ){ //如果key的位置有数据
			if(hashArray[hashVal].getkey() == key){
				DataItem temp  = hashArray[hashVal]; //取走数据以后将这个位置上的数据设置为空
				hashArray[hashVal] = nonItem;
				return temp;  //返回key位置的数据
			}
			++hashVal;    //如果这个位置上数据不是要找的数据,就向前遍历这个数据
			hashVal%=arraySize;
		}
		return null;
	}
	
	//哈希查找
	public DataItem find(int key){
		int hashVal = hashFun(key);
		while(hashArray[hashVal]!=null){
			if(hashArray[hashVal].getkey() == key){
				return hashArray[hashVal];
			}
			++hashVal;
			hashVal%=arraySize;
		}
		return null;
	}
	//测试
	public static void main(String[] args) {
		HashTable hs = new HashTable(5);
		DataItem i1 = new DataItem(2);
		hs.insert(i1);
		DataItem i2 = new DataItem(1);
		hs.insert(i2);
		DataItem i3 = new DataItem(4);
		hs.insert(i3);
		DataItem i4 = new DataItem(3);
		hs.insert(i4);
		hs.displayTable();
		System.out.println(hs.delete(0));
		
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的C语言实现哈希表的例子,其中包括了电话号码和用户名两个关键字的哈希表,并采用了线性探测再散列的方法解决冲突。 ```c #include <stdio.h> #include <string.h> #define MAX_SIZE 100 // 哈希表的最大大小 #define EMPTY -1 // 哈希表空位标志 typedef struct { char phone[12]; // 电话号码 char name[20]; // 用户名 char address[30]; // 地址 } Record; typedef struct { Record data; // 数据项 int key; // 哈希表关键字 } HashNode; void init(HashNode hash_table[], int size) { int i; for (i = 0; i < size; i++) { hash_table[i].key = EMPTY; } } int hash(char* key, int size) { int hash_val = 0; while (*key) { hash_val = (hash_val << 5) + *key++; } return hash_val % size; } int find(char* key, HashNode hash_table[], int size) { int hash_val = hash(key, size); while (hash_table[hash_val].key != EMPTY && strcmp(hash_table[hash_val].data.phone, key) != 0) { hash_val = (hash_val + 1) % size; } return hash_val; } void insert(Record data, HashNode hash_table[], int size) { int hash_val = find(data.phone, hash_table, size); hash_table[hash_val].data = data; hash_table[hash_val].key = hash(data.phone, size); } Record* search_by_phone(char* phone, HashNode hash_table[], int size) { int hash_val = find(phone, hash_table, size); if (hash_table[hash_val].key != EMPTY) { return &(hash_table[hash_val].data); } return NULL; } Record* search_by_name(char* name, HashNode hash_table[], int size) { int i; for (i = 0; i < size; i++) { if (hash_table[i].key != EMPTY && strcmp(hash_table[i].data.name, name) == 0) { return &(hash_table[i].data); } } return NULL; } int main() { HashNode phone_table[MAX_SIZE], name_table[MAX_SIZE]; Record record; int i, size; char phone[12], name[20]; printf("Enter the size of hash table: "); scanf("%d", &size); init(phone_table, size); init(name_table, size); printf("\nEnter the phone number, name and address of the person:\n"); for (i = 0; i < size; i++) { printf("Record %d:\n", i + 1); scanf("%s %s %s", record.phone, record.name, record.address); insert(record, phone_table, size); insert(record, name_table, size); } printf("\nEnter the phone number to search: "); scanf("%s", phone); Record* r = search_by_phone(phone, phone_table, size); if (r != NULL) { printf("Phone: %s\nName: %s\nAddress: %s\n", r->phone, r->name, r->address); } else { printf("Record not found.\n"); } printf("\nEnter the name to search: "); scanf("%s", name); r = search_by_name(name, name_table, size); if (r != NULL) { printf("Phone: %s\nName: %s\nAddress: %s\n", r->phone, r->name, r->address); } else { printf("Record not found.\n"); } return 0; } ``` 在这个例子中,我们首先定义了一个 `Record` 结构体来表示每个记录,其中包括了电话号码、用户名和地址三个数据项。然后我们定义了一个 `HashNode` 结构体来表示哈希表中的节点,其中包括了一个 `data` 成员来存储记录数据,以及一个 `key` 成员来存储哈希表关键字。 在 `init` 函数中,我们将哈希表中的每个节点的 `key` 成员初始化为 `EMPTY`,表示该节点为空。 在 `hash` 函数中,我们使用了一种简单的哈希函数,将字符串转换为整数并取模得到哈希值。 在 `find` 函数中,我们使用线性探测的方法解决哈希冲突,如果当前节点的 `key` 成员不为 `EMPTY` 且节点中的电话号码与要查找的电话号码不同,则继续搜索下一个节点,直到找到一个空节点或者关键字与要查找的电话号码相同的节点为止。 在 `insert` 函数中,我们通过调用 `find` 函数找到一个空节点或者与要插入的记录关键字相同的节点,并将该节点的 `data` 和 `key` 成员更新为要插入的记录数据和关键字。 在 `search_by_phone` 函数中,我们通过调用 `find` 函数找到与给定电话号码相同的节点,并返回该节点中的记录数据。 在 `search_by_name` 函数中,我们遍历哈希表中的所有节点,找到用户名与给定名字相同的节点,并返回该节点中的记录数据。 最后,在 `main` 函数中,我们首先从键盘输入每个记录的电话号码、用户名和地址,并将其插入到电话号码和用户名两个哈希表中。然后,我们分别通过调用 `search_by_phone` 和 `search_by_name` 函数来查找给定电话号码和用户名对应的记录,并输出该记录的电话号码、用户名和地址。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值