C++实现Hash表

来源:互联网 发布:asp.net是编程语言吗 编辑:程序博客网 时间:2024/05/16 13:55

C++实现Hash表的插入,删除,重建开放寻址法

#include<iostream>  
using namespace std;  
  
typedef int KeyType; //设关键字域为整形,需要修改类型时,只需修改这里就可以  
const int NULLKEY=0; //NULLKEY表示该位置无值  
int c=0; //用来统计冲突次数  
  
struct Elemtype //数据元素类型  
{  
    KeyType key;  
    int ord;   
};  
  
int hashsize[]={11,19,29,37,47}; //hash表容量递增表  
int Hash_length=0;//hash表表长  
  
class HashTable  
{  
private:  
    Elemtype *elem; //数据元素数组,动态申请  
    int count;// 当前数据元素个数  
    int size; //决定hash表的容量为第几个,hashsize[size]为当前hash容量  
public:  
  
    int Init_HashTable() //构造一个空hash表  
    {  
        int i;  
        count=0;  
        size=0; //初始化容量为hashsize[0]=11  
        Hash_length=hashsize[0];  //初始的hash表的容量是11
        elem=new Elemtype[Hash_length];  
        if(!elem)  
        {  
            cout<<"内存申请失败"<<endl;  
            exit(0);  
        }  
        for(i=0;i<Hash_length;i++)  //初始化hash表,每个元素都是NULLKEY
            elem[i].key=NULLKEY;  
        return 1;  
    }  
  
    ~HashTable()  //析构函数
    {  
        delete[]elem;  
        elem=NULL;  
        count=0;  
        size=0;  
    }  
  
    unsigned Hash(KeyType k) //选取hash函数的一种(取模法,模为hash表的长度)  
    {  
        return k%Hash_length;  
    }  
  
    void Collision(int &p,int d) //解决冲突  
    {  
        
p=(p+d)%Hash_length; //采用开放地址法里的线性探测法来解决冲突
    }  
  
    bool Search_Hash(KeyType k,int &p) //查找  
    {  
        //在开放地址hash表中查找关键字等于k的元素  
        //若找到用p表示待查数据的地址标号 
        c=0;  
        p=Hash(k); //求hash地址  
        while(elem[p].key!=NULLKEY && elem[p].key!=k&&c<Hash_length)  //遇到空巢或者超过表容量或者已经找到循环终止
        {  
                    c++;  
                Collision(p,c);  
        }  
        if(elem[p].key==k)  //如果查找成功返回1
            return 1;  
        else  
            return 0;  
  
    }  
  
    int Insert_Hash(Elemtype e) //插入  
    {  
        //在查找不成功的情况下将k插入到hash表中  
        int p; int c=0;
int Hash_length=hashsize[0]; 
        if(Search_Hash(e.key,p))  
            return -1; //表示该元素已在hash表中  
else 
        {  
while(c<Hash_length)
{
int j= (Hash(e.key)+c)%Hash_length;
if(elem[j].key==NULLKEY)
{
            elem[p]=e;  
            count++;  
            return 1;  
}
c++;
}
               return 0;
        //原来的hash表溢出时,需要扩大hash表的容量再插入
if(c=Hash_length)
            ReCreate_HashTable(); // 重建hash表,把输入插入到表中  
}
}  
  
    void ReCreate_HashTable() //重建hash表  
    {  
        int i,count2=count;  
        Elemtype *p,*elem2=new Elemtype[count];  
        p=elem2;  
        cout<<"____重建hash表_____"<<endl;  
        for(i=0;i<Hash_length;i++) //将原有元素暂存到elem2中  
            if(elem[i].key!=NULLKEY)  
                *p++=*(elem+i);  
        count=0;
delete []elem;  //清空elem中的元素
        size++; //hash容量增大  
        Hash_length=hashsize[size];  
        Elemtype *q=new Elemtype[Hash_length];  
        if(!q)  
        {  
            cout<<"空间申请失败"<<endl;  
            exit(0);  
        }  
        elem=q;  //原来的elem表变大了,用了新的表长度
        for(i=0;i<Hash_length;i++)  
            elem[i].key=NULLKEY;  
        for(p=elem2;p<elem2+count2;p++) //将原有元素依次插入到elem表中
            Insert_Hash(*p);  

    }  
  
    void Traverse_HashTable()  
    {  
        cout<<"哈希地址0->"<<Hash_length-1<<endl;  
        for(int i=0;i<Hash_length;i++)  
            if(elem[i].key!=NULLKEY)  
                cout<<"元素的关键字值和它的标志分别是:"<<elem[i].key<<"  "<<elem[i].ord<<endl;  
  
    }  
  
    void Get_Data(int p)  
    {  
        cout<<"元素的关键字值和它的标志分别是:"<<elem[p].key<<"  "<<elem[p].ord<<endl;  
    }  
      
};  
int main()  
{  
    Elemtype r[12]={{17,1},{60,2},{29,3},{38,4},{1,5},{2,6},{3,7},{4,8},{5,9},{6,10},{7,11},{6,12}};  
    HashTable H;  
    int i,p,j;  
    KeyType k;  
    H.Init_HashTable();  //初始化hash表,能装11个元素
    for(i=0;i<11;i++) //插入前11个记录  
    {  
        j=H.Insert_Hash(r[i]);  
        if(j==-1)  
            cout<<"表中已有关键字为"<<r[i].key<<"  "<<r[i].ord<<"的记录"<<endl;  
    }  
  
    cout<<"按哈希地址顺序遍历哈希表"<<endl;  
    H.Traverse_HashTable();  
    cout<<endl;  
  
    cout<<"输入要查找的记录的关键字:";  
    cin>>k;  
    j=H.Search_Hash(k,p);  
    if(j==1)  
        H.Get_Data(p);  
    else  
        cout<<"无此记录"<<endl;  
  
    j=H.Insert_Hash(r[11]); //插入一个元素
    if(j==0)  
    {  
        cout<<"插入失败"<<endl;  
        cout<<"需要重建哈希表才可以插入"<<endl;  
        cout<<"____重建哈希表____"<<endl;  
        H.Insert_Hash(r[i]); //重建后重新插入  
    }  
if(j==-1)
{
cout<<"hash表中已经有这个值"<<endl;
}
  
    cout<<"遍历重建后的哈希表"<<endl;  
    H.Traverse_HashTable();  
    cout<<endl;  
  
    cout<<"输入要查找的记录的关键字:";  
    cin>>k;  
    j=H.Search_Hash(k,p);  
    if(j==1)  
        H.Get_Data(p);  
    else  
        cout<<"该记录不存在"<<endl;  
  
    return 0;  
}  

0 0