哈希算法 C语言实现(采用链表)
2017-12-05 22:27
155 查看
7-16 航空公司VIP客户查询(25 分)
不少航空公司都会提供优惠的会员服务,当某顾客飞行里程累积达到一定数量后,可以使用里程积分直接兑换奖励机票或奖励升舱等服务。现给定某航空公司全体会员的飞行记录,要求实现根据身份证号码快速查询会员里程积分的功能。
输入格式:
输入首先给出两个正整数N(≤105)4000
和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
大体思路:
建立一个不占多少内存但是又很巨量的指针数组
然后采用 身份证号处理 第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; }
相关文章推荐
- 采用c语言数据结构实现链表和stl 分别实现链表
- 链表的c语言实现以及根据linux内核中链表的实现过程
- 操作系统模拟内存管理实验,C语言链表实现,附源码
- C语言链表中数组实现数据选择排序,升序、降序功能主要难点
- c语言实现单链表数据结构及其基本操作
- C语言实现链表
- C语言单链表实现19个功能完全详解
- 链表C语言基本实现
- C语言链表各类操作实现
- 链表的实现(C语言)示例
- C语言实现通用链表初步(一)
- 链表的C语言实现之循环链表及双向链表
- 线性链表(C语言实现)
- C语言实现单链表的基本操作及其部分面试题
- C语言实现无头单链表及链表相关面试题(重点!)
- 【C语言】单链表的实现
- C语言实现链表节点的删除
- C语言实现单链表(带头结点)的基本操作(创建,头插法,尾插法,删除结点,打印链表)
- C语言实现双向链表[上]
- 创建链表的三种算法(C语言实现)——正向、逆向、递归