这个哈希表是根据 取余的规则进行划分每个桶子的索引 ,代码关键部分都写了注释 ,废话不多说,上代码.
Hash.h代码如下:
#pragma once
#define MAXSIZE 128
//链表 节点的数据结构
typedef struct _LNode {
int key;
const void* value;
_LNode* next;
}LNode;
typedef LNode* List; //别名
typedef LNode* Element; //别名,这俩是同一个,就是使用的时候用来区分一下
typedef struct _Hash {
int m_typeLength; // 哈希筒子的数量
List* m_typeList; // 指针数组
}Hash;
//初始化哈希
Hash* initHash(int length);
//删除节点
void deleteHash(Hash* hash, int key);
//插入节点
void insertHash(Hash* hash, int key, const void* value);
//销毁哈希
void destroyHash(Hash* hash);
//获取哈希表的索引值
int getHashIndex(Hash* hash, int key);
//获得当前节点的元素
const void* getValue(Element e);
//查找key的节点
Element findKey(int key,Hash* hash);
Hash.cpp代码如下:
#include "Hash.h"
#include <iostream>
using namespace std;
//初始化哈希
Hash* initHash(int length) {
Hash* hash = NULL;
hash = new Hash;
//判断分配内存是否成功
if (!hash) {
cout << "哈希对象分配内存失败" << endl;
return NULL;
}
//如果当前传过来的筒子数量是0或者比0小,那么就初始化为默认值
if (length <= 0) {
hash->m_typeLength = MAXSIZE;
}
else {
hash->m_typeLength = length;
}
//给指针数组分配内存
hash->m_typeList = new List[hash->m_typeLength];
//判断指针数组是否分配内存成功
if (!hash->m_typeList) {
cout << "指针数组分配内存失败" << endl;
delete hash; //释放内存
return NULL;
}
//给每个桶子 的节点分配内存
for (int i = 0; i < hash->m_typeLength; i++)
{
hash->m_typeList[i] = new LNode;
if (!hash->m_typeList[i]) {
cout << "筒子里的节点分配内存失败" << endl;
delete[] hash->m_typeList; //分配失败就要手动释放已经分配的内存
delete hash;
return NULL;
}
else {
memset(hash->m_typeList[i], 0, sizeof(LNode)); //把每个桶子里的节点都置为0
}
}
return hash;
}
//删除节点
void deleteHash(Hash* hash,int key) {
List L = NULL;
Element cur = NULL, pre = NULL;
L = hash->m_typeList[getHashIndex(hash, key)];
cur = L->next; //获取第一个有效节点,因为头节点是空的,所以需要next
pre = L;
while (cur != NULL && cur->key != key)
{
pre = cur; //记录上一次的节点,方便把链表重新连接起来
cur = cur->next;
}
if (cur) {
pre->next = cur->next; //重新连接链表
delete cur;
}
}
//插入节点
void insertHash(Hash* hash, int key, const void* value) {
List L = NULL;
Element e = NULL, tmp = NULL;
//插入节点需要判断key值,不能有两个相同的key
e = findKey(key, hash);
//如果不存在
if (e == NULL) {
tmp = new LNode;
if (!tmp) {
cout << "插入的节点 内存分配失败" << endl;
return;
}
L = hash->m_typeList[getHashIndex(hash, key)]; //获得桶子的头节点
//头插法
tmp->next = L->next;
tmp->key = key;
tmp->value = value;
L->next = tmp;
}
else {
cout << "该key 已经存在了" << endl;
}
return;
}
//销毁哈希
void destroyHash(Hash* hash) {
List L = NULL;
Element e = NULL,tmp = NULL;
//遍历每一个桶子的节点,然后挨个销毁
for (int i = 0; i < hash->m_typeLength; ++i) {
L = hash->m_typeList[i]; //挨个获得每个桶子的头节点
e = L->next; //获得第一个有效节点
while (e != NULL)
{
tmp = e;
e = e->next;
delete tmp;
}
delete L; //销毁头节点
}
delete[] hash->m_typeList; //销毁指针数组
delete hash;
}
//获取哈希表的索引值
int getHashIndex(Hash* hash, int key) {
return key % hash->m_typeLength;
}
//获得当前节点的元素
const void* getValue(Element e) {
return e ? e->value : NULL;
}
//查找key的节点
Element findKey(int key, Hash* hash) {
List L = NULL;
Element e = NULL;
L = hash->m_typeList[getHashIndex(hash, key)]; //获得key值在哈希表中的位置
e = L->next; //所有的桶子的头节点都是空,所以需要next
while (e != NULL && e->key != key)
{
e = e->next;
}
return e;
}
main.cpp 代码如下:
#include "Hash.h"
#include <iostream>
using namespace std;
int main()
{
Hash* hash;
const char* arr[] = { "张一","张二","张三","张四","张五" };
//初始化
hash = initHash(7);
//插入五个节点
for (int i = 0; i < 5; ++i) {
insertHash(hash, i+1, arr[i]);
}
//输出所有的内容
for (int i = 0; i < hash->m_typeLength; ++i) {
Element e = findKey(i, hash);
if(e)
cout << "key: " << i + 1 << " 的数据为: " << (const char*)getValue(e) << endl;
else {
cout << "没有找到" << i+1 << "的节点" << endl;
}
}
cout << endl;
//删除key值为3的节点
deleteHash(hash, 3);
//再次输出所有的内容
for (int i = 0; i < hash->m_typeLength; ++i) {
Element e = findKey(i, hash);
if (e)
cout << "key: " << i + 1 << " 的数据为: " << (const char*)getValue(e) << endl;
else {
cout << "没有找到" << i + 1 << "的节点" << endl;
}
}
//销毁哈希函数
destroyHash(hash);
}