最简单的哈希表创建

        这个哈希表是根据  取余的规则进行划分每个桶子的索引 ,代码关键部分都写了注释 ,废话不多说,上代码.

      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);
}

在C语言中,我们可以使用数组结合哈希函数来创建一个简单的电话簿数据结构,即哈希表(也叫散列表)。这里是一个基本的概念示例: 首先,定义一个结构体来表示联系人,包括姓名和电话号码: ```c typedef struct { char name[50]; char phone_number[20]; } Contact; ``` 接下来,我们选择一个合适的哈希函数来计算联系人的名字作为键值对的索引。常见的哈希函数如取模运算(键除以数组长度并取余数),然后分配一个动态大小的数组作为我们的哈希表: ```c #define MAX_CONTACTS 100 // 假设最大存储量 Contact contacts[MAX_CONTACTS] = {0}; // 初始化所有元素为0 int contact_count = 0; // 记录当前已添加的联系人数 // 哈希函数示例(取字符串长度取模) size_t hash_name(const char *name) { return strlen(name) % MAX_CONTACTS; } ``` 现在你可以编写插入、查找和删除函数来操作这个哈希表: - 插入(假设名字未重复): ```c void add_contact(char *name, char *phone_number) { if (contact_count < MAX_CONTACTS) { contacts[hash_name(name)].name = name; strcpy(contacts[hash_name(name)].phone_number, phone_number); contact_count++; } else { printf("电话簿已满,无法添加更多联系人。\n"); } } ``` - 查找: ```c char* find_phone_by_name(const char *name) { size_t index = hash_name(name); if (contacts[index].name != NULL && strcmp(contacts[index].name, name) == 0) { return contacts[index].phone_number; } else { return "找不到该联系人"; } } ``` - 删除(假设你知道名字并且它存在): ```c void remove_contact(const char *name) { size_t index = hash_name(name); if (contacts[index].name != NULL && strcmp(contacts[index].name, name) == 0) { memmove(&contacts[index], &contacts[index+1], (MAX_CONTACTS - index - 1) * sizeof(Contact)); contact_count--; contacts[MAX_CONTACTS-1].name = NULL; // 清理最后一个元素 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值