数据结构与算法学习之路:简单的哈希表实现(链地址法解决冲突)

一、哈希表是什么?

  散列表(Hash table,也叫哈希表),是根据关键码值(Key-Value)而直接进行访问的数据结构。

 

    也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。


    给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数所以我们可以知道:


    哈希表的优点在于,查找效率高O(1),但是耗费空间。


    思想我个人认为是空间换取时间……


二、哈希函数的构造方法:

    1、直接定址法:取关键字或关键字的某个线性函数值为哈希地址。

    2、数字分析法:假设关键字是以r为基的数(如:以10为基的十进制数),并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。

    3、平方取中法:取关键字平方后的中间几位为哈希地址。

    4、斐波那契(Fibonacci)散列法

    5、折叠法:将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址,这方法称为折叠法。

    6、除留余数法:取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。即H(key)=key MOD p,(p<=m),这是一种最简单,也是最常用的构造哈希函数的方法。它不仅可以对关键字直接取模(MOD),也可在折叠、平方取中等运算之后取模。

    7、随机数法:选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H(key)=random(key),其中random为随机函数。通常,当关键字长度不等时采用此法构造哈希函数较切当。


三、哈希表的缺陷:


哈希表总会不可避免的产生冲突(尤其是在数据量大的时候),这个时候就需要一个方法来解决冲突,以下是几种常用的解决冲突的方法:

1、开放定址法

2、再哈希法

3、链地址法

4、建立一个公共溢出区


四、代码实现:


笔者这次发的代码主要是把一堆数字建成哈希表,然后查找数字。这里使用了链地址法去解决冲突,在这里顺便解释一下链地址法吧。


假设经过哈希函数处理,元素A、B、C、D在哈希表中的位置是一样的,也就是说:A、B、C、D四个元素发生了冲突。这个时候呢,我们不妨让先来的A放在哈希表里,然后让A(一个结构体元素,里边存着有指针)指向B,B指向C,C指向D。后面还有冲突元素过来也是这样连上去。换句话说:我们是用一个链表把这些相似的元素存了起来。


#include 
#include 

#define TRUE 1
#define FALSE 0

#define HASH_SIZE 12

typedef struct Hash_Table{
	int data;
	Hash_Table* next;
}*Hash_TablePtr;

int Hash(int key);
int Search(Hash_TablePtr hash, int key);

int main(){
	Hash_Table hash[HASH_SIZE];

	int i, search;
	int temp[HASH_SIZE] = { 9, 31, 26, 19, 1, 13, 2, 11, 27, 16, 5, 21 };

	for (i = 0; i < HASH_SIZE; i++){
		hash[i].data = -1;
		hash[i].next = NULL;
	}

	for (i = 0; i < HASH_SIZE; i++){
		int x, y;

		x = temp[i];
		y = Hash(x);

		Hash_TablePtr pre;

		if (hash[y].data == -1)
			hash[y].data = x;
		else{
			Hash_TablePtr chain_adress = (Hash_TablePtr)malloc(sizeof(Hash_Table));
			chain_adress->data = x;
			chain_adress->next = NULL;

			pre = &hash[y];

			while (pre->next != NULL)
				pre = pre->next;

			pre->next = chain_adress;
		}
	}

	printf("请输入要找的数:");
	scanf("%d", &search);
	if (Search(hash, search))
		printf("找到了\n");
	else
		printf("没找到\n");
}

int Hash(int key){
	return key % 11;
}

int Search(Hash_TablePtr hash, int key){
	int adress = Hash(key);

	if (hash[adress].data == -1)
		return FALSE;
	else if (hash[adress].data == key)
		return TRUE;
	else{
		Hash_TablePtr temp = &hash[adress];
		while (temp != NULL){
			temp = temp->next;

			if (temp == NULL)
				return FALSE;
			else if (temp->data == key)
				return TRUE;
		}

		return FALSE;
	}
}


你可能感兴趣的:(数据结构与算法)