对哈希表进行一些基本操作
源文件
#include"HashBucket.h"
#include"Prime.h"
int main()
{
test();
return 0;
}
//初始化哈希桶
void InitHashBucket(HT* ht, int capacity,PHF dataToInt)
{
int BucketNo = 0;
capacity = GetPrime(capacity);
ht->_table = (PNode*)malloc(capacity*sizeof(Node));
assert(ht->_table);
//所有存放链表的地址置空
for (int i = 0; i < capacity; i++)
{
ht->_table[i]=NULL;
}
ht->_capacity = capacity;
ht->_size = 0;
ht->_DateToInt = dataToInt;
}
//插入,此哈希桶中没有相同元素
int InsertHashBucketUnique(HT* ht, K key, V v)
{
int BucketNo = 0;
PNode pNewNode = NULL;
PNode pCur = NULL;
//检查是否需要扩容
ChechCapacity(ht);
BucketNo = HashFunc(ht, key);
pCur = ht->_table[BucketNo];
//查找是否有相同元素
while (pCur)
{
//若有相同元素,则插入失败
if (pCur->_data._key == key)
return 0;
pCur = pCur->_pNext;
}
//跳出循环,则没有找到相同元素,插入新结点
//头插法
pNewNode = BuyNode(key, v);
pNewNode->_pNext = ht->_table[BucketNo];
ht->_table[BucketNo] = pNewNode;
ht->_size++;
//插入成功
return 1;
}
//删除,此哈希桶中没有相同元素
int DeleteHashBucketUnique(HT* ht, K key)
{
PNode pCur = NULL;
PNode pPrev = NULL;
int BucketNo = 0;
key = ht->_DateToInt(key);
BucketNo = HashFunc(ht, key);
pCur = ht->_table[BucketNo];
while (pCur)
{
//找到元素,删除
if (pCur->_data._key == key)
{
//若为头结点
if (pCur == ht->_table[BucketNo])
ht->_table[BucketNo] = pCur->_pNext;
else
pPrev->_pNext = pCur->_pNext;
free(pCur);
pCur = NULL;
ht->_size--;
//删除成功
return 1;
}
//记录前一个结点
pPrev = pCur;
pCur = pCur->_pNext;
}
//找不到,删除失败
return 0;
}
//插入元素,此哈希表中可能存在相同元素
void InsertHashBucketEqual(HT* ht, K key, V v)
{
int BucketNo = 0;
PNode pCur = NULL;
//检查是否需要扩容
key = ht->_DateToInt(key);
ChechCapacity(ht);
BucketNo = HashFunc(ht, key);
pCur = BuyNode(key, v);
//头插法
pCur->_pNext = ht->_table[BucketNo];
ht->_table[BucketNo] = pCur;
ht->_size++;
}
//删除,此哈希桶中有相同元素
int DeleteHashBucketEqual(HT* ht, K key)
{
PNode pCur = NULL;
PNode pPrev = NULL;
int BucketNo = HashFunc(ht, key);
int oldsize = ht->_size;
key = ht->_DateToInt(key);
pCur = ht->_table[BucketNo];
while (pCur)
{
//找到元素,删除
if (pCur->_data._key == key)
{
//若为头结点
if (pCur == ht->_table[BucketNo])
{
ht->_table[BucketNo] = pCur->_pNext;
free(pCur);
pCur = ht->_table[BucketNo];
}
else
{
pPrev->_pNext = pCur->_pNext;
free(pCur);
pCur = pPrev->_pNext;
}
ht->_size--;
}
else
{
//记录前一个结点
pPrev = pCur;
pCur = pCur->_pNext;
}
}
//删除成功
if (oldsize - (ht->_size) > 0)
return 1;
//没找到或删除失败
else
return 0;
}
//查找
PNode FindHashBucket(HT* ht, K key)
{
int BucketNo = 0;
PNode pCur = NULL;
if (NULL==ht)
return 0;
key = ht->_DateToInt(key);
BucketNo = HashFunc(ht, key);
pCur = ht->_table[BucketNo];
while (pCur)
{
if (pCur->_data._key == key)
return pCur;
pCur = pCur->_pNext;
}
//找不到,返回0
return 0;
}
//扩容
int ChechCapacity(HT* ht)
{
//扩容条件
if (ht->_capacity == ht->_size)
{
unsigned long newcapacity = GetPrime(ht->_capacity);
PNode pCur = NULL;
int NewBacketNo = 0;
//创建一个新的哈希桶
PNode* newtable = (PNode*)malloc(sizeof(Node)*newcapacity);
assert(newtable);
//将原哈希桶中数据转移到新的哈希桶中
//遍历原哈希桶
for (unsigned long i = 0; i < ht->_capacity; i++)
{
pCur = ht->_table[i];
while (pCur)
{
//计算新桶号
NewBacketNo = pCur->_data._key%newcapacity;
//头插,取出pCur放入新桶中
ht->_table[i] = pCur->_pNext;
pCur->_pNext = newtable[NewBacketNo];
newtable[NewBacketNo] = pCur;
//返回原哈希表的下一个结点
pCur = ht->_table[i];
}
}
//释放原哈希桶
free(ht->_table);
ht->_table = newtable;
//更新容量
ht->_capacity = newcapacity;
return 1;
}
else
return 0;
}
//销毁
void DestroyHashBucket(HT* ht)
{
PNode pCur = NULL;
for (unsigned long i = 0; i < ht->_capacity; i++)
{
pCur = ht->_table[i];
while (pCur)
{
ht->_table[i] = pCur->_pNext;
free(pCur);
pCur = ht->_table[i];
}
}
free(ht->_table);
ht->_table = NULL;
}
//哈希函数
int HashFunc(HT* ht, K key)
{
return key%ht->_capacity;
}
//创建新结点
PNode BuyNode(K key, V value)
{
PNode pNewNode = (PNode)malloc(sizeof(Node));
assert(pNewNode);
pNewNode->_pNext = NULL;
pNewNode->_data._key = key;
pNewNode->_data._value = value;
return pNewNode;
}
//打印哈希桶
void PrintHashBucket(HT* ht)
{
PNode pCur = NULL;
for (unsigned long i = 0; i < ht->_capacity; i++)
{
pCur = ht->_table[i];
while (pCur)
{
printf("Table[%d] :(%d) (%d)", i, pCur->_data._key, pCur->_data._value);
printf("\n");
pCur = pCur->_pNext;
}
}
printf("\n");
}
//字符串转化成整型函数
size_t BKDRHash(const char * str)
{
unsigned int seed = 131; // 31 131 1313
unsigned int hash = 0;
while (*str)
{
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF);
}
//数据转化成整型函数
size_t DataToInt(K key)
{
return key;
}
void test()
{
HT ht;
InitHashBucket(&ht, 10, DataToInt);
InsertHashBucketEqual(&ht, 12, 20);
InsertHashBucketEqual(&ht, 30, 20);
InsertHashBucketEqual(&ht, 40, 20);
InsertHashBucketEqual(&ht, 40, 20);
PrintHashBucket(&ht);
InsertHashBucketUnique(&ht, 30, 20);
InsertHashBucketUnique(&ht, 41, 22);
PrintHashBucket(&ht);
DeleteHashBucketUnique(&ht, 30);
DeleteHashBucketEqual(&ht, 40);
PrintHashBucket(&ht);
DestroyHashBucket(&ht);
system("pause");
}
头文件
#include<malloc.h>
#include<assert.h>
#include<stdio.h>
typedef int K;
typedef int V;
typedef (*PHF)(K); //函数指针
typedef struct Pair
{
K _key;
V _value;
}Pair;
typedef struct Node
{
struct Node* _pNext;
Pair _data;
}Node, *PNode;
typedef struct HashTable
{
PNode* _table;
unsigned long _capacity;
unsigned long _size;
PHF _DateToInt;
}HT;
void InitHashBucket(HT* ht, int capacity,PHF dataToInt);
int InsertHashBucketUnique(HT* ht, K key, V v);
int DeleteHashBucketUnique(HT* ht, K key);
void InsertHashBucketEqual(HT* ht, K key, V v);
int DeleteHashBucketEqual(HT* ht, K key);
PNode FindHashBucket(HT* ht, K key);
int ChechCapacity(HT* ht);
void DestroyHashBucket(HT* ht);
int HashFunc(HT* ht, K key);
PNode BuyNode(K key, V value);
void PrintHashBucket(HT* ht);
void test();
此外,还用了一个计算素数容量的函数
#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
};
unsigned long GetPrime(unsigned long capacity);
#include "Prime.h"
unsigned long GetPrime(unsigned long capacity)
{
unsigned long i = 0;
for (; i < _PrimeSize; i++)
{
if (capacity < _PrimeList[i])
return _PrimeList[i];
}
return _PrimeList[_PrimeSize - 1];
}