7-15 航空公司VIP客户查询(哈希表的链表实现)

不少航空公司都会提供优惠的会员服务,当某顾客飞行里程累积达到一定数量后,可以使用里程积分直接兑换奖励机票或奖励升舱等服务。现给定某航空公司全体会员的飞行记录,要求实现根据身份证号码快速查询会员里程积分的功能。

输入格式:

输入首先给出两个正整数N(≤105)和K(≤500)。其中K是最低里程,即为照顾乘坐短程航班的会员,航空公司还会将航程低于K公里的航班也按K公里累积。随后N行,每行给出一条飞行记录。飞行记录的输入格式为:18位身份证号码(空格)飞行里程。其中身份证号码由17位数字加最后一位校验码组成,校验码的取值范围为0~9和x共11个符号;飞行里程单位为公里,是(0, 15 000]区间内的整数。然后给出一个正整数M(≤105),随后给出M行查询人的身份证号码。

输出格式:

对每个查询人,给出其当前的里程累积值。如果该人不是会员,则输出No Info。每个查询结果占一行。

输入样例:

4 500
330106199010080419 499
110108198403100012 15000
120104195510156021 800
330106199010080419 1
4
120104195510156021
110108198403100012
330106199010080419
33010619901008041x

输出样例:

800
15000
1000
No Info

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

这个题首先告诉你,只要你懂了歪门邪道的念头大概率都会超时的哟,什么c++的map什么的,别问,问就是我试过,还是要老老实实的用哈希表来做吧,像这种大数据来说,最好不过了,还是老样子,提供c语言版(其实c++里面也有hash函数的,个人在网上查了一些但是搞不太懂,)

1.c语言版

#include <iostream>
#include <queue>
#include <algorithm>
#include <map>
#include <cstdio>
#define maxm 100005
using namespace std;

//看到网上的题解发现string在map中应用时间特别长,所以考虑将字符串转化为long long来看
/*
int main()
{
    map<string ,int> m;
    int n,l;
    cin>>n>>l;
    for(int i=0;i<n;i++)
    {
        string s;
        int x;
        cin>>s>>x;
        x=max(l,x);//最小值为l
        m[s]+=x;//注意可能有相同的
    }
    int k;
    cin>>k;
    while(k--)
    {
        string ss;
        cin>>ss;
        map<string,int>::iterator it=m.find(ss);//查找
        if(it!=m.end())//找到le
        {
            if(m[ss]<l)
                cout<<l<<endl;
            else
                cout<<m[ss]<<endl;
        }
        else
            cout<<"No Info"<<endl;
    }


    return 0;
}
*/
//哈希函数映射,取余10003
//单独构造一个哈希求键值的函数
//还需要单独创建一个单链表来表示身份证号用来找出相同的项进行合并
struct node{
   char s[20];
   int v;
   struct node *next;
   node(){v=0;next=NULL;}
};//哈希节点的构造
node h[maxm];

int Hash(char s[])//哈希转换函数
{
    int idx = 0,i;
    for( i = 0; i < 17; i++)
    {
        idx = (idx*10 + s[i]-'0')%10003;
    }
    if(s[i]=='x') idx = (idx*10 + 11)%10003;
    else idx = (idx*10 + s[i]-'0')%10003;
    return idx;

}
void add(int idx,char s[],int v)//向哈希表中添加节点并合并相同项
{
    int flag=0;//标记
    node *fp=&h[idx];
    node *sp=h[idx].next;
    while(sp)
    {
        if(!strcmp(sp->s,s))
        {
            sp->v+=v;
            flag=1;
            break;
        }
        fp=sp;
        sp=sp->next;
    }
    if(!flag)
    {
        fp->next=new node();
        strcpy(fp->next->s,s);//注意不能用c++的直接赋值会出错fp->next->s=s;
        fp->next->v=v;
    }
}
void find(char s[])//哈希查找
{
    int idx=Hash(s);
    node *fp=&h[idx];
    node *sp=h[idx].next;
    int flag1=0;
     while (sp)
    {
        if (strcmp(sp->s,s) == 0)
        {
            printf("%d\n", sp->v);
            flag1=1;
            break;
        }
        fp = sp;
        sp = sp->next;
    }
    if (!flag1)
        printf("No Info\n");

}
int main()
{
    int n,l;
    cin>>n>>l;
    char s[20];
    for(int i=0;i<n;i++)
    {
        int x;
        scanf("%s %d",s,&x);
        if(x<l)
            x=l;
        int m=Hash(s);
        add(m,s,x);
    }
    int k;
    scanf("%d",&k);
    for(int i=0;i<k;i++)
    {
        scanf("%s",s);
        find(s);
    }
    return 0;
}

其中具体的代码意思我再代码段中做了些注释,应该比较好理解,就不多做解释了,重点就在与不用map的话要将带字符串的记录保存下来,可以将字符串变为数字并且缩小来实现,还有就是注意哈希表的下标表示的就是字符串由哈希函数转换而来的值,而链表的创建可以保证在下标不连续的情况下得以连续遍历来确定有无相同项需要合并。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈希表是一种高效的数据结构,可以用来存储和查找键值对。其中,哈希函数将键映射到一个特定的桶中,每个桶中存储一组键值对。在哈希表中,如果两个键被映射到同一个桶中,就发生碰撞。为了解决这个问题,可以使用链表法。 链表法是一种解决哈希表碰撞问题的方法。具体来说,对于哈希表中的每个桶,可以使用一个链表来存储所有映射到该桶的键值对。如果发生碰撞,只需要将新的键值对添加到链表的末尾即可。 下面是一个使用链表实现哈希表的示例代码: ```python class Node: def __init__(self, key, value): self.key = key self.value = value self.next = None class HashTable: def __init__(self, capacity): self.capacity = capacity self.buckets = [None] * capacity def hash_function(self, key): return hash(key) % self.capacity def put(self, key, value): index = self.hash_function(key) node = self.buckets[index] while node: if node.key == key: node.value = value return node = node.next new_node = Node(key, value) new_node.next = self.buckets[index] self.buckets[index] = new_node def get(self, key): index = self.hash_function(key) node = self.buckets[index] while node: if node.key == key: return node.value node = node.next return None def remove(self, key): index = self.hash_function(key) node = self.buckets[index] prev = None while node: if node.key == key: if prev: prev.next = node.next else: self.buckets[index] = node.next return prev = node node = node.next ``` 在这个示例中,我们定义了一个Node类来表示哈希表中的每个节点,每个节点包含一个键、一个值和一个指向下一个节点的指针。我们还定义了一个HashTable类来实现哈希表,其中包含一个桶数组和一些基本的操作方法,如put、get和remove。 在put方法中,我们首先使用哈希函数计算出键的索引,然后遍历桶中的链表,查找该键是否已经存在于哈希表中。如果找到了该键,我们只需要更新其对应的值即可。否则,我们创建一个新的节点,并将其添加到链表的开头。 在get方法中,我们同样使用哈希函数计算出键的索引,然后遍历桶中的链表,查找该键的值。如果找到了该键,我们返回其对应的值。否则,返回None。 在remove方法中,我们首先使用哈希函数计算出键的索引,然后遍历桶中的链表,查找该键。如果找到了该键,我们将其从链表中删除即可。 总的来说,链表法是一种简单且常用的哈希表解决碰撞问题的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值