ハッシュ表の基本的な操作--ファスナー法

5309 ワード

HashTableBucett.h
#pragma once

#include 
#include 
#include 
#include 
#include 
//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();
HashTable Buckeet.
#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
", count); } printf("
"); } 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; }