【数据结构】哈希桶

1.使用哈希桶处理整型数据

1)HashTableBucket.h

#ifndef  _HASHTABLEBUCKET_H__
#define _HASHTABLEBUCKET_H__





#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include <string.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];
}

static size_t StrHash(const char* str)
{
	size_t hash = 0;
	size_t seed = 131;
	while (*str)
	{
		/*hash += *str;*/
		hash = hash*seed + *str;
		++str;
	}

	/*printf("%u\n", hash);*/

	return hash;
}


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);



#endif

2)HashTableBucket.c


#include "HashTableBucket.h"

void HTBInit(HTB* htb, size_t len)
{
	assert(htb);
	//根据素数表获取哈希表的长度
	int HTB_len = GetNextPrime(len);
	//为哈希桶开辟空间(
	HashNode** table = (HashNode**)malloc(sizeof(HashNode*)*(HTB_len));
	if (table == NULL)
	{
		perror("use malloc of create");
		exit(EXIT_FAILURE);
	}
	htb->_tables = table;
	htb->_size = 0;
	htb->_len = HTB_len;
	//将哈希表中的所有指针初始化为空,否则会对野指针操作
	memset(htb->_tables,0, sizeof(HashNode*)*(htb->_len));
}

		

void HTBDestory(HTB* htb)
{
	unsigned int i = 0;
	assert(htb);

	for (; 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;
}



//哈希函数,计算哈希地址(整数)
static int HTBHashFunc(HTBKeyType key, int len)
{
  return key%len;
}


HashNode* BuyHashNode(HTBKeyType key, HTBValueType value)
{
	HashNode* node = malloc(sizeof(HashNode));
	if (node != NULL)
	{
		node->_key = key;
		node->_value = value;
		node->_next = NULL;
	}
	return node;
}

void HTBCheckCapacity(HTB* htb)
{
	assert(htb);
	if (htb->_size == htb->_len)
	{
		unsigned int i;
		HTB newhtb;
		newhtb._len = GetNextPrime(htb->_len);
		HTBInit(&newhtb, newhtb._len);
		if (htb->_size == htb->_len)
		{
			for (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;
	}
}

int HTBInsert(HTB* htb, HTBKeyType key, HTBValueType value)
{
	size_t index;
	HashNode* cur, *newNode;

	HTBCheckCapacity(htb);

	assert(htb);
	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)
{
	size_t index;
	HashNode* cur = NULL, *prev = NULL;
	assert(htb);

	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)
{
	size_t index;
	HashNode* cur;
	assert(htb);

	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)
{
	unsigned int i = 0;
	assert(htb);
	for (i=0; i < htb->_len; ++i)
	{
		int count = 0;
		
		printf("table[%d]->", i);
		HashNode* cur = htb->_tables[i];
		while (cur)
		{
			printf("([key:%d}:{value:%d])->", cur->_key, cur->_value);
			count++;
			cur = cur->_next;
		}

		
		printf("(count=%d)->over\n", count);

	}


}



3)Test.c

#include "HashTableBucket.h"




void HTBtest1()
{
	HTB htb;
	HTBInit(&htb, 10);
	HTBInsert(&htb, 6, 0);
	HTBInsert(&htb, 11, 0);
	HTBPrint(&htb);
}



int  main()
{
	HTBtest1();
	system("pause");
	return 0;
}

2.使用哈希桶处理字符数据

1)HashTableBucket.h

#ifndef  _HASHTABLEBUCKET_H__
#define _HASHTABLEBUCKET_H__





#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include <string.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];
}

static size_t StrHash(const char* str)
{
	size_t hash = 0;
	size_t seed = 131;
	while (*str)
	{
		/*hash += *str;*/
		hash = hash*seed + *str;
		++str;
	}

	/*printf("%u\n", hash);*/

	return hash;
}

//
typedef char* HTBKeyType;
typedef char* 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);



#endif

2)HashTableBucket.c


#include "HashTableBucket.h"

void HTBInit(HTB* htb, size_t len)
{
	assert(htb);
	//根据素数表获取哈希表的长度
	int HTB_len = GetNextPrime(len);
	//为哈希桶开辟空间(
	HashNode** table = (HashNode**)malloc(sizeof(HashNode*)*(HTB_len));
	if (table == NULL)
	{
		perror("use malloc of create");
		exit(EXIT_FAILURE);
	}
	htb->_tables = table;
	htb->_size = 0;
	htb->_len = HTB_len;
	//将哈希表中的所有指针初始化为空,否则会对野指针操作
	memset(htb->_tables,0, sizeof(HashNode*)*(htb->_len));
}

		

void HTBDestory(HTB* htb)
{
	unsigned int i = 0;
	assert(htb);

	for (; 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;
}

size_t HTBHashFunc(HTBKeyType key, size_t len)
{
	int count = 0;
	int i = 0;
	while (*(key + i) != '\0')
	{
		count += *(key + i);
		++i;
	}
	return count%len;
	
}

HashNode* BuyHashNode(HTBKeyType key, HTBValueType value)
{
	HashNode* node = malloc(sizeof(HashNode));
	if (node != NULL)
	{
		node->_key = key;
		node->_value = value;
		node->_next = NULL;
	}
	return node;
}

void HTBCheckCapacity(HTB* htb)
{
	assert(htb);
	if (htb->_size == htb->_len)
	{
		unsigned int i;
		HTB newhtb;
		newhtb._len = GetNextPrime(htb->_len);
		HTBInit(&newhtb, newhtb._len);
		if (htb->_size == htb->_len)
		{
			for (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;
	}
}

int HTBInsert(HTB* htb, HTBKeyType key, HTBValueType value)
{
	size_t index;
	HashNode* cur, *newNode;

	HTBCheckCapacity(htb);

	assert(htb);
	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)
{
	size_t index;
	HashNode* cur = NULL, *prev = NULL;
	assert(htb);

	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)
{
	size_t index;
	HashNode* cur;
	assert(htb);

	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)
{
	unsigned int i = 0;
	assert(htb);
	for (i=0; i < htb->_len; ++i)
	{
		int count = 0;
		
		printf("table[%d]->", i);
		HashNode* cur = htb->_tables[i];
		while (cur)
		{
			printf("([key:%s}:{value:%s])->", cur->_key, cur->_value);
			count++;
			cur = cur->_next;
		}

		
		printf("(count=%d)->over\n", count);

	}


}



3)Test.c

#include "HashTableBucket.h"


void HTBtest2()
{
	HTB htb;
	HTBInit(&htb, 10);

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

	HTBPrint(&htb);
}


int  main()
{
	HTBtest2();
	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值