本程序可以适用于
icoding的数据结构并没有一个测试代码,其都是直接编写一个函数的形式,因此很难知道自己的实际输出是什么。针对部分题目,我编写了一系列测试代码以供大家进行数据输出的测试。
HashTable* create_hash(int size){ //TODO } HASH_RESULT hash_add_int(HashTable *table, const char *key, int value){ //TODO }
请将您的函数代码复制到上述函数中,然后修改main函数的相关内容,完成测试样例的输入
请注意,对于hash表添加:在添加过程中,如果要添加的键值key已在哈希表中,且对应的值value也已存在,则函数返回 HASH_ALREADY_ADDED;如果要添加的键值key已在哈希表中,但对应的值value不同,则函数将value值更新到哈希表中,之后返回 HASH_REPLACED_VALUE;如果要添加的键值key不在哈希表中,则函数创建 HashEntry 类型,并将其加入到哈希表中,且函数返回 HASH_ADDED。
哈希函数
long hash_string(const char *str)
{
long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
if(hash < 0)
hash *= -1;
return hash;
}
已经实现并且已经添加到下方的代码中。
———————————————————————————————————————————
如果插入后打印链表为空链表,且插入操作正确。说明您对hash_string函数返回值处理错误
#include<stdio.h>
#include<stdbool.h>
#include<string.h>
#include <stdlib.h>
typedef enum{
HASH_OK,
HASH_ERROR,
HASH_ADDED,
HASH_REPLACED_VALUE,
HASH_ALREADY_ADDED,
HASH_DELETED,
HASH_NOT_FOUND,
} HASH_RESULT;
typedef struct __HashEntry HashEntry;
struct __HashEntry{
union{
char *str_value;
double dbl_value;
int int_value;
} key;
union{
char *str_value;
double dbl_value;
int int_value;
long long_value;
void *ptr_value;
} value;
HashEntry *next;
};
struct __HashTable{
HashEntry **bucket;
int size;
HASH_RESULT last_error;
};
typedef struct __HashTable HashTable;
long hash_string(const char *str)
{
long hash = 5381;
int c;
while ((c = *str++) != 0)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
//hash表添加
//打印hash表
void print_hash(HashTable *table){
int i;
for(i=0;i<table->size;i++){
HashEntry *p = table->bucket[i];
if(i>=10)printf("[%d]| ",i);
else{
printf("[0%d]| ",i);
}
if(p==NULL) printf("^ ");
while(p!=NULL){
if(p->next!=NULL){
printf("%d(%s)-> ", p->value.int_value, p->key.str_value);
p = p->next;
}
if(p->next==NULL){
printf("%d(%s) ^ ", p->value.int_value, p->key.str_value);
p = p->next;
}
}
putchar('\n');
}
}
//----------以上为辅助函数-----------------
HashTable* create_hash(int size){
//TODO
}
HASH_RESULT hash_add_int(HashTable *table, const char *key, int value){
//TODO
}
int main(){
//----------------以 下 内 容 可 修 改-----------------
int size=10;//hash表大小,可修改,需要是正整数
bool print_empty_table=true;//是否打印空表?true:打印,false:不打印
//用以判断初始化是否正确
bool flag = true;//是否测试添加函数hash_add_int?true:测试,false:不测试
//若初始化函数错误,请勿进行相关测试
int val[]={1,2,3,4,1,1,258};//要添加的数据的value
char key[][7]={"a","bb","ccc","dddd","k","a","bb"};//要添加的数据的key
//注意key为字符串!所以需要用双引号引起
//key的第二个数据需要手动填写,内容为字符串总个数
//key的第二个数据需要手动填写,内容为字符串总个数
//key的第二个数据需要手动填写,内容为字符串总个数
//key的第二个数据需要手动填写,内容为字符串总个数
//程序会将相同下标的val和key视为一组,比如("a",1)是一组
//保证两个数组的长度相同(程序会检测)
//程序会循环添加数据,直到添加成功为止。可以依次查看hash_add_int函数是否正确。
//----------------以 上 内 容 可 修 改-----------------
printf("icoding\nHash Table\n");
printf("*提示* 本题hash_add_int的val为int类型,key为字符串;本题添加函数需要对key相同和val相同的数据进行替换操作,请仔细审题\n----开始测试----\n");
if(size<=0){
printf("size值必须为大于0的正整数,请修改main函数的size值\n程序自动终止,请修改\n");
return -1;
}
int len1 = sizeof(val)/sizeof(int);
//定义len2,统计key的字符串个数
int len2 = sizeof(key)/sizeof(key[1]);
if(len1!=len2){
printf("数组长度不一致,其中val长度为%d,key长度为%d,请检查\n程序自动终止,请修改源代码\n",len1,len2);
return 0;
}
printf(">>创建hash表,将创建%d个空位\n",size);
HashTable *table = create_hash(size);
if(table==NULL){
printf("创建hash表失败,返回值为NULL\n程序自动终止,请修改源代码\n");
return 0;
}else if(table->bucket==NULL){
printf("创建hash表失败,table->bucket为NULL\n程序自动终止,请修改源代码\n");
return 0;
}
else if(table->size!=size){
printf("您的hash表的table->size值为%d,正确应该为%d,赋值错误\n请检查是否正确赋值\n程序自动终止,请修改源代码\n",table->size,size);
return 0;
}else{
printf("创建hash表成功\n·table->bucket地址为 %p \n·table->size 大小为 %d\t [%s]\n",table->bucket,table->size,size==table->size?"赋值正确":"赋值错误,请检查!");
}
if(print_empty_table){
printf("\n···打印空的hash表···\n");
print_hash(table);
}
printf("\n\n");
if(flag){
printf(">>添加元素\n");
printf("下方会显示添加的结果\n添加成功不显示,序号从0开始,若不显示请检测是否正确返回值\n-------------------------------------------------\n");
printf("序号\t[状 态]\tKey\tVal\t 说明\n");
bool is_print=false;//是否输出了错误数据?
for(int i=0;i<len1;i++){
HASH_RESULT result = hash_add_int(table,key[i],val[i]);
//hash_add_int(table, key[i], val[i]);
if(result==HASH_ALREADY_ADDED){
printf("%d\t[已存在]\t%s\t%d\t重复添加val和key相同的数据\n",i,key[i],val[i]);
is_print=true;
}
else if(result==HASH_ERROR){
is_print=true;
printf("%d\t[失 败]\t%s\t%d\t函数返回ERROR,可能无法开辟空间\n",i,key[i],val[i]);
}else if(result==HASH_REPLACED_VALUE){
is_print=true;
printf("%d\t[值替换]\t%s\t%d\t键相同,值不同,替换成最新值\n",i,key[i],val[i]);
}
else{
continue;
}
}
if(!is_print){
printf("\n ····所有数据均正确插入,函数未返回错误···· \n\n");
}
printf("-------------------------------------------------\n···打印hash表···\n^表示空或终止,数字代表Val值,()内表示key值。val为int类型,key为字符串\n");
print_hash(table);
}
else{
printf("您未进行添加元素的函数运行,若需要请修改main函数的flag");
}
printf("\n");
printf("本程序仅用于可视化输出,不进行正确与错误的准确判断\n----测试结束----\n");
return 0;
}
如果不对函数内置测试样例进行更改,那么将有以下输出
解释:【"a",1】插入两次,为重复插入。只进行一次。【"bb",1】【"bb",258】两组数据先后被输入,他们的key相同,但value不同,替换为最新的。【"k",1】【"a",1】key不同,因此不替换正常插入,但由于hash相同,链接在同一个bucket里面。