雜湊表——拉鍊法
阿新 • • 發佈:2018-11-10
一、Hash.h
#ifndef __HASH_H__
#define __HASH_H__
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int KeyType;
typedef struct HashNode
{
KeyType _key;
struct HashNode* _next;
}HashNode;
typedef struct HashTable
{
HashNode** _tables; //指標陣列
size_t _size;
size_t _capacity;
}HashTable;
HashNode* BuyHashNode(KeyType key);
size_t HashFunc(HashTable* ht, KeyType key);
static size_t GetNextPrimeNum(HashTable* ht);
void HashTableInit(HashTable* ht, size_t Initsize);
int HashTableInsert(HashTable* ht, KeyType key);
HashNode* HashTableFind(HashTable* ht, KeyType key);
int HashTableRemove(HashTable* ht, KeyType key);
void HashTablePrint(HashTable* ht);
void HashTableDestory(HashTable* ht);
#endif __HASH_H__
二、Hash.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include "Hash.h"
//初始化
void HashTableInit(HashTable* ht, size_t Initsize)
{
assert(ht);
ht->_tables = (HashNode**)malloc(Initsize*sizeof(HashNode*));
assert(ht->_tables);
ht->_size = 0;
ht->_capacity = Initsize;
for (size_t i = 0; i < ht->_capacity; i++)
{
ht->_tables[i] = NULL;
}
}
//銷燬
void HashTableDestory(HashTable* ht)
{
assert(ht);
for (size_t index = 0; index < ht->_capacity; index++) //先銷燬每一個連結串列
{
HashNode* cur = ht->_tables[index];
while (cur)
{
HashNode* next = cur->_next;
free(cur);
cur = NULL;
cur = next;
}
}
free(ht->_tables); //再銷燬順序表
ht->_tables = NULL;
ht->_size = ht->_capacity = 0;
}
//雜湊函式-查詢位置
size_t HashFunc(HashTable* ht, KeyType key)
{
return key % ht->_capacity;
}
//素數表
static size_t GetNextPrimeNum(HashTable* ht)
{
const int _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 index = 0;
while (index < _PrimeSize)
{
if (ht->_capacity < _PrimeList[index])
{
return _PrimeList[index];
}
index++;
}
return _PrimeList[_PrimeSize - 1];
}
//擴容
void Checkcapacity(HashTable* ht)
{
assert(ht);
if (ht->_size == ht->_capacity) //將載荷因子控制在1
{
HashTable newht; //新建一個雜湊表
HashTableInit(&newht, GetNextPrimeNum(ht));
for (size_t i = 0; i < ht->_capacity; i++)
{
HashNode* cur = ht->_tables[i];
while (cur)
{
HashNode* next = cur->_next; //儲存下一個節點
size_t index = HashFunc(&newht, cur->_key); //重新計算原雜湊表中每一個key在新雜湊表中的位置
//利用原來已開闢的空間來進行連結,不用再重新開闢空間
cur->_next = newht._tables[index];
newht._tables[index] = cur;
cur = next;
}
ht->_tables[i] = NULL;
}
free(ht->_tables); //銷燬原雜湊表
ht->_tables = newht._tables; //更新雜湊表
ht->_capacity = newht._capacity;
}
}
//建立結點
HashNode* BuyHashNode(KeyType key)
{
HashNode* newnode = (HashNode*)malloc(sizeof(HashNode));
assert(newnode);
newnode->_key = key;
newnode->_next = NULL;
return newnode;
}
//插入
int HashTableInsert(HashTable* ht, KeyType key)
{
assert(ht);
Checkcapacity(ht);
size_t index = HashFunc(ht, key);
HashNode* cur = ht->_tables[index];
while (cur)
{
if (cur->_key == key)
{
return 0;
}
cur = cur->_next;
}
HashNode* newnode = BuyHashNode(key);
newnode->_next = ht->_tables[index];
ht->_tables[index] = newnode;
ht->_size++;
return 1;
}
//查詢
HashNode* HashTableFind(HashTable* ht, KeyType key)
{
assert(ht);
size_t index = HashFunc(ht, key);
HashNode* cur = ht->_tables[index];
while (cur)
{
if (cur->_key == key)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
//刪除
int HashTableRemove(HashTable* ht, KeyType key)
{
assert(ht);
size_t index = HashFunc(ht, key);
HashNode* cur = ht->_tables[index];
if (cur == NULL)
{
return 0;
}
else if (cur->_next == NULL)
{
if (cur->_key == key)
{
free(cur);
ht->_tables[index] = NULL;
ht->_size--;
return 1;
}
return 0;
}
else
{
HashNode* prev = ht->_tables[index];
while (cur)
{
if (cur->_key == key)
{
prev->_next = cur->_next;
free(cur);
cur = NULL;
ht->_size--;
return 1;
}
prev = cur;
cur = cur->_next;
}
return 0;
}
}
//列印
void HashTablePrint(HashTable* ht)
{
assert(ht);
printf("\n");
for (size_t index = 0; index < ht->_capacity; index++)
{
HashNode* cur = ht->_tables[index];
while (cur)
{
printf("%d->", cur->_key);
cur = cur->_next;
}
printf("NULL\n");
}
printf("\n");
}
三、Test.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include "Hash.h"
int main()
{
HashTable ht;
HashTableInit(&ht, 5);
int arr[] = { 10, 20, 30, 40, 50 };
for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
{
HashTableInsert(&ht, arr[i]);
}
HashTablePrint(&ht);
HashNode* cur = HashTableFind(&ht, 1);
if (cur)
{
printf("找到:%d\n", cur->_key);
}
else
{
printf("未找到\n");
}
HashTableInsert(&ht, 1);
HashTableInsert(&ht, 2);
HashTableInsert(&ht, 3);
HashTableInsert(&ht, 4);
HashTablePrint(&ht);
cur = HashTableFind(&ht, 1);
if (cur)
{
printf("找到:%d\n", cur->_key);
}
else
{
printf("未找到\n");
}
HashTableRemove(&ht, 1);
HashTablePrint(&ht);
cur = HashTableFind(&ht, 1);
if (cur)
{
printf("找到:%d\n", cur->_key);
}
else
{
printf("未找到\n");
}
HashTableDestory(&ht);
system("pause");
return 0;
}