哈希值的获取字符串的二进制,再二进制转换为一组数字,这组数字就是用来确定key在哪个桶层中的
代码中 #define tongsize 8 //桶大小是2的n次方,,,,,这里的n=3(2的3次方等于8),那么会把3个二进制转换为一个数字
/* 当重新分配还是分配到一个桶层时候,会出现哈希key不够用,就会出现引用了无效内存的bug,所以使用more_ceng arr[j]=strtol( bi, NULL, 2);//把二进制字符串bi转换为十进制 测试数据 set 电风 111 set 风 set 赋给 22 set 4风 33 set 4 44 set 5 55 set a 66 set c 77 set x 88 set ww 放了 set qq 撒解放了 set e 解放了 set yy 旦解放了 set ii 撒 get 电风 get 风 get 4风 get 4 get 5 get a get c get x get ww get qq get e get yy get ii */ #include<conio.h> #include<math.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #define tongsize 8 //桶大小是2的n次方 #define VALUESIZE 3 //值链表的长度 //---------------------------------------------------------------------------// typedef struct value *value_pointer; //值的结构体 typedef struct value { char key[10]; char zhi[20]; value_pointer link; }value; typedef struct zitong *zitong_pointer;//桶的结构体 typedef struct zitong { int biao_tong; /*0 is 指向值 , 非0 则是指向一个子桶*/ int geshu;//值的个数 value_pointer value_link; zitong_pointer zitong_link; }zitong; zitong tong[tongsize]; int ceng=1;//层次深度,分配桶的时候,可能ceng加+1 //---------------------------------------------------------------------------// zitong_pointer init_tong(int biaoceng);//分配和初始化桶,可以改为内存直接付0 value_pointer init_value();//分配值的空间 int binarystring(char c,char*bite,int j,int bite_len);//返回二进制 int* bitetoarr(char* bite,int bishu,int more_ceng) ;//比特转换为数字 int* hash_key(char *key);//返回哈希key,key转为比特,比特再转为数字数组 void ret_fenpei(value_pointer a,zitong_pointer b,int now_ceng);//a值,b是桶,c是层次 value_pointer set_find(zitong_pointer root_arr,int pre_biao_tong, int*hk,int now_ceng);//hk是key的哈希值 void set(zitong_pointer root_arr,int pre_biao_tong); value_pointer get_find(zitong_pointer root_arr, int*hk,int now_ceng,char* key);//hk是key的哈希值 void getvalue(zitong_pointer root_arr); //---------------------------------------------------------------------------// void main() { zitong root;//根小桶 root.biao_tong=1;//表示指向的子桶 root.zitong_link = init_tong(root.biao_tong); printf("请输入 set如set key value. get如get key;quit退出\n"); char caozuo[10]; int sel; do{ scanf("%s",&caozuo); if (strcmp(caozuo,"set")==0) sel=1; else if (strcmp(caozuo,"get")==0) sel=2; else if (strcmp(caozuo,"look")==0) sel=3; else if (strcmp(caozuo,"quit")==0) sel=0; else sel=-1; switch(sel) { case 0:printf("\t\t\t^-^再见!^-^ \t\t\t\n");system("pause");break; case 1: set(root.zitong_link,root.biao_tong);break; case 2:getvalue(root.zitong_link);printf("\n\n");break; //case 3:look();printf("\n");break; default: printf("请输入正确的选项号!");printf("\n\n");break; } }while(sel!=0); } zitong_pointer init_tong(int biaoceng) //分配和初始化桶,可以改为内存直接付0 { zitong_pointer t; t=(zitong_pointer)malloc(sizeof(zitong)*tongsize); int i; for(i=0;i<tongsize;i++) { t[i].biao_tong=0; t[i].geshu=0; t[i].value_link=NULL; t[i].zitong_link=NULL; } if (biaoceng > ceng)//当这个桶的深度大于当前最大深度时,ceng才+1 ceng++;// return t; } value_pointer init_value()//分配值的空间 { value_pointer v; v=(value_pointer)malloc(sizeof(value)); v->link=NULL; return v; } int binarystring(char c,char*bite,int j,int bite_len)//获取一个字符的二进制 { int i; for(i=0;i<8;i++) { if(j*8+i >=bite_len)return 1;//二进制足够了 if (c & 0x80) bite[j*8+i]='1'; else bite[j*8+i]='0'; c <<= 1; } return 0; } int* hash_key(char *key)//返回哈希key,key转为比特,比特再转为数字数组 { //字符串key的长度乘以8就得到比特长度 int more_ceng=ceng+3;//加多越多越安全 int len =strlen(key);//字符串长度 int bishu=(int)(log10(tongsize)/log10(2)) ;//使用bishu个比特来确定一个数字 int bite_len=bishu*more_ceng;//刚开始是3*1=3 char *bite=(char*)malloc(bite_len);//申请存放01110011的字符串 for (int i = 0; i < len; ++i)//把字符转换为比特 if(binarystring(key[i],bite,i,bite_len) == 1)break; int bite_len_now=strlen(bite);//0011010字符串的长度 while(1)//使得二进制足够长 { int k=0; if (bite_len_now < bite_len){ bite[bite_len_now+k]=bite[k]; ++k; } else break; } int* arr= bitetoarr(bite,bishu,more_ceng);//比特转换为数字 free(bite); return arr; } int* bitetoarr(char* bite,int bishu,int more_ceng) //比特转换为数字 { int *arr; char bi[10]={0}; arr=(int *)malloc(sizeof(int)*more_ceng);//刚开始是1 for (int j = 0; j < more_ceng; ++j) { bi[0]=bite[j*bishu+0];//bite数组的中10010110 bi[1]=bite[j*bishu+1]; bi[2]=bite[j*bishu+2]; arr[j]=strtol( bi, NULL, 2); } return arr; } void ret_fenpei(value_pointer a,zitong_pointer b,int now_ceng)//a值,b是桶,c是层次 { int* fen_hk=hash_key(a->key); a->link=b[ fen_hk[now_ceng] ].value_link;//连接后面的 b[ fen_hk[now_ceng] ].value_link=a;//连接到头部 b[ fen_hk[now_ceng] ].geshu++;//个数加+1 free(fen_hk); } value_pointer set_find(zitong_pointer root_arr,int pre_biao_tong, int*hk,int now_ceng)//hk是key的哈希值 { //key是否存在 //在哪个子桶 //得先判断key是否存在了 分1对应的子桶无值 2.扫描链表 //不存在 分1添加到链表的头部 2.值满了,申请新的桶再分配 if (now_ceng>=ceng) printf("error now_ceng is over"); zitong_pointer here=&root_arr[ hk[now_ceng] ];//达到桶的层次节点 int biaoji;//桶的标记,子桶或是值,非0表示桶的层次 biaoji=here->biao_tong; value_pointer vp; if (0==biaoji)//子桶指向链表值 { if(VALUESIZE > here->geshu)//子桶无值或者子桶有值,并且小于链的长度 { value_pointer vp=init_value();//申请空间 vp->link=here->value_link;//连接后面的 here->value_link=vp;//连接到头部啊 here->geshu++;//值的个数加+1 return vp; } else//子桶的值达到VALUESIZE { value_pointer temp2; value_pointer temp=here->value_link;//把链表拿出来 here->biao_tong=pre_biao_tong+1;//子桶标记 here->zitong_link=init_tong(here->biao_tong);//========分配新的子桶 while(temp != NULL)//循环递归重新在新子桶上分配 { temp2=temp->link; ret_fenpei(temp,here->zitong_link,now_ceng+1);//递归重新分配 temp=temp2; } vp=set_find(here->zitong_link,here->biao_tong,hk,now_ceng+1);//就在新的子桶中寻找了,由hk[now_ceng+1]子哈希确定新子桶的桶层次 return vp; } } else//说明子桶指向子桶,//进入子桶中寻找了,由hk[now_ceng+1]子哈希确定子桶的桶层次 { vp=set_find(here->zitong_link,here->biao_tong,hk,now_ceng+1); return vp; } } value_pointer get_find(zitong_pointer root_arr, int*hk,int now_ceng,char* key)//hk是key的哈希值 { //在哪个子桶层 //得先判断key是否存在了 分1对应的子桶无值 2.扫描链表 //不存在 分1添加到链表的头部 2.值满了,申请新的桶再分配 if (now_ceng>=ceng) printf("error now_ceng is over"); zitong_pointer here=&root_arr[ hk[now_ceng] ];//达到桶的层次节点 int biaoji;//桶的标记,子桶或是值,非0表示桶的层次 biaoji=here->biao_tong; value_pointer vp; vp=here->value_link; if (0==biaoji)//子桶指向链表值 { while(vp != NULL) { if (0 == strcmp(vp->key,key) ) return vp; vp=vp->link; } return NULL; } else//说明子桶指向子桶, { vp=get_find(here->zitong_link,hk,now_ceng+1,key);//进入子桶中寻找了,由hk[now_ceng+1]子哈希确定子桶的桶层次 return vp; } } void set(zitong_pointer root_arr,int pre_biao_tong) { char key[10],zhi[20]; int* hk; value_pointer p; scanf("%s %s",&key,&zhi); hk=hash_key(key); p=get_find(root_arr,hk,0,key);//是否已经存在相同的key了 if (p ==NULL)//说明不存在节点 p=set_find(root_arr,pre_biao_tong,hk,0);//发现点 strcpy(p->key,key); strcpy(p->zhi,zhi); free(hk); } void getvalue(zitong_pointer root_arr) { char key[10]; int* hk; value_pointer p; scanf("%s",&key); hk=hash_key(key); p=get_find(root_arr,hk,0,key);//发现点 if (p==NULL) printf("no key to value"); else printf("%s",p->zhi); free(hk); }
时间: 2024-10-19 13:19:02