哈希表练习

来源:互联网 发布:c gui编程 编辑:程序博客网 时间:2024/04/30 11:17

#include<iostream>
#include<fstream>
#include<memory>
#include<math.h>

typedef unsigned __int64 Uint;

using namespace std;

struct Hash_elem{  //hash_table的元素
 Uint hash_key;
 int hash_value;
};

struct Hash_table
{
   Hash_elem *table;
   int count;
   int sizeindex;
};

unsigned int size_array[]={257,503,1009,2027,4073,8039,9973,20011,29989,41011,50587,62927,73877,84463,99991};//递增容量表
int hash_size=size_array[0];
int col;
int bits;
Uint pre;

Uint cbtoc(char* ch){
  Uint v=0;
  for(int i=0;i<bits;i++)
 {
  if(ch[i]=='1')
  v+=(1<<(bits-1-i));
 }
 return v;
}

unsigned int hash(Uint &v)  //哈希函数
{
 return v%hash_size;
}

void collision(unsigned int &p,int d) //冲突处理,线性探测增量
{
   p=(p+d)%hash_size;
}

void hash_init(Hash_table &H)//建立hash表

 col=0;
 H.count=0;
 H.table=(Hash_elem*)malloc(sizeof(Hash_elem)*hash_size);
 if(!H.table){
  cout<<"overflow";
  exit(0);}
 for(int i=0;i<hash_size;i++)
  H.table[i].hash_value=0;
}

void hash_search(Hash_table H,Uint Key,unsigned int &p)

 col=0;
 p=hash(Key);
 while(H.table[p].hash_value!=0 && Key!=H.table[p].hash_key)
 {
  col++;//冲突数+1
  if(col<hash_size)
   collision(p,col);
  else
   break;
 }
/* if(Key==H.table[p].hash_key)
  return 1;//key值相同
 else
  return 0;//可用的空hash值*/
}
void hash_insert(Hash_table& H,unsigned int& p,Uint& v)
{
 H.table[p].hash_value++;
 H.table[p].hash_key=v; 
 H.count++;
}

void get_bits();
void hash_resize(Hash_table& H)//自动扩充容量
{
 cout<<"resize!!!"<<endl;
 H.sizeindex++;
 hash_size=size_array[H.sizeindex];
}

void get_bits(Hash_table &H,ifstream &inf){
  unsigned int p;
 Uint v;
 char c;
 hash_init(H);
 H.sizeindex=0;
 while((c = inf.get())!= EOF) {
 if(c=='/n')              //到达换行符,吃掉
  continue;
 char ch[512];
 inf.putback(c);
 inf.get(ch,bits+1);
 if(strlen(ch)<bits) //尾数不足bits位,剔除
  continue;
 v=cbtoc(ch);
 cout<<hash(v)<<' ';
 printf("%I64u/n",v);
 hash_search(H,v,p);
 if(col>hash_size/2)
 { 
  free(H.table);//释放内存
  inf.seekg(0, ios_base::beg);//回到开头
  hash_resize(H);
  hash_init(H);
  continue;
 }
 else
  hash_insert(H,p,v);
 }
}

void get_bits2(Hash_table &H,ifstream &inf){
  unsigned int p;
 Uint v,v1;
 char c;
 hash_init(H);
 H.sizeindex=0;
 while((c = inf.get())!= EOF) {
 if(c=='/n')              //到达换行符,吃掉
  continue;
 char ch[512];
 inf.putback(c);
 inf.get(ch,bits+1);
 if(strlen(ch)<bits) //尾数不足bits位,剔除
  continue;
 v=cbtoc(ch);
 v1=v+(pre<<bits);
 pre=v;
 hash_search(H,v1,p);
 if(col>hash_size/2)
 { 
  free(H.table);//释放内存
  inf.seekg(0, ios_base::beg);//回到开头
  hash_resize(H);
  hash_init(H);
  continue;
 }
 else
  hash_insert(H,p,v1);
 }
}

int main(){
 double p_si;
 double si_h;
 double si_h0=0;
 double si_h1=0;
 Hash_table H;
 bool flag=0;
 cout<<"please input bits:"<<endl;
 cin>>bits;
 char chf[512];//第一个元素
 ifstream fin("D:/in.txt");
 fin.get(chf,bits+1);//第一个元素,特殊处理。。
 while(strlen(chf)<bits)
 {
  fin.get();
  fin.get(chf,bits+1);
 }
 Uint fv=cbtoc(chf);
 pre=fv;
 fin.seekg(0, ios_base::beg); 
 get_bits(H,fin);//读入hash table
 if(H.table[hash(fv)].hash_value==1)
  {
   H.table[hash(fv)].hash_value=0;
   flag=1;//剔除第一个元素标志
  }

 unsigned int hspre=hash_size;
 
 hash_size=size_array[0];
 fin.clear();
 fin.seekg(0, ios_base::beg);

 fin.get(chf,bits+1); //吃掉第一个
 while(strlen(chf)<bits)
 {
  fin.get();
  fin.get(chf,bits+1);
 }

 Uint judge=(1<<bits)-1;
 Hash_table H1; 
 get_bits2(H1,fin);
 for(int i=0;i<hspre;i++)
  if(H.table[i].hash_value)
  {
   double temp=0;
   for(int j=0;j<hash_size;j++)
    if((H.table[i].hash_key & H1.table[j].hash_key)==judge)
    {
     double p_sji=double(H1.table[j].hash_value)/double(H.table[i].hash_value);
                    temp+=(p_sji*(log(p_sji)/log(2)));
    }
   si_h1+=(p_si*temp);
   int temp1=H.table[i].hash_value;
//   cout<<hex<<H.table[i].hash_key<<dec<<'/t';
   printf("%I64u/t",H.table[i].hash_key);
   p_si=double(temp1)/double(H.count);
   si_h=log(temp1)/log(2);
   cout<<"H="<<si_h<<'/t'<<endl;//输出H
   si_h0+=(p_si*(log(p_si)/log(2)));
  
  }
 cout<<"H0="<<-si_h0<<endl;
 cout<<"H1="<<-si_h1<<endl;

 return 0;
}