高级程序员必备数据结构算法之哈希表

什么是哈希表

哈希表有称为散列表,是一种空间换结构的数据结构。为每个数据加入键元素,通过键进行检索。
哈希表的组成:
键(key):是自己添加的用于检索的数据,一般为整型,也可以为其他类型;
值(value):用于存储数据的地方;
索引:数组的下标;
哈希桶:连接在哈希表数组上的数组或链表;
哈希函数:将键值映射到索引上(数组下标),一般采用求余法;
如图:
在这里插入图片描述
过程:建立结构体,把数据加上键,键通过对求余,判断和哪个数组下标一致,就链接到哪个下标,这个过程称为映射。通过映射,当我们要寻找这个数据时,提供键值,一求余,就可以求出在哪个哈希桶,然后挨个检索,就可以迅速找到。(当哈希通的数量越多,检索的速度越快)。
注哈希桶的实现也可以用顺序表。

哈希表的代码实现

#include<iostream>
#include<Windows.h>
#include<string.h>

using namespace std;

#define MAX_SIZE 16
typedef char*	TYPE;

typedef struct _HashNode{
	_HashNode* next;
	TYPE data;
	int key;
}HashNode;

typedef HashNode* HashList;

typedef struct _HashTable {
	HashList HList;
	int Hash_size;
}HashTable;

static int debug = 0;

//求出每个节点对应的 位置
int Hash(int key,int max_size) {
	return (key % max_size);
}

//初始化哈希表
bool initHash(HashTable *Hash_T, int max_size) {
	if (Hash_T == NULL) {
		cout << "传入地址为空,无法初始化!" << endl;
		return false;
	}
	Hash_T->Hash_size = max_size;
	if (max_size <= 0) {
		Hash_T->Hash_size = MAX_SIZE;
	}
	Hash_T->HList = new HashNode[Hash_T->Hash_size];
	if (Hash_T->HList == NULL) {
		cout << "分配内存出现错误!" << endl;
		return false;
	}

	for (int i = 0; i < Hash_T->Hash_size; i++) {
		Hash_T->HList[i].data = 0;
		Hash_T->HList[i].key = 0;
		Hash_T->HList[i].next = NULL;
	}
	return true;
}

//在哈希表中查找指定键是否存在
HashNode*  find(HashTable *Hash_T, int key) {
	HashNode *HN;
	int e = 0;
	if (Hash_T == NULL) {
		cout << "传入地址为空,无法操作!" << endl;
		return false;
	}
	if (key < 0) {
		cout << "非合法键值,无法查找!" << endl;
		return false;
	}
	e = Hash(key, Hash_T->Hash_size);
	if (Hash_T->HList[e].next == NULL) {
		return NULL;
	}
	else {
		HN = Hash_T->HList[e].next;
	}
	do{
		if (HN->key == key) {
			return HN;
		}
		if (HN->next == NULL) {
			break;
		}
		HN = HN->next;
	} while (1);

	return NULL;
}

//向指定哈希表中插入数据
bool insert(HashTable *Hash_T, int key, void *elem) {
	int e = 0;
	int a = 0;
	if (Hash_T == NULL) {
		cout << "传入地址为空,无法操作!" << endl;
		return false;
	}
	if (key < 0) {
		cout << "非合法键值,无法插入!" << endl;
		return false;
	}
	if (find(Hash_T, key)) {
		cout << "Hash表中已经此键!" << endl;
		return false;
	}
	HashNode* HN = new HashNode();
	HN->data = (const TYPE)elem;
	HN->key = key;
	e = Hash(key, Hash_T->Hash_size);
	
	if (debug) {
		cout << "e为:" << e << endl;
		cout << "插入的键为:" << HN->key << "    插入的数据为:" << HN->data << endl;
	}
	if (Hash_T->HList[e].next==NULL) {
		Hash_T->HList[e].next = HN; 
		HN->next = NULL;
		if (debug) {
			cout << "insert:";
			cout << "插入的键为:" << (Hash_T->HList[e]).next->key << "    插入的数据为:" << Hash_T->HList[e].next->data << endl;
		}
		return true;
	}
	HN->next = Hash_T->HList[e].next;
	Hash_T->HList[e].next = HN;
	
	return true;

}

//删除哈希表根据键指定的元素
bool DeleteElems(HashTable *Hash_T, int key) {
	if (Hash_T == NULL) {
		cout << "传入地址为空,无法操作!" << endl;
		return false;
	}
	if (key < 0) {
		cout << "非合法键值,无法删除!" << endl;
		return false;
	}
	if (find(Hash_T, key)) {
		/*int a = 0;*/
		HashNode *HN;
		HashNode *HH;
		int e = 0;
		e = Hash(key, Hash_T->Hash_size);
		HN = Hash_T->HList[e].next;
		HH = &(Hash_T->HList[e]);
		if (debug) {
			cout << "find——e=" << e << endl;
		}
		while (1)
		{
			if (HN->key == key) {
				if (HN->next == NULL) {
					delete HN;
					HH->next = NULL;
					return true;
				}
				else
				{
					HH->next = HN->next;
					delete HN;
					return true;
				}
			}
			HH = HN;
			HN = HN->next;
		}
		return false;
	}
	else {
		cout << "没有找到对应要删除的键,操作失败!" << endl;
		return false;
	}
}


//删除哈希表
bool DeleteHash(HashTable *Hash_T) {
	HashNode* HN;
	HashNode* HH;
	if (Hash_T == NULL) {
		cout << "传入地址为空,无法操作!" << endl;
		return false;
	}
	for (int i = 0; i < Hash_T->Hash_size; i++) {
		HN = &(Hash_T->HList[i]);
		do{
			HH = HN;
			if (HH == NULL) {
				break;
			}
			HN = HN->next;
			delete HH;
		} while (1);
	}
	delete Hash_T;
	return true;
}


void* GetData(HashNode* e) {
	if (e == NULL) {
		cout << "传入的节点地址为空,无法查找" << endl; 
		return NULL;
	}
	return e->data;
}

int main() {
	HashTable Hash_;
	initHash(&Hash_, 6);
	const char* arry[] = { "张三","李四","翠花" };
	insert(&Hash_, 3, (void *)arry[0]);
	insert(&Hash_, 4, (void *)arry[1]);
	insert(&Hash_, 5, (void *)arry[2]);
	DeleteElems(&Hash_, 3);
	HashNode* e;
	for (int i = 0; i < 6; i++) {
		
		e = find(&Hash_, i);
		if (debug) {
			if (e) {
				cout << "外e:" << e->key << endl;
			}

		}
		
		if (e) {
			printf("%s\n", GetData(e));
		}
		else {
			printf("not found(key:%d)\n", i);
		}
	}
	system("pause");
}

结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小生乔克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值