1,首先定义节点
一个hash表里面存了10 个链表节点 基于这个原理 读者可以实现更为复杂的hash表 要想更复杂 就可以定义一个新的结构体 里面含有多个hash表指针 层层套娃 下面是一个表中10个链表节点的实现
struct MyNode
{
int date;
MyNode* pNext;
};
struct HashTable
{
MyNode* val[10]; // 10个链表节点
};
2,数据存放
我们可以自己定义一个规则将数据 按照这个规则将数据存放在相应的链表中 我们叫这个规则称为hash函数 下面例子是 将要存放的数据%10 也就是根据其各位数将其存放在对应的链表下标中 而且 对存进来的数据进行有序存放 (从小到大)
//创建哈希表
//参数:无
//返回值:hash表头指针
HashTable* creatHashTable(){
HashTable* phash = new HashTable;
memset(phash, 0, sizeof(HashTable)); // 整个表里面的10个链表地址初始化为0
return phash;
// 插入数据放链表里面
bool insertHashTable(HashTable* phash, int date){
if (phash == NULL){
return false;
}
// 准备新节点获取存储地址
MyNode* pNode = phash->val[date % 10];
if (pNode == NULL){
phash->val[date % 10] = new MyNode;
phash->val[date % 10]->date = date;
phash->val[date % 10]->pNext = NULL;
}
else{
if (date <= pNode->date){
// 前插
MyNode* newNode = new MyNode;
newNode->date = date;
newNode->pNext = pNode;
pNode = newNode;
}
else // 遍历存放
{
while (pNode->pNext!=NULL && pNode->pNext->date<date) // 当下一个节点的数据小于要插入的数据时 移动节点指针
{
pNode = pNode->pNext;
}
if (pNode->pNext == NULL){
// 后插入
pNode->pNext = new MyNode;
pNode->pNext->date = date;
pNode->pNext->pNext = NULL;
}
else{
// 夹逼插入
MyNode* newNode = new MyNode;
newNode->date = date;
newNode->pNext = pNode->pNext;
pNode->pNext = newNode;
}
}
}
return true;
}
我们函数返回值可以自己设置
3,查找数据节点
根据数据查找返回数据所在的节点
// 根据数据查找节点
MyNode* findDate(HashTable* phash, int findDate){
if (phash == NULL){
return NULL;
}
MyNode* pNode = phash->val[findDate % 10];
if (pNode == NULL){
return NULL;
}
while (pNode)
{
if (pNode->date == findDate){
return pNode;
}
pNode = pNode->pNext;
}
// 否则没有找到
return NULL;
}
4,删除数据
我们可以将要删除是数据传进我们写的查找函数 再根据查找的节点来删除 注意:要想删除目标节点 就要知道目标节点的前一个节点 而目标节点的前一个节点又需要 重新从头节点开始遍历
// 删除数据
bool delFindDate(HashTable* phash,int delDate){
// 使用查找函数 直接找到要删除节点的 指针/ 地址
MyNode* pNode = findDate(phash, delDate);
if (pNode == NULL){
return false; // 找不到 删除失败
}
// 要想删除这个节点 那么要知道它的上一个节点 用上一个节点指向 它 的下一个节点 然后把 它 删除
// 要想知道 它 的上一个节点 必须从头节点找过来
MyNode* tempNode = phash->val[delDate % 10];
while (tempNode->pNext!=pNode)
{
tempNode = tempNode->pNext;
}// 跳出循环则找到它的上一个节点了
tempNode->pNext = pNode->pNext;
delete pNode;
return true;
}
5,删除整个hash表
// 删除整个表
void clearHashTable(HashTable* &phash){
if (phash == NULL){
return;
}
MyNode* phead;
MyNode* pNode;
for (int i = 0; i < 10; i++){
// 查表
if ((phead = phash->val[i]) != NULL)
{
// 如果链表不为空 那么 遍历链表
while (phead)
{
pNode = phead;
phead = phead->pNext;
delete pNode;
}
}
}// 最后删除装这10个链表头节点 的容器
delete[]phash;
phash = NULL;
}