您的位置:首页 > 编程语言 > C语言/C++

哈希算法 C语言实现(采用链表)

2017-12-05 22:27 155 查看


7-16 航空公司VIP客户查询(25 分)

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


输入格式:

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


输出格式:

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


输入样例:

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


输出样例:

800
15000
1000
No Info

大体思路:

建立一个不占多少内存但是又很巨量的指针数组

然后采用 身份证号处理 第6,10,14,16,17,18位 转换为哈希地址

然后将每个身份证号插入哈希链表(指针数组)

代码如下:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define MAX 200000
typedef struct Node * Hash;/** 哈希链表中的小单元**/
struct Node{
    char arr[20]; // 身份证号
    int fen; // 积分
    Hash next; // 下一个单元 没有的话是NULL
};
int deal(char *arr) /**处理身份证号**/
{
    int idex;
    idex = (arr[5]-'0')*10000+(arr[9]-'0')*1000+(arr[13]-'0')*100+(arr[15]-'0')*10+(arr[16]-'0');
    if(arr[17]=='x') idex = idex*10+10;
    else idex = idex*10 + (arr[17]-'0');
    return idex;
}
int nextprime(int N)  /**需要一个(大于总数N的又是最小的)素数 为了是以此大小建立哈希链表后 链表不一定塞满但是查找的效率会提高不少**/
{
    int i,p=(N%2)?N+2:N+1;
    while(p<MAX)
    {
        for(i=(int)sqrt(N);i>=2;i--)
            if(!(p%i)) break;
        if(i<2) break; //是素数 返回
        else p+=2;    //不是的话就找下一个奇数
    }
    return p;
}
Hash insert(Hash h,int x,char *s) /** 哈希链表的插入 **/
{
    Hash p =h;
    while(p) /**先看看是不是空指针**/
    {
        /**看样子是**/
        if(strcmp(p->arr,s)==0)   /**再看看身份证号是不是已经存在了**/ 
        {
            p->fen+=x;
            return h;
        }
        else p=p->next; /** 下一个小单元 如果最后没有了 会是NULL 循环会结束**/
    }
    /**然后我i们知道 指针为空,或者此指针指的小链表中没有此身份证号**/
    p= (Hash)malloc(sizeof(struct Node)); /**那就建立一个**/
    strcpy(p->arr,s); 
    p->fen=x;
    p->next=h; /**链表的头节点插入的写法,在此处比较方便**/
    return p;  /**返回新建的节点(此节点的next已经指向了原h所指的东西)给h 毕竟 给拿走了,得把自己和拿走的一起交回去了**/
}
void display(Hash h,char *s) /**输入链表的符合条件的身份证号**/
{
    while(h)
    {
        if(strcmp(h->arr,s)==0)
        {
            printf("%d\n",h->fen);
            return;
        }
        h=h->next;
    }
    printf("No Info\n");
}
int main(){
    int n,k;
    scanf("%d %d\n",&n,&k);
    int p= nextprime(n);
    Hash *h = (Hash*)malloc(p*sizeof(Hash)); /**这就是那不占内存 又可以超级多的 指针数组 此处 h是指针的指针,其实可以当指针数组的名字**/
    int i;
    for(i=0;i<p;i++) /**初始化指针数组**/
    {
        h[i]=NULL;
    }
    int x,idex;     /**然后剩下的就没啥难度了**/
    char arr[20];
    while(n--)
    {
        scanf("%s %d\n",arr,&x);
        if(x<k) x=k;
        idex = deal(arr)%p;
        h[idex] = insert(h[idex],x,arr);
    }
    int m;
    scanf("%d\n",&m);
    while(m--)
    {
        scanf("%s",arr);
        idex = deal(arr)%p;
        display(h[idex],arr);
    }
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: