HashTable.h
#include <assert.h>
#include <stdio.h>
#include <malloc.h>
#include "Common.h"
typedef enum State
{
EMPTY,
EXIST,
DELETE
}State;
typedef int DataType;
typedef size_t(*PDT)(DataType str);
typedef struct Elem
{
DataType _data;
State _state;
}Elem;
typedef enum
{
_IsLine,
_IsNotLine
}IsLine;
typedef struct HashTable
{
Elem * _table;
int _capacity;
int _size;
int _total;
IsLine _Dete;
PDT _setData;
}HashTable;
void HashTableInit(HashTable * ht, int capacity, IsLine _Dete, PDT setData);
void HashTableInsert(HashTable *ht, DataType data);
void HashTableDelete(HashTable *ht, DataType data);
int HashTableFind(HashTable *ht, DataType data);
int HashTableSize(HashTable *ht);
int HashTableEmpty(HashTable *ht);
void HashTableDestory(HashTable* ht);
int HashFunc(HashTable* ht, int data);
int IsLineDete(HashTable* ht, int HashAddr);
int DeteTwo(HashTable * ht, int HashAddr, int i);
void TestHashData();
void TestHashStr();
HashTable.c
#include "HashTable.h"
void HashTableInit(HashTable * ht, int capacity, IsLine Dete, PDT setData)
{
assert(ht);
capacity = GetCapacity(capacity);
ht->_table = (Elem*)malloc(sizeof(Elem)*capacity);
if (NULL == ht->_table)
return;
for (int i = 0; i < capacity; i++)
ht->_table[i]._state = EMPTY;
ht->_capacity = capacity;
ht->_size = 0;
ht->_total = 0;
ht->_setData = setData;
ht->_Dete = Dete;
}
int CheckCapacity(HashTable *ht)
{
if ((ht->_total) * 10 / (ht->_capacity) > 7)
return 1;
return 0;
}
void _Swop(int * newht, int* oldht)
{
int temp = *newht;
*newht = *oldht;
*oldht = temp;
}
void Swop(HashTable* newht, HashTable* oldht)
{
Elem * pTemp = newht->_table;
newht->_table = oldht->_table;
oldht->_table = pTemp;
_Swop(&newht->_capacity, &oldht->_capacity);
_Swop(&newht->_size, &oldht->_size);
_Swop(&newht->_total, &oldht->_total);
}
void BuyCapacity(HashTable * ht)
{
assert(ht);
HashTable newht;
int NewCapacity = GetCapacity(ht->_capacity);
HashTableInit(&newht, NewCapacity, ht->_Dete, ht->_setData);
for (int i = 0; i < ht->_capacity; ++i)
{
if (ht->_table[i]._state == EXIST)
HashTableInsert(&newht, ht->_table[i]._data);
}
Swop(&newht, ht);
HashTableDestory(&newht);
}
void HashTableInsert(HashTable *ht, DataType data)
{
int HashAddr = 0;
int i = 0;
assert(ht);
if (CheckCapacity(ht))
{
BuyCapacity(ht);
}
int Newdata = ht->_setData(data);
HashAddr = HashFunc(ht, Newdata);
while (EMPTY != ht->_table[HashAddr]._state)
{
if (ht->_table[HashAddr]._state == EMPTY)
{
if (ht->_table[HashAddr]._data == data)
return;
}
if (ht->_Dete == _IsLine)
HashAddr = IsLineDete(ht, HashAddr);
else
HashAddr = DeteTwo(ht, HashAddr, ++i);
}
ht->_table[HashAddr]._state = EXIST;
ht->_table[HashAddr]._data = data;
ht->_size++;
ht->_total++;
}
int HashTableFind(HashTable * ht, DataType data)
{
int HashAddr = 0;
int StartAddr = 0;
int i = 0;
assert(ht);
int Newdata = ht->_setData(data);
HashAddr = HashFunc(ht, Newdata);
StartAddr = HashAddr;
while (EMPTY != ht->_table[HashAddr]._state)
{
if (ht->_table[HashAddr]._state == EXIST)
{
if (ht->_table[HashAddr]._data == data)
return HashAddr;
}
if (ht->_Dete == _IsLine)
{
HashAddr = IsLineDete(ht, HashAddr);
if (HashAddr == StartAddr)
return -1;
}
else
HashAddr = DeteTwo(ht, HashAddr, ++i);
}
return -1;
}
void HashTableDelete(HashTable *ht, DataType data)
{
assert(ht);
if (-1 == HashTableFind(ht, data))
return;
ht->_table[HashTableFind(ht, data)]._state = DELETE;
ht->_size--;
}
int HashTableSize(HashTable *ht)
{
assert(ht);
return ht->_size;
}
int HashTableEmpty(HashTable *ht)
{
assert(ht);
if (0 == ht->_size)
return 1;
return 0;
}
void HashTableDestory(HashTable* ht)
{
assert(ht);
free(ht->_table);
ht->_table = NULL;
ht->_capacity = 0;
ht->_size = 0;
ht->_total = 0;
}
int HashFunc(HashTable* ht, int data)
{
assert(ht);
return data % (ht->_capacity);
}
int IsLineDete(HashTable* ht, int HashAddr)
{
HashAddr = HashAddr + 1;
if (HashAddr == ht->_capacity)
HashAddr = 0;
return HashAddr;
}
int DeteTwo(HashTable * ht, int HashAddr, int i)
{
HashAddr = HashAddr + 2 * i + 1;
if (HashAddr >= ht->_capacity)
HashAddr %= ht->_capacity;
return HashAddr;
}
void TestHashData()
{
HashTable ht;
HashTableInit(&ht, 10, _IsLine, DataToInt);
HashTableInsert(&ht, 5);
HashTableInsert(&ht, 9);
HashTableInsert(&ht, 13);
HashTableInsert(&ht, 10);
HashTableInsert(&ht, 2);
HashTableInsert(&ht, 13);
HashTableInsert(&ht, 10);
HashTableInsert(&ht, 2);
HashTableInsert(&ht, 8);
int size = HashTableSize(&ht);
DataType data = ht._table[HashTableFind(&ht, 9)]._data;
HashTableDelete(&ht, 13);
size = HashTableSize(&ht);
HashTableDestory(&ht);
}
#if 0
void TestHashStr()
{
HashTable ht;
HashTableInit(&ht, 10, _IsLine, StrToInt);
HashTableInsert(&ht, "b");
HashTableInsert(&ht, "ca");
HashTableInsert(&ht, "a");
HashTableInsert(&ht, "ac");
int size = HashTableSize(&ht);
DataType data = ht._table[HashTableFind(&ht, "ac")]._data;
HashTableDelete(&ht, "a");
size = HashTableSize(&ht);
HashTableDestory(&ht);
}
#endif
Common.c
#include "Common.h"
int GetCapacity(size_t capacity)
{
int i = 0;
for (; i < 28; i++)
{
if (capacity < _PrimeList[i])
return _PrimeList[i];
}
return _PrimeList[27];
}
size_t StrToInt(const char * str)
{
unsigned int seed = 131;
unsigned int hash = 0;
while (*str)
{
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF);
}
size_t DataToInt(int data)
{
return data;
}
Common.h
#pragma once
#define size_t unsigned long
#define _PrimeSize 28
static const unsigned long _PrimeList[_PrimeSize] =
{
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
};
int GetCapacity(size_t capacity);
size_t StrToInt(const char * str);
size_t DataToInt(int data);