魔咒词典 - HDU 1880 hash表

本文介绍了一个C语言实现的自定义HashMap数据结构,用于高效地进行键值对查询。通过使用两个独立的HashMap,分别以键和值作为索引,实现了双向查找功能。文章详细解释了数据结构的设计思路,包括节点结构、哈希函数和搜索算法,并提供了完整的代码示例。

OJ:http://acm.hdu.edu.cn/showproblem.php?pid=1880

 

题意还是非常的清楚,给你一个键值对,需求是给出k的时候,查出v,给你v的时候,查出k。还要注意的是,输出结果的时候,k中的[]是不会被输出的,但是查询的时候给出的k是包含[]的,且题中说明了魔咒个和字符串中都不会包含[]这两个字符。

 

解析:

其实这个题,使用有标准库的语言非常好实现,只是c语言没有,就稍微麻烦一点。

因为这是结题,我们完全没有必要去写一个动态的链式结构的HashMap,因为题目中说明了数量,所以我们只需要一次性开足够的空间就可以,要一次性开足够的空间就不能使用链表了,直接使用数组结构来替代链表。

之前的设想是直接使用一个hashmap,对k和v分别作为键值存一次,但是这样直接导致了空间不够,后来就改成了两个HashMap,两个map一个以k为键,一个一v为键。

 

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define MAX 100010

// map的node
typedef struct{
    char c[25];
    char f[85];
    // 因为使用的是数组来充当链式结构,所以这里的next指向的是下一个node的坐标
    int next;
}Node;

// 一个map,以k作为键,v作为值
Node n1[MAX];
// 一个mao,以v作为键,k作为值
Node n2[MAX];

// 保存某一个hash值的链在n1数组中开始位置,然后n1数组中的node会将该hash值下的所有node连接起来
// 这个主要就是一个开始作用
int hIndex1[MAX];
int hIndex2[MAX];

// n1中待使用空间的开始下标
int curIndex1 = 0;
int curIndex2 = 0;

void init(){
    memset(hIndex1,-1,sizeof(hIndex1));
    memset(hIndex2,-1,sizeof(hIndex2));
    for(int i=0;i<MAX;i++){
        n1[i].next = -1;
        n2[i].next = -1;
    }
}

int hashcode(char *s){
    int seed = 131;
    int hash = 0;
    while(*s){
        hash = hash*seed + *s++;
    }
    return (hash&0x7fffffff);
}


void push(char *c,char *f){
    strcpy(n1[curIndex1].c,c);
    strcpy(n1[curIndex1].f,f);
    int hash = hashcode(c)%MAX;
    // 新的node直接放在链的开始位置
    n1[curIndex1].next = hIndex1[hash];
    // hIndex中保存的是新node的index
    hIndex1[hash] = curIndex1++;

    strcpy(n2[curIndex2].c,c);
    strcpy(n2[curIndex2].f,f);
    hash = hashcode(f)%MAX;
    n2[curIndex2].next = hIndex2[hash];
    hIndex2[hash] = curIndex2++;
}

int search1(char *c){
    int hash = hashcode(c)%MAX;
    if(hIndex1[hash] == -1){
        return -1;
    }
    int index = hIndex1[hash];
    for(;index!=-1;){
        if(!strcmp(n1[index].c,c)){
            return index;
        }
        index = n1[index].next;
    }
    return -1;
}

int search2(char *f){
    int hash = hashcode(f)%MAX;
    if(hIndex2[hash] == -1){
        return -1;
    }
    int index = hIndex2[hash];
    for(;index!=-1;){
        if(!strcmp(n2[index].f,f)){
            return index;
        }
        index = n2[index].next;
    }
    return -1;
}


int main(){
    init();
    char k[25],v[105];
    char line[150];
    for(;1;){
        gets(line);
        if(line[0] == '@'){
            break;
        }
        int len = strlen(line);
        int i=0;
        for(;i<len;i++){
            if(line[i] ==']'){
                k[i] = line[i];
                break;
            }
            k[i] = line[i];
        }
        k[++i] = 0;
        int p = 0;
        for(i=i+1;i<len;i++){
            v[p++] = line[i];
        }
        v[p] = 0;
        push(k,v);
    }
    int count;
    scanf("%d", &count);
    getchar();
    for(;count>0;count--){
        gets(line);
        int index;
        if(line[0] == '['){
            index = search1(line);
            if(index!=-1){
                printf("%s\n",n1[index].f);
            }else{
                printf("what?\n");
            }
        }else{
            index = search2(line);
            if(index!=-1){
                int len = strlen(n2[index].c);
                int i = 1;
                for(;i<len-1;i++){
                    v[i-1] = n2[index].c[i];
                }
                v[i-1] = '\0';
                printf("%s\n",v);
            }else{
                printf("what?\n");
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值