一次简单的散列查找习题
前言
在地址空间为0~16的散列区中,对以下关键字序列构造两个哈希表:
(Jan, Feb, Mar, Apr, May, June, July, Aug, Sep, Oct, Nov, Dec)
(1)用线性探测开放定址法处理冲突;
(2)用链地址法处理。
一、.h文件
#ifndef __HASH_H__
#define __HASH_H__
#include <iostream>
#include <cstring>
using namespace std;
struct Node
{
char Str[50];
Node* Next;
Node()
{
Str[0]=0;
Next=NULL;
}
};
class HashTable
{
private:
char table[17][20];
Node* table2;
bool Switch; // 2 kinds of search & insert
bool* sign;
bool* sign2;
bool test_key;
public:
HashTable();
int Hash(char str[]);
void HashInsert(char str[]);
bool getSign(int index);
bool getSign2(int index);
bool getSwitch();
void reverseSwitch();
void signMark(int index);
void sign2Mark(int index);
bool whetherInTable(char str[]);
};
HashTable::HashTable()
{
test_key=false;
//table = new char* [16];
sign = new bool [17];
table2 = new Node [17];
sign2 = new bool [17];
for(int i=0;i<16;++i)
{
table[i][0]=0;
sign[i]=true;
sign2[i]=true;
}
Switch=false;
if(test_key)cout<<"Initialize HashTable object successfully!\n";
}
bool HashTable::whetherInTable(char str[])
{
int index=Hash(str);
if(index<0 || index>=17)return false;
if(getSwitch())
{
while(!getSign(index) && strcmp(table[index],str)!=0 )
{
index=(index+1)%17;
}
if(strcmp(table[index],str)==0)return true;
return false;
}
else
{
if(getSign2(index))return false;
Node* ptr=&table2[index];
while(ptr!= NULL && strcmp(ptr->Str,str)!=0)
{
ptr=ptr->Next;
//cout<<ptr<<" ";
}
if(ptr==NULL)return false;
return true;
}
}
void HashTable::signMark(int index){sign[index]=false;}
void HashTable::sign2Mark(int index){sign2[index]=false;}
void HashTable::reverseSwitch(){Switch=!Switch;}
bool HashTable::getSwitch(){return Switch;}
int HashTable::Hash(char str[])
{
char first=str[0];
return (first-'A'+1)/2;
}
void HashTable::HashInsert(char str[])
{
int index=Hash(str);
if(index<0 || index>=17)return;
if(getSwitch())
{
while(!getSign(index))
{
index=(index+1)%17;
}
strcpy(table[index],str);
signMark(index);
}
else
{
if(getSign2(index))
{
strcpy(table2[index].Str,str);
sign2Mark(index);
}
else
{
Node* now = &table2[index];
while(now->Next!=NULL)
{
now=now->Next;
}
Node* newNode = new Node;
newNode->Next=NULL;
now->Next=newNode;
strcpy(newNode->Str,str);
}
}
if(test_key)cout<<"Insert element in HashTable object successfully!\n";
}
bool HashTable::getSign(int index){return sign[index];}
bool HashTable::getSign2(int index){return sign2[index];}
#endif
二、.cpp文件
#include <iostream>
#include "Hash.h"
using namespace std;
int main()
{
char strlist[12][10];
cout<<"请输入要存储的字符串元素(规制下才有效存储):";
for(int i=1;i<=12;++i)
{
cin>>strlist[i-1];
//cout<<strlist[i-1];
}
HashTable htable;
// if(htable.getSwitch())cout<<"线性探测法处理冲突:\n";
// else cout<<"链表地址法处理冲突:\n";
for(int i=0;i<12;++i)
{
htable.HashInsert(strlist[i]);
}
htable.reverseSwitch();
// if(htable.getSwitch())cout<<"线性探测法处理冲突:\n";
// else cout<<"链表地址法处理冲突:\n";
for(int i=0;i<12;++i)
{
htable.HashInsert(strlist[i]);
}
char que[50];
htable.reverseSwitch();
cout<<"线性探测法处理冲突(输入quit退出):\n";
while(true)
{
cout<<"请输入查询:";
cin>>que;
if(strcmp(que,"quit")==0)break;
cout<<"查询结果:"<<(htable.whetherInTable(que)?"在表内":"不在表内")<<endl;
}
htable.reverseSwitch();
cout<<"链表地址法处理冲突(输入quit退出):\n";
while(true)
{
cout<<"请输入查询:";
cin>>que;
if(strcmp(que,"quit")==0)break;
cout<<"查询结果:"<<(htable.whetherInTable(que)?"在表内":"不在表内")<<endl;
}
return 0;
}
//Jan Feb Mar Apr May June July Aug Sep Oct Nov Dec
并分别求这两个哈希表在等概率情况下查找成功和不成功时的平均查找长度。 设哈希函数为H(x)= └i/2┘,其中i为关键字中第一个字母在字母表中的序号。