哈希表的基本操作--拉链法

HashTableBucket.h

#pragma once

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
//typedef char* HTBKeyType;
//typedef char* HTBValueType;

//typedef char* HTBKeyType;
//typedef int HTBValueType;

typedef int HTBKeyType;
typedef int HTBValueType;

typedef struct HashNode
{
	struct HashNode* _next;
	HTBKeyType _key;
	HTBValueType _value;
}HashNode;

typedef struct HashTableBucket
{
	HashNode** _tables;
	size_t _size;
	size_t _len;
}HTB;

//初始化
void HTBInit(HTB* htb, size_t len);
//销毁
void HTBDestory(HTB* htb);
//插入
int HTBInsert(HTB* htb, HTBKeyType key, HTBValueType value);
//删除
int HTBRemove(HTB* htb, HTBKeyType key);
//查找
HashNode* HTBFind(HTB* htb, HTBKeyType key);
//大小
int HTBSize(HTB* htb);
//判断是否为空
int HTBEmpty(HTB* htb);

void TestHashTableBucket();

HashTableBucket.c

#include "HashTableBucket.h"



static size_t GetNextPrime(size_t value)//质数表,给增容提供最佳选择容量大小
{
	int i = 0;
	//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 (; i < 28; ++i)
	{
		if (_PrimeList[i] > value)
		{
			return _PrimeList[i];
		}
	}

	return _PrimeList[27];
}
//初始化
void HTBInit(HTB* htb, size_t len)
{
	assert(htb);
	根据素数表获取哈希表的长度
	htb->_len = GetNextPrime(len);
	htb->_size = 0;
	//为哈希表开辟空间
	htb->_tables = (HashNode**)malloc(sizeof(HashNode*)*htb->_len);
	//将哈希表中的所有指针初始化为空
	memset(htb->_tables, 0, sizeof(HashNode*)*htb->_len);
}
//销毁
void HTBDestory(HTB* htb)
{
	assert(htb);
	//释放哈希表上每一条链上的节点
	for (size_t i = 0; i < htb->_len; i++)
	{
		HashNode* cur = htb->_tables[i];
		while (cur)
		{
			HashNode* next = cur->_next;
			free(cur);
			cur = next;
		}
		htb->_tables[i] = NULL;
	}
	//释放哈希表
	free(htb->_tables);
	htb->_tables = NULL;
	htb->_size = 0;
	htb->_len = 0;
}
int HTBHashFunc(HTBKeyType key, int len)
{
	//return StrHash(key) % len;
	return key % len;
}
//检查负载因子是否达到1,如果达到1,则需要扩容
void HTBCheckCapacity(HTB* htb)
{
	assert(htb);
	if (htb->_size == htb->_len)
	{
		HTB newhtb;
		newhtb._len = GetNextPrime(htb->_len);
		HTBInit(&newhtb, newhtb._len);
		for (size_t i = 0; i < htb->_len; ++i)
		{
			HashNode* cur = htb->_tables[i];
			while (cur)
			{
				HashNode* next = cur->_next;
				size_t index = HTBHashFunc(cur->_key, newhtb._len);

				cur->_next = newhtb._tables[index];
				newhtb._tables[index] = cur;

				cur = next;
			}

			htb->_tables[i] = NULL;
		}
		//释放旧的哈希表
		HTBDestory(htb);
		htb->_tables = newhtb._tables;
		htb->_size = newhtb._size;
		htb->_len = newhtb._len;
	}
}

//创建节点
HashNode* BuyHashNode(HTBKeyType key, HTBValueType value)
{
	HashNode* node = malloc(sizeof(HashNode));
	node->_key = key;
	node->_value = value;
	node->_next = NULL;

	return node;
}

//插入一个元素
int HTBInsert(HTB* htb, HTBKeyType key, HTBValueType value)
{
	assert(htb);
	HashNode* cur, *newNode;
	HTBCheckCapacity(htb);
	int index = HTBHashFunc(key, htb->_len);
	cur = htb->_tables[index];
	while (cur)
	{
		if (cur->_key == key)
			return -1;

		cur = cur->_next;
	}

	newNode = BuyHashNode(key, value);
	newNode->_next = htb->_tables[index];
	htb->_tables[index] = newNode;
	htb->_size++;

	return 0;
}
//删除一个元素
int HTBRemove(HTB* htb, HTBKeyType key)
{
	assert(htb);

	HashNode* cur = NULL, *prev = NULL;

	int index = HTBHashFunc(key, htb->_len);
	cur = htb->_tables[index];
	while (cur)
	{
		if (cur->_key == key)
		{
			if (prev == NULL)
				htb->_tables[index] = cur->_next;
			else
				prev->_next = cur->_next;

			free(cur);
			--htb->_size;
			return 0;
		}

		prev = cur;
		cur = cur->_next;
	}

	return -1;

}
//在哈希表中查找一个元素
HashNode* HTBFind(HTB* htb, HTBKeyType key)
{
	assert(htb);
	HashNode* cur;
	int index = HTBHashFunc(key, htb->_len);
	cur = htb->_tables[index];
	while (cur)
	{
		if (cur->_key == key)
		{
			return cur;
		}

		cur = cur->_next;
	}

	return NULL;
}

int HTBSize(HTB* htb)
{
	assert(htb);
	return htb->_size == 0 ? 0 : 1;
}
int HTBEmpty(HTB* htb)
{
	assert(htb);
	return htb->_size == htb->_len ? 0 : 1;
}
//打印哈希表
void HTBPrint(HTB* htb)
{
	assert(htb);
	for (size_t i = 0; i < htb->_len; ++i)
	{
		int count = 0;
		HashNode* cur = htb->_tables[i];
		printf("桶[%d]->", i);

		while (cur)
		{
			printf("[%s:%s]->", cur->_key, cur->_value);
			++count;
			cur = cur->_next;
		}
		printf("%d\n", count);
	}

	printf("\n");
}
void TestHashTableBucket()
{
	HTB htb;
	HTBInit(&htb, 10);

	HTBInsert(&htb, "insert", "插入");
	HTBInsert(&htb, "delete", "删除");
	HTBInsert(&htb, "hash", "哈希");
	HTBInsert(&htb, "test", "测试");

	HTBPrint(&htb);
	HTBRemove(&htb, "test");
	HTBPrint(&htb);

}

int main()
{
	TestHashTableBucket();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值