哈希表(链地址法)

一、概念

  • 我前面说过哈希表的开放定址法,现在说说链地址法又称开散列法,在利用毕散列时我们说到有哈希冲突,而开散列法正好避开了哈希冲突,每个下标所在位置就是桶口,每个桶可以看做是一个链表,我们把哈希冲突的元素放在同一个桶中。
  • 虽然我们加设了一个指针,看起来增加了存储开销,但是毕散需要大量的空闲空间以保证搜索速度,而表所占的空间比指针要大得多,所以开散列反而比毕散列要节省存储空间。

二、源代码

1、hashtable.h

#ifndef _HASHTABLE__H_
#define _HASHTABLE__H_

#include "stdio.h"
#include "string.h"
#include "assert.h"
#include "stdlib.h"
#define MAX 10

typedef int KeyType;
typedef int ValueType;
typedef struct HashNode
{
	KeyType _key;
	ValueType _value;
	struct HashNode* _next;
}HashNode, *pHashNode;
typedef struct HashTable
{
	pHashNode *_tables;
	size_t _size;
	size_t _N;
}HashTable, *pHashTable;

pHashNode BuyHashNode(KeyType key, ValueType value);
size_t HashFunc(KeyType key, size_t N);
size_t GetNextPrimeNum(size_t cur);
void HashTableInit(pHashTable ht, size_t x);
int HashTableInsert(pHashTable ht, KeyType key, ValueType value);
pHashNode HashTableFind(pHashTable ht, KeyType key);
int HashTableRemove(pHashTable ht, KeyType key);
void HashTableDestory(pHashTable ht);
void Print(pHashTable ht);

#endif

2、hashtable.c

#include "hashtable.h"
//创建结点
pHashNode BuyHashNode(KeyType key, ValueType value)
{
	pHashNode node = (pHashNode)malloc(sizeof(HashNode));
	node->_key = key;
	node->_value = value;
	node->_next = NULL;
	return node;
}
//确定下标
size_t HashFunc(KeyType key, size_t N)
{
	return key % N;
}
//确定表大小
size_t GetNextPrimeNum(size_t cur)
{
	const int _PrimeSize = 28;
	static const unsigned long _PrimeList[28] = {
		53ul, 97ul, 193ul, 389ul, 769ul, 
		1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 
		49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 
		1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 
		50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 
		1610612741ul, 3221225473ul, 4294967291ul };
	for (int i = 0; i < _PrimeSize; i++)
	{
		if (_PrimeList[i] > cur)
			return _PrimeList[i];
	}
}
//初始化
void HashTableInit(pHashTable ht,size_t x)
{
	assert(ht);
	ht->_tables = (pHashNode*)malloc(sizeof(pHashNode)*x);
	memset(ht->_tables, 0, sizeof(pHashNode)*x);
	ht->_size = 0;
	ht->_N = x;
}
//插入
int HashTableInsert(pHashTable ht, KeyType key, ValueType value)
{
	assert(ht);
	if (ht->_N == ht->_size) //扩容
	{
		HashTable newht;
		HashTableInit(&newht, GetNextPrimeNum(ht->_N));
		for (size_t i = 0; i < ht->_N; i++)
		{
			pHashNode cur = ht->_tables[i];
			size_t count = HashFunc(cur->_key, newht._N);
			while (cur != NULL)
			{
				cur->_value = 0;
				pHashNode next = cur->_next;
				cur->_next = newht._tables[count];
				newht._tables[count] = cur;
				while (cur->_next != NULL)
				{
					cur = cur->_next;
					cur->_value++;
				}
				cur = next;
			}
		}
		free(ht->_tables);
		ht->_tables = newht._tables;
		ht->_N = newht._N;
		ht->_size = newht._size;
	}
	size_t index = HashFunc(key, ht->_N);
	pHashNode node = BuyHashNode(key, value);
	if (HashTableFind(ht, key) != NULL)
		return -1;
	node->_next = ht->_tables[index];
	ht->_tables[index] = node;
	while (node->_next != NULL)
	{
		node = node->_next;
		node->_value++;
	}
	ht->_size++;
	return 0;
}
//查找
pHashNode HashTableFind(pHashTable ht, KeyType key)
{
	assert(ht);
	pHashNode node = ht->_tables[HashFunc(key, ht->_N)];
	while (node != NULL)
	{
		if (node->_key == key)
			return node;
		else
			node = node->_next;
	}
	return NULL;
}
//删除
int HashTableRemove(pHashTable ht, KeyType key)
{
	assert(ht);
	size_t index = HashFunc(key, ht->_N);
	pHashNode cur = ht->_tables[index];
	if (cur->_key == key)
	{
		ht->_tables[index] = ht->_tables[index]->_next;
		free(cur);
		ht->_size--;
		return 0;
	}
	while (cur->_next != NULL)
	{
		if (cur->_next->_key == key)
		{
			pHashNode tmp = cur->_next->_next;
			free(cur->_next);
			cur->_next = tmp;
			ht->_size--;
			return 0;
		}
		else
			cur = cur->_next;
	}
	return -1;
}
//清除
void HashTableDestory(pHashTable ht)
{
	assert(ht);
	for (size_t i = 0; i < ht->_N; i++)
	{
		while (ht->_tables[i])
		{
			pHashNode tmp = ht->_tables[i];
			ht->_tables[i] = ht->_tables[i]->_next;
			free(tmp);
		}
	}
	free(ht->_tables);
	ht->_size = 0;
	ht->_N = 0;
}
//打印
void Print(pHashTable ht)
{
	assert(ht);
	for (size_t i = 0; i < ht->_N; i++)
	{
		pHashNode node = ht->_tables[i];
		printf("table[%d]->", i);
		while (node != NULL)
		{
			printf("%d.%d->", node->_key, node->_value);
			node = node->_next;
		}
		printf("NULL\n");
	}
}

3、写一个测试(test.c)让代码跑起来并加以验证

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值