1.利用哈希表处理整型数据
1)HashTable.h
#ifndef __HASHTABLE_H__
#define __HASHTABLE_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 HTKeyType;
typedef int HTValueType;
enum State
{
EMPTY,
EXITS,
DELETE,
};
typedef struct HashNode
{
enum State _state;
HTKeyType _key;
HTValueType _value;
}HashNode;
typedef struct HashTable
{
HashNode* tables;
size_t len; // 长度
size_t size; // 有效数据个数
}HashTable;
void HTInit(HashTable* ht, size_t len);
void HTDestory(HashTable* ht);
int HTInsert(HashTable* ht, HTKeyType key, HTValueType value);
int HTRemove(HashTable* ht, HTKeyType key);
HashNode* HTFind(HashTable* ht, HTKeyType key);
int HTSize(HashTable* ht);
int HTEmpty(HashTable* ht);
void HashPrint(HashTable* ht);
#endif
2)HashTable.c
#include "HashTable.h"
//闭散列
void HTInit(HashTable* ht, size_t len)
{
size_t i;
assert(len > 0);
assert(ht);
len = GetNextPrime(len);
ht->len = len;
ht->size = 0;
ht->tables = (HashNode*)malloc(sizeof(HashNode)*ht->len);
memset(ht->tables, 0, sizeof(HashNode)*len);
for (i = 0; i < ht->len; i++)
{
ht->tables[i]._state = EMPTY;
}
}
void HTDestory(HashTable* ht)
{
assert(ht);
free(ht->tables);
ht->tables = NULL;
ht->len = 0;
ht->size = 0;
}
size_t HashTableFunc(HTKeyType key, size_t len)
{
return (key) % len;
}
void ExpendCapacity(HashTable *ht)//给数组增容变为新数组
{
if ((ht->size * 10) / (ht->len) > 7)//如果当前的元素个数>数组长度的0.7增容减少哈希冲突
{
HashTable newht;
HTInit(&newht, GetNextPrime(ht->len));
for (unsigned int i = 0; i <ht->len; i++)
{
if (ht->tables[i]._state == EXITS)
{
HTInsert(&newht, ht->tables[i]._key, ht->tables[i]._value);
}
}
HTDestory(ht);
ht->len = newht.len;
ht->size = newht.size;
ht->tables = newht.tables;
}
}
int HTInsert(HashTable* ht, HTKeyType key, HTValueType value)
{
// 增容
int i = 0;
size_t index;
size_t start;
ExpendCapacity(ht);
start = HashTableFunc(key, ht->len);
index = start;
while (ht->tables[index]._state == EXITS)
{
if (ht->tables[index]._key == key)
{
return 0;
}
else
{
/*++index;
if (index == ht->_len){
index = 0;
}*/
++i;
index = start + i*i;
index %= ht->len;
}
}
ht->tables[index]._state = EXITS;
ht->tables[index]._key = key;
ht->tables[index]._value = value;
ht->size++;
return 1;
}
int HTRemove(HashTable* ht, HTKeyType key)
{
assert(ht);
HashNode* cur = HTFind(ht, key);//先查找位置
if (cur == NULL)
{
return 0;
}
else
{
cur->_state = DELETE;//直接把状态置为删除
ht->size--;
return 1;
}
}
HashNode* HTFind(HashTable* ht, HTKeyType key)
{
assert(ht);
int index = HashTableFunc(key, ht->len);
int i = 1;
while (ht->tables[index]._state != EMPTY)
{
if (ht->tables[index]._key == key)
{
if (ht->tables[index]._state == EXITS)
{
return &(ht->tables[index]);
}
else
{
return NULL;
}
}
else
{
++index;
if (index == ht->len)
{
index = 0;
}
}
}
return NULL;
}
int HTSize(HashTable* ht)
{
assert(ht);
return ht->size;
}
int HTEmpty(HashTable* ht)
{
assert(ht);
return ht->size == 0 ? 0 : 1;
}
void HashPrint(HashTable *ht)//打印数组
{
unsigned int i = 0;
for (i = 0; i < ht->len; i++)
{
if (ht->tables[i]._state == EXITS)
printf("[%d]->Exits->%d\n", i, ht->tables[i]._key);
else if (ht->tables[i]._state == EMPTY)
{
printf("[%d]->Empty\n", i);
}
else
{
printf("[%d]->Delte\n", i);
}
}
printf("\n");
}
3)Test.c
#include "HashTable.h"
void HTtest1()
{
HashNode* ret;
HashTable ht;
size_t i;
HTInit(&ht, 10);
HTInsert(&ht, 7, 0);
HTInsert(&ht, 17, 0);
HTInsert(&ht, 27, 0);
HTInsert(&ht, 8, 0);
HashPrint(&ht);
HTRemove(&ht, 17);
ret = HTFind(&ht, 27);
ret->_value = 10;
HashPrint(&ht);
/*for (i = 0; i < 10; ++i)
{
HTInsert(&ht, rand(), i);
}
HashPrint(&ht);*/
}
int main()
{
HTtest1();
system("pause");
return 0;
}
2.利用哈希表处理字符类型数据
1)HashTable.h
#ifndef __HASHTABLE_H__
#define __HASHTABLE_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* HTKeyType;
typedef int HTValueType;
enum State
{
EMPTY,
EXITS,
DELETE,
};
typedef struct HashNode
{
enum State _state;
HTKeyType _key;
HTValueType _value;
}HashNode;
typedef struct HashTable
{
HashNode* tables;
size_t len; // 长度
size_t size; // 有效数据个数
}HashTable;
void HTInit(HashTable* ht, size_t len);
void HTDestory(HashTable* ht);
int HTInsert(HashTable* ht, HTKeyType key, HTValueType value);
int HTRemove(HashTable* ht, HTKeyType key);
HashNode* HTFind(HashTable* ht, HTKeyType key);
int HTSize(HashTable* ht);
int HTEmpty(HashTable* ht);
void HashPrint(HashTable* ht);
#endif
2)HashTable.c
#include "HashTable.h"
//闭散列
void HTInit(HashTable* ht, size_t len)
{
size_t i;
assert(len > 0);
assert(ht);
len = GetNextPrime(len);
ht->len = len;
ht->size = 0;
ht->tables = (HashNode*)malloc(sizeof(HashNode)*ht->len);
memset(ht->tables, 0, sizeof(HashNode)*len);
for (i = 0; i < ht->len; i++)
{
ht->tables[i]._state = EMPTY;
}
}
void HTDestory(HashTable* ht)
{
assert(ht);
free(ht->tables);
ht->tables = NULL;
ht->len = 0;
ht->size = 0;
}
size_t HashTableFunc(HTKeyType key, size_t len)
{
return StrHash(key) % len;
}
void ExpendCapacity(HashTable *ht)//给数组增容变为新数组
{
if ((ht->size * 10) / (ht->len) > 7)//如果当前的元素个数>数组长度的0.7增容减少哈希冲突
{
HashTable newht;
HTInit(&newht, GetNextPrime(ht->len));
for (unsigned int i = 0; i <ht->len; i++)
{
if (ht->tables[i]._state == EXITS)
{
HTInsert(&newht, ht->tables[i]._key, ht->tables[i]._value);
}
}
HTDestory(ht);
ht->len = newht.len;
ht->size = newht.size;
ht->tables = newht.tables;
}
}
int HTInsert(HashTable* ht, HTKeyType key, HTValueType value)
{
// 增容
int i = 0;
size_t index;
size_t start;
ExpendCapacity(ht);
start = HashTableFunc(key, ht->len);
index = start;
while (ht->tables[index]._state == EXITS)
{
if (ht->tables[index]._key == key)
{
return 0;
}
else
{
/*++index;
if (index == ht->_len){
index = 0;
}*/
++i;
index = start + i*i;
index %= ht->len;
}
}
ht->tables[index]._state = EXITS;
ht->tables[index]._key = key;
ht->tables[index]._value = value;
ht->size++;
return 1;
}
int HTRemove(HashTable* ht, HTKeyType key)
{
assert(ht);
HashNode* cur = HTFind(ht, key);//先查找位置
if (cur == NULL)
{
return 0;
}
else
{
cur->_state = DELETE;//直接把状态置为删除
ht->size--;
return 1;
}
}
HashNode* HTFind(HashTable* ht, HTKeyType key)
{
assert(ht);
int index = HashTableFunc(key, ht->len);
int i = 1;
while (ht->tables[index]._state != EMPTY)
{
if (ht->tables[index]._key == key)
{
if (ht->tables[index]._state == EXITS)
{
return &(ht->tables[index]);
}
else
{
return NULL;
}
}
else
{
++index;
if (index == ht->len)
{
index = 0;
}
}
}
return NULL;
}
int HTSize(HashTable* ht)
{
assert(ht);
return ht->size;
}
int HTEmpty(HashTable* ht)
{
assert(ht);
return ht->size == 0 ? 0 : 1;
}
void HashPrint(HashTable *ht)//打印数组
{
int i = 0;
char* strState[3] = { "EMPTY", "EXIST", "DELETE" };
assert(ht);
for (; i < ht->len; ++i)
{
printf("%s->table[%d]%s:%d\n", strState[ht->tables[i]._state], i,
ht->tables[i]._key, ht->tables[i]._value);
}
printf("\n");
}
3)Test.c
#include "HashTable.h"
void HTtest2()
{
int i = 0;
HashNode* ret;
char* strs[] = { "insert", "insert", "insert", "insert", "insert", "sort", "insert", "sort", "find" };
/*char* strs[] = {"abcd", "bcad", "cbad","cbad", "aad", "abc", "acb"};*/
HashTable ht;
HTInit(&ht, 10);
for (; i < sizeof(strs) / sizeof(char*); ++i)
{
ret = HTFind(&ht, strs[i]);
if (ret)
{
ret->_value++;
}
else
{
HTInsert(&ht, strs[i], 1);
}
}
HashPrint(&ht);
}
int main()
{
HTtest2();
system("pause");
return 0;
}