散列(Hashing)在现实中经常遇到按照给定的值进行查询的实例。在软件开发过程记录存放的位置和用于表示他的数据项直接的对应关系。这种数据结构记录了数据和数据位置的信息,这就是Hashing。
我们哈希链表的数据结构图示是这样的
如图所示这就是整个hashtable的图书,其中红色部分其实是一个数组,里面存放的是链表,大家可以通过蓝色知道里面存放的是链表,绿色部分就是链表的一个结点,有数据域和指针域组成,紫色部分就是我们的数据域,里面的数据包含两部分,一部分是关键码,另一部分就是存放关键码整体数据的位置指针(比如我们要存放身份证号,但身份证号特别长,我们可以用身份证后的后六位作为标识,那么身份证后六位就是关键码,那个位置指针就可以找到全部身份证号的信息)。
首先我们要定义存储数据的数据结构
#define M 13 //一般为质数,降低哈希冲突
typedef int keytype;//关键码类型
typedef struct{}Record;//结果集
typedef struct//数据,就是图中的紫色部分
{
keytype key;//定义关键码
Record *recptr;//记录指针
}ElemType;
然后就是定义结点
struct HashNode//哈希链表的结点,由元素+指针构成。相当于图中的绿色部分
{
ElemType data;
HashNode *next;
};
接下来就是哈希表,就是那个数组
typedef struct//哈希表,相当于图中红色部分
{
HashNode*table[M];//数组
int cursize;//当前元素个数
}HashTable;
我们把整体的数据结构定义好以后来说说这个哈希链表的思想。
首先我们要根据建立关键码和存储位置有关的对应函数关系,这个函数我们称为散列方法,使得每个关键码都能对应唯一一个存储位置。一般我们通过取余法来实现。这个也叫转换函数。通过这个函数可以直接找到哈希表的下标位置
int Hash(int val)//哈希函数返回哈希表的某个位置
{
return val%M;//这里面的M我们定位13,一般是质数防止哈希冲突
}
找下标位置以后我们就要把数据存放到对应的数组下标,当table[0]种有数据我们就把下一个将要放入table[0]种的数据用链表的形式存放。
一下是链式哈希的全部实现代码
#include<iostream>
#include<assert.h>
using namespace std;
//链式哈希
#define M 13 //一般为质数,降低哈希冲突
typedef int keytype;//关键码类型
typedef struct{}Record;//结果集
typedef struct//元素
{
keytype key;//定义关键码
Record *recptr;//记录指针
}ElemType;
struct HashNode//哈希链表的结点,由元素+指针构成
{
ElemType data;
HashNode *next;
};
typedef struct//哈希表
{
HashNode*table[M];//数组
int cursize;//当前元素个数
}HashTable;
int Hash(int val)//哈希函数返回哈希表的某个位置
{
return val%M;
}
void Init_HashTable(HashTable* pt)//初始化
{
assert(pt!=NULL);
for(int i=0;i<M;i++)
{
pt->table[i]=NULL;
}
pt->cursize=0;
}
HashNode* buynode()
{
HashNode*s=(HashNode*)malloc(sizeof(HashNode));
if(s==NULL) exit(EXIT_FAILURE);
memset(s,0,sizeof(HashNode));
return s;
}
HashNode* findNode(HashTable* pt,int kx)//查询
{
assert(pt!=NULL);
int pos=Hash(kx);
HashNode*p=pt->table[pos];
while(p!=NULL&&p->data.key!=kx)
{
p=p->next;
}
return p;
}
void freenode(HashNode*p)
{
free(p);
}
bool Insert_HashTable(HashTable *pt,ElemType item)
{
assert(pt!=NULL);
HashNode*p=findNode(pt,item.key);
if(p!=NULL)
{
return false;
}
p=buynode();//新建一个结点
int pos=Hash(item.key);
p->data=item;//
p->next=pt->table[pos];
pt->table[pos]=p;//头插法
pt->cursize+=1;
return true;
}
bool Delete_Hashnode(HashTable*pt,keytype item)
{
assert(pt!=NULL);
HashNode*p=findNode(pt,item);
if(p==NULL)
{
return false;
}
int pos=Hash(item);
p=pt->table[pos];
HashNode*pr=p;
if(p->data.key==item)
{
pt->table[pos]=p->next;
}
else
{
while(p->next->data.key!=item)
{
p=p->next;
pr=pr->next;
}
pr->next=p->next->next;
p=NULL;
}
freenode(p);
pt->cursize-=1;
return true;
}
void show(HashTable*pt,int pos)
{
HashNode *p=pt->table[pos];
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
int main()
{
HashTable ht;
Init_HashTable(&ht);
ElemType item={-1,NULL}; //定义一个元素
while (cin>>item.key,item.key!=-1)
{
Insert_HashTable(&ht,item);
}
show(&ht,1);
Delete_Hashnode(&ht,14);
show(&ht,1);
}