哈希 == 散列
哈希技术:让数据的存储位置和数据值本身产生某种联系,这种联系用哈希函数来表示,使得每一个关键字都会有一个存储位置
如果数据的关键字和数据的存储位置之间存在一个映射关系,这时如果数据无序且需要查找,则不用一个一个遍历,可以直接使用哈希计算
映射关系 == 哈希函数:f(关键字)=存储地址
如果我们使用哈希存储数据,则会有一个效果:假设我们需要查找一个值X是否存储(数据无序),只需要将X代入到哈希函数f(x)中计算即可,会得到一个地址Y,这时只需要直接去看一下地址Y里面的值是否是X即可,时间复杂度是O(1)
哈希函数是一个压缩映像函数。关键码集合比哈希表地址集合大得多。因此有可能经过哈希函数的计算,把不同的关键码映射到同一个哈希地址上,这就产生了冲突。
f(x1)=y,f(x2)=y
1.1,线性探测法:fi(key) = (f(key) + di) MOD m ( di = 1,2,3,...,m-1)//从冲突的地方向右探测
1.2,二次探测法:fi(key) = (f(key) + di) MOD m ( di = 1^2,,-1^2,2^2,-2^2,,...,q^2,-q^2),q<= m/2
//从冲突的地方向左、右两方探测,而且探测的距离越大
1.3,随机探测法:di采用随机函数得到
fi(key) = RHi(key) (RHi表示多个散列函数)
基础表哈希,溢出表顺序,并且如果在基础表里面找不到(没有冲突),就不需要在溢出表里面找


.h文件
#pragma once
#define MAX_SIZE 12
typedef int ELEMTYPE;
typedef struct Node
{
ELEMTYPE data;
struct Node* next;
}Node;
typedef struct List_hash
{
struct Node arr[MAX_SIZE];//存放单链表的头节点
}List_hash,*List_Phash;
//初始化
void Init_List_hash(List_hash* lh);
//插入(头插)
bool Inseert_List_hash(List_hash* lh, ELEMTYPE val);
//删除
bool Del_List_hash(List_hash* lh, ELEMTYPE val);
//查找
Node* Find_List_hash(List_hash* lh, ELEMTYPE val);
//打印
void Show(List_hash* lh);
.cpp文件
#include "list_hash.h"
#include
#include
using namespace std;
//初始化(有头节点)
void Init_List_hash(List_hash* lh)
{
for (int i = 0; i < MAX_SIZE; i++)
{
lh->arr[i].next = nullptr;
}
}
//插入(头插)
bool Inseert_List_hash(List_hash* lh, ELEMTYPE val)
{
assert(lh != nullptr);
//1.首先利用hash函数计算在哪一个头节点插入
int index = val % MAX_SIZE;
//2.插入
Node* newnode = (Node*)malloc(sizeof(Node));
assert(newnode != nullptr);
newnode->data = val;
newnode->next = lh->arr[index].next;
lh->arr[index].next = newnode;
return true;
}
//删除
bool Del_List_hash(List_hash* lh, ELEMTYPE val)
{
assert(lh != nullptr);
//1.首先利用hash函数计算在哪一个头节点删除
int index = val % MAX_SIZE;
//2.判断这个头节点后面有没有有效节点(判断是否为空链表),不空查找,为空退出
if (lh->arr[index].next == nullptr)
{
//为空
return false;
}
Node* p = &(lh->arr[index]);
//找到所要删除的节点(p)
p = Find_List_hash(lh, val);
if (p == nullptr)
{
return false;
}
Node* q = &lh->arr[index];
//找到所要删除的节点的前一个节点(q)
for (; q->next != p; q = q->next);
//删除节点
q->next = p->next;
free(p);
return true;
}
//查找
Node* Find_List_hash(List_hash* lh, ELEMTYPE val)
{
assert(lh != nullptr);
//1.首先利用hash函数计算在哪一个头节点删除
int index = val % MAX_SIZE;
Node* p = lh->arr[index].next;
for (; p != nullptr; p = p->next)
{
if (p->data == val)
{
return p;
}
}
return nullptr;
}
//打印
void Show(List_hash* lh)
{
for (int i = 0; i < MAX_SIZE; i++)
{
cout << "[" << i << "]";
for (Node* p = lh->arr[i].next;p!=nullptr;p=p->next)
{
cout << p->data << "->";
}
cout <<"NULL" <<endl;
}
}
int main()
{
List_hash head;
Init_List_hash(&head);
Inseert_List_hash(&head, 48);
Inseert_List_hash(&head, 37);
Inseert_List_hash(&head, 15);
Inseert_List_hash(&head, 16);
Inseert_List_hash(&head, 29);
Inseert_List_hash(&head, 67);
Inseert_List_hash(&head, 56);
Inseert_List_hash(&head, 34);
Inseert_List_hash(&head, 47);
Inseert_List_hash(&head, 12);
Inseert_List_hash(&head, 25);
Inseert_List_hash(&head, 22);
Show(&head);
Del_List_hash(&head, 25);
Del_List_hash(&head, 34);
Del_List_hash(&head, 12);
Show(&head);
}