一、实验目的
1、掌握散列表结构的定义和实现。
2、掌握散列表结构的应用。
二、实验内容
1、题目描述:
给定散列函数的除数D和操作数m,输出每次操作后的状态。
有以下三种操作:
插入x,若散列表已存在x,输出“Existed”,否则插入x到散列表中,输出所在的下标。
查询x,若散列表不含有x,输出“-1”,否则输出x对应下标。
删除x,若散列表不含有x,输出“Not Found”,否则输出删除x过程中移动元素的个数。
输入输出格式:
输入:
第一行两个整数D,m。分别代表散列函数的除数D和操作数m。
接下来m行,每行两个整数opt和x,分别代表操作类型和操作数。
若opt为0,代表插入x;
若opt为1,代表查询x;
若opt为2,代表删除x。
输出:
按需输出。
2、题目描述:
给定散列函数的除数D和操作数m,输出每次操作后的状态。
有以下三种操作:
插入x,若散列表已存在x,输出"Existed";
查询x,若散列表不含有x,输出"Not Found",否则输出x所在的链表长度;
删除x,若散列表不含有x,输出"Delete Failed",否则输出x所在链表删除x后的长度;
输入输出格式:
输入:
第一行两个整数D(1<=D<=3000)和m(1<=m<=3000),其中D为散列函数的除数,m为操作数。
接下来的m行,每行两个整数opt和x,分别代表操作类型和操作数。
若opt为0,则代表向散列表中插入x;
若opt为1,代表查询散列表中x是否存在;
若opt为2,(如果散列表中含有x),删除x。
输出:
按需输出。
#include<iostream>
#include<string>
using namespace std;
template<class K>
class Hash;
template<>
class Hash<int>{
//将theKey映射,方法为其本身
public:
size_t operator()(const int theKey) const{
return size_t(theKey);
}
};
template<class K,class E>
class HashTable{
private:
pair<const K,E>** table;//散列表
Hash<K> hash;//把类型K映射到一个整数
int dSize;//字典中数对个数
int divisor;//散列函数除数
protected:
int search(const K& theKey) const;
public:
HashTable(int theDivisor=10);
~HashTable(){
delete []table;}
void find(const K& theKey) const;
void insert(const pair<const K, E>&thePair);
void erase(K& theKey);
};
template<class K,class E>
HashTable<K,E>::HashTable(int theDivisor){
divisor=theDivisor;
dSize=0;
table=new pair<const K,E>*[divisor];
for(int i=0;i<divisor;i++){
table[i]=NULL;
}
}
template<class K,class E>
int HashTable<K,E>::search(const K& theKey)const{
//查找关键字为theKey的数对
//如果存在返回它的位置或则可以插入theKey的位置
int i=(int)hash(theKey)%divisor;//起始桶
int j=i; //从起始桶开始
do{
if(table[j]==NULL||table[j]->first==theKey)//标识
return j;//返回位置或可以插入的位置
j=(j+1)%divisor;//找到了,但标识不同,只能放下一个桶
}while(j!=i);//判断是否已经回到起始桶
return j; //表满了
}
template<class K,class E>
void HashTable<K, E>::find(const K& theKey) const{
//返回匹配数对的指针。不存在则返回NULL
int b=search(theKey);
if(table[b]==NULL||table[b]->first!=theKey){
//判断table是否匹配数对
cout<<-1<<endl;
return ;
}//没找到
cout<<b<<endl;//找到匹配数对
return ;
}
template<class K,class E>
void HashTable<K,E>::insert(const pair<const K, E>&thePair){
int b=search(thePair.first);
if(table[b]==NULL){
//没匹配到数对,且表未满
table[b]=new pair<const K,E>(thePair);
dSize++;
cout<<b<<endl;//输出散列表下标
}else{
if(table[b]->first==thePair.first){
//有标识一样的的数对,
cout<<"Existed"<<endl;
}
}
}
template<class K,class E>
void HashTable<K,E>::erase(K& theKey){
int b=search(theKey);
if(table[b]==NULL||table[b]->first!=theKey)
cout<<"Not Found"<<endl;
else{
//返回删掉这个元素之后,其他何其相同关键字元素填充进去
table[b] = NULL;
int flag=0;//移动元素的个数
int position=b;//循环定位的位置
int waitinsert=b;//等待其他元素到来的空位置
int signal;//判断是不是被排挤的非这个下标的元素,例如0却在1位。
do{
position = (position + 1) % divisor;//当前定位的位置
if (table[position] == NULL)
break;
signal = table[position]->first % divisor;//这个元素本该有的下标
if ((signal <= waitinsert &&waitinsert < position)
|| (signal <=waitinsert && position < signal)
|| (position < signal && waitinsert < position)){
table[waitinsert] = table[position];
table[position] = NULL;
waitinsert = position;
flag++;
}
} while(table[(position+ 1) % divisor]!= NULL&& position!= b);//不为空且未返回到原位置
cout << flag << endl;
}
}
int main(){
int D, m;
cin>>D;cin>>m;
HashTable<int, int> hashtable(D);
pair<int, int> q;
for (int i=0;i < m; i++) {
int op,number;
cin>>op;cin>>number;
if (op==0){
q.first = number; q.second = number;
hashtable.insert(q);
}
else if(op==1){
q.first = number; q.second = number;
hashtable.find(q.first);
}
else{
q.first=number;q.second=number;
hashtable.erase(q.first);
}
}
return 0;
}
#include<iostream>
using namespace std;
template<class K,class E>
struct pairNode{
//节点结构
typedef pair<const K,E> pairType;//为pair<const K,E>起个别名
pairType element;
pairNode<K,E> *next;
//构造节点
pairNode(const pairType& thePair):element(thePair){
}//记得要用这种形式的,否则报错
pairNode(const pairType& thePair,pairNode<K,E>*theNext):element(thePair){
//更新
this->next=theNext;
}
};
template<class K,class E>
class SortChain{
private:
pairNode<K,E>*firstNode;//指向第一个节点的指针
int dSize;//链表的数对个数
public:
SortChain():firstNode(NULL),dSize(0){
}
~SortChain();
void insert(const pair< K,E>& thePair);
void find(const K&theKey)const;//pair<const K,E>*是一种类型
void erase(const K&theKey);
int size() const {
return dSize;}
};
template<class K,class E>
SortChain<K,E>::~SortChain(){
pairNode<K,E>*nextNode;
while(firstNode!=NULL){
nextNode=firstNode->next;
delete firstNode;
firstNode=nextNode;
}
}
template<class K,class E>
void SortChain<K,E>::insert(const pair< K,E>& thePair){
pairNode<K,E> *p=firstNode;//pairnode类型的指针,指向firstnode
pairNode<K,E> *tp=NULL;
while(p!=NULL&&p->element.first<thePair.first){
tp=p; //为了待能在tp之后插入新节点会
p=p->next;
}
if(p!=NULL&&p->element.first==thePair.first){
//匹配到点
cout<<"Existed"<<endl;
return ;
}
//未找到匹配的
pairNode<K,E>*newNode=new pairNode<K,E>(thePair,p);//在p前立一个新节点
if(tp==NULL){
firstNode=newNode;
}else{
tp->next=newNode;
}
dSize++;
return ;
}
template<class K,class E>
void SortChain<K,E>::find(const K&theKey)const{
pairNode<K,E>*currentNode=firstNode;//指向现有头节点的指针
while(currentNode!=NULL&¤tNode->element.first!=theKey){
currentNode=currentNode->next;
}
if(currentNode!=NULL&¤tNode->element.first==theKey){
//匹配到了
cout<<dSize<<endl;
return ;
}
//未匹配到
cout<<"Not Found"<<endl;
return ;
}
template<class K,class E>
void SortChain<K,E>::erase(const K&theKey){
pairNode<K,E> *p=firstNode;
pairNode<K,E> *tp=NULL;
while(p!=NULL&&p->element.first<theKey){
tp=p;
p=p->next;
}
if(p!=NULL&&p->element.first==theKey){
if(tp==NULL){
firstNode=p->next;
}else{
tp->next=p->next;
}
delete p;
dSize--;
cout<<dSize<<endl;
}else{
cout<<"Delete Failed"<<endl;
}
}
template<class K>
class Hash;
template<>
class Hash<int>{
//将theKey映射,方法为其本身
public:
size_t operator()(const int theKey) const{
return size_t(theKey);
}
};
template<class K,class E>
class HashChain{
protected:
SortChain<K,E>*table;//链表型数组
int divisor;//位置数
Hash<K>hash;//把类型K映射到一个非负整数
int dSize;//整个系统的数对个数
public:
HashChain(int theDivisor=10);
~HashChain(){
delete []table;};
void find(const K&theKey)const;
void insert(const pair<const K,E>& thePair);
void erase(const K&theKey);
};
template<class K,class E>
HashChain<K,E>::HashChain(int theDivisor){
divisor=theDivisor;
dSize=0;
table=new SortChain<K,E>[divisor];//SortChain<K,E>型的数组
}
template<class K,class E>
void HashChain<K,E>::find(const K&theKey)const{
table[hash(theKey)%divisor].find(theKey);
}
template<class K,class E>
void HashChain<K,E>::insert(const pair<const K,E>& thePair){
int Arrayindex=(int)hash(thePair.first)%divisor;//先找数组对应的格子
int Listsize=table[Arrayindex].size();//这个格子的链表的长度
table[Arrayindex].insert(thePair);
if(table[Arrayindex].size()>Listsize)//代表插进去的不是重复的,因此总数加一
dSize++;
}
template<class K,class E>
void HashChain<K,E>::erase(const K&theKey){
table[hash(theKey)%divisor].erase(theKey);
}
int main(){
int D,m;
cin>>D;cin>>m;
HashChain<int,int> H(D);
pair<int,int> q;
for(int i=0;i<m;i++){
int op,x;
cin>>op;cin>>x;
if(op==0){
q.first=x;q.second=x;
H.insert(q);
}else if(op==1){
q.first=x;q.second=x;
H.find(q.first);
}else if(op==2){
q.first=x;q.second=x;
H.erase(q.first);
}
}
}