Hash:将存储位置与数据本身对应掐来的存储手段就是Hash
例2.5 统计通成绩学生人数(1018)
题目描述:读入n(n<=1000)名学生的成绩(0~100,整型)(当读到n时结束),将获得某一给定分数的学生人数输出。
样例输入: 3 80 60 90 60 2 85 66 0 5 60 75 90 55 75 75 0
样例输出: 1 0 2
#include<stdio.h> int main(){ int n,tmp,num; int buf[101]; while(scanf("%d",&n)!=EOF&&n!=0){ for(int i=0;i<=100;i++)//也可直接定义为int Hash[101]={0}; buf[i]=0; for(int i=0;i<n;i++){ scanf("%d",&tmp); buf[tmp]++; } scanf("%d",&num); printf("%d\n",buf[num]); } return 0; }
例2.6 Sort (1431)
题目描述:给你n个整数,请按从大到小的顺序输出前m大的数。第一行有两个数n,m(0<n,m<1000000),第二行包含n个各不相同,且处于区间[-500000,500000]的整数。
样例输入: 5 3 3 -35 92 213 -644 样例输出: 213 92 3
由于代排序数字的数量十分庞大(1000000),即使使用快排也仍有可能超时。而哈希只需要从尾到头遍历数组,其时间复杂度仍在百万数量级,解法符合要求。
由于输入数据中出现了负数,于是我们不能直接把输入数据当做数组下标来访问数组元素,而是将每一个输入的数据都加上一个固定偏移值,使数据区间映射到数组下标区间。
本题还要注意在最后一个数字之后不存在空格。
#include<stdio.h> int Hash[1000001];//在函数内部的静态数组是在栈上分配空间所以不能开得太大,而全局的数组是在数据段分配空间所以可以弄大些。如果在函数内部开大数组可能产生栈溢出。 int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF){ for(int i=0;i<=1000000;i++) Hash[i]=0; for(int i=1;i<=n;i++){ int tmp; scanf("%d",&tmp); Hash[tmp+500000]++; } for(int i=1000000;i>=0;i--){ if(Hash[i]!=0){ printf("%d",i-500000); m--; if(m!=0) printf(" "); else{ printf("\n"); break; } } } } return 0; }