#include <iostream>
using namespace std;
#define HashTable_Size 100
//用除留余数法求关键字的哈希地址
int Hash(int k,int m)
{
return k%m;
}
//**********************************************************
//开放地址法——闭哈希表
//**********************************************************
//闭哈希表的类型定义
#define MIN -100000000
typedef struct
{
int r[HashTable_Size];
int length;
}HashTable;
//闭哈希表的初始化
void InitHashTable(HashTable &HT)
{
int i;
for(i=0;i<HT.length;i++)
HT.r[i]=MIN;
}
//闭哈希表的插入——采用线性探测法处理冲突
void InsertHashTable_Close(HashTable &HT,int x)
{
int i,j,m;
m=HT.length;
i=Hash(x,m);
if(HT.r[i]==MIN)
HT.r[i]=x;
else
{
j=(i+1)%m;
while(HT.r[j]!=MIN && j!=i)//当查找到的哈希地址为非空,即产生冲突,并且j还没有循环一圈时,执行循环
j=(j+1)%m;
if(HT.r[j]==MIN)//如果找到了空的位置,则执行插入
HT.r[j]=x;
else//如果j循环一圈还没找到空的位置插入,则表示哈希表已经满了
cout<<"OVER FLOW!";
}
}
//闭哈希表的建立
void CreateHashTable_Close(HashTable &HT)
{
int i;
int n;//表中元素的个数
int h[100];
cin>>n>>HT.length;//n是元素个数,和表长不是一个概念
InitHashTable(HT);
for(i=0;i<n;i++)
cin>>h[i];//先把要输入的元素存储到一个数组中
for(i=0;i<n;i++)
InsertHashTable_Close(HT,h[i]);//用插入操作建立哈希表
}
//闭哈希表的查找
int HashSearch_Close(HashTable &HT,int x)
{
int i,j,m;
m=HT.length;
i=Hash(x,m);
if(HT.r[i]==x)
return i;//一次比较成功,找到了该记录,返回记录地址,查找结束
j=(i+1)%m;//若第一次查找有冲突,向后查找
while(HT.r[j]!=MIN && j!=i)
{//当查找到的哈希地址为非空,并且j还没有循环一圈时,执行循环
if(HT.r[j]==x)
return j;
j=(j+1)%m;
}
return -1;//没有查找到记录
}
//*****************************************************************************
//链地址法(拉链法)——开哈希表
/*基本思想是将所有哈希地址相同的记录存储到一个单链表中,在哈希表中存储的是所有
哈希地址相同的记录的头指针*/
//*****************************************************************************
//开哈希表的类型定义
typedef struct HTNode
{
int key;
struct HTNode *next;
}HTNode;
typedef struct HashList
{
HTNode *List[HashTable_Size];//该数组存放的是指针,即为哈希表
int length;
}HashList;
//开哈希表的初始化
void InitHashList(HashList &HL)
{
int i;
for(i=0;i<HL.length;i++)
HL.List[i]=NULL;
}
//开哈希表的插入
void InsertHashList_Open(HashList &HL,int x)
{
int i,m;
HTNode *p,*q;
m=HL.length;
i=Hash(x,m);
p=HL.List[i];//找到x在哈希表中所在的单链表,即和x相对应的头指针
if(p==NULL)
{//即和该记录对应的哈希地址为空,即目前还没有还该记录冲突的记录,则插入该元素
q=new HTNode;
q->key=x;
q->next=HL.List[i];
HL.List[i]=q;//这里不能用尾插法,得用头插法
}
else
{//即已有相同的哈希地址的记录
while(p!=NULL)
p=p->next;
q=new HTNode;
q->key=x;
q->next=HL.List[i];
HL.List[i]=q;
}
}
//开哈希表的建立
void CreateHashList_Open(HashList &HL)
{
int i;
int n;//表中元素的个数
int h[100];
cin>>n>>HL.length;
InitHashList(HL);
for(i=0;i<n;i++)
cin>>h[i];
for(i=0;i<n;i++)
InsertHashList_Open(HL,h[i]);
}
//开哈希表的查找
HTNode *HashSearch_Open(HashList &HL,int x)
{
int i,m;
HTNode *p;
m=HL.length;
i=Hash(x,m);
p=HL.List[i];//找到x在哈希表中所在的单链表,即和x相对应的头指针
if(p==NULL)
return NULL;
else
{//即已有相同的哈希地址的记录
while(p!=NULL && p->key!=x)
p=p->next;//当P为非空并且和x不相等
if(p->key==x)
return p;
return NULL;
}
}
void main()
{
//freopen("in.txt","r",stdin);
int i;
HashTable HT;
CreateHashTable_Close(HT);
i=HashSearch_Close(HT,47);
if(i!=-1)
cout<<HT.r[i]<<endl;
else
cout<<"Not Found!"<<endl;
/*HTNode *p;
HashList HL;
CreateHashList_Open(HL);
p=HashSearch_Open(HL,3);
if(p==NULL)
cout<<"Not Found!"<<endl;
else
cout<<p->key<<endl;*/
}
我写的和书上的不一样,因为我不知道这个哈希表具体是怎么用的,我根据我自己理解的哈希表的用法,去设计写这个哈希表的,虽然和书上的不一样,但是根本的思想还是一样的,现在我又掌握了哈希表的写法,嘿嘿,下一步应该是排序了,数据结构已经结课了,我要抓紧时间写把代码写一下!
现在我感觉轻松了好多,下午把线性代数考了,我感觉轻松极了,因为我心中的一块大石头落地了,接下来到就都小菜了,还有就是我可以有更多的精力来写程序了,而不是整天钻在抽象、枯燥的数学里面了,哈哈,努力啊!