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

来源:互联网 发布:秋冬季棉拖鞋淘宝 编辑:程序博客网 时间:2024/06/05 20:17

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

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

输入格式:

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

输出格式:

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

输入样例:

4 500330106199010080419 499110108198403100012 15000120104195510156021 800330106199010080419 1412010419551015602111010819840310001233010619901008041933010619901008041x

输出样例:

800150001000No Info
大体思路:
建立一个不占多少内存但是又很巨量的指针数组
然后采用 身份证号处理 第6,10,14,16,17,18位 转换为哈希地址
然后将每个身份证号插入哈希链表(指针数组)
代码如下:
#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>#define MAX 200000typedef 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;}
原创粉丝点击