今天在做HDOJ上的1800 题,题目描述的很复杂,其实解题思路归纳起来就这么一句话:
“给你一系列数字,找出出现次数最多的那个”
由于测试样本给的数字可能很大,范围超出__int64的表示范围,所以只能用个字符串来写大数了
用的是C语言,也只能自己写hash算法。
由于是多组测试数据,所以每次都要把hash表清空,开始随手写了个
1 for(i=0;i<NHASH;i++) 2 carr[i] = NULL;
代码提交后,不管怎么样,AC了,不过内存使用虽然在AC范围内,但也出奇的大。
想了半天,是上面代码的问题,因为数组里面每个元素都可能是长度大于一的链表,结构如下:
1 typedef struct MyCount MyCount; 2 struct MyCount { 3 char num[32]; 4 int cnt; 5 MyCount *next; 6 };
所以很显然,我几乎没有正确的free已经分配出去的内存
而free链表的话,很容易就会引起内存泄露,正确的free链表的代码如下(来自《Expert C Programming》):
1 struct node *p, *start, *tmp; 2 for(p=start; p; p=tmp){ 3 tmp = p->next; 4 free(p); 5 }
另附上AC代码,AC的效率不高,但是也算是可作为参考用C实现了一个简单的hash表
View Code
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #define MULTIPLIER 31 5 #define NHASH 1023 6 typedef struct MyCount MyCount; 7 struct MyCount { 8 char num[32]; 9 int cnt; 10 MyCount *next; 11 }; 12 MyCount *carr[NHASH]; 13 int hash(char *str) { 14 unsigned int h; 15 unsigned char *p; 16 h=0; 17 for(p=(unsigned char *)str; *p!='\0'; p++) 18 h = MULTIPLIER * h + *p; 19 return h%NHASH; 20 } 21 void add(char *str) { 22 int h; 23 int findit = 0; 24 MyCount *sp; 25 h = hash(str); 26 for(sp = carr[h]; sp!=NULL; sp = sp->next) { 27 if(strcmp(str,sp->num) == 0){//find it 28 sp->cnt++; 29 findit = 1; 30 break; 31 } 32 } 33 if(findit==0){//did not find it 34 sp = (MyCount *)malloc(sizeof(MyCount)); 35 strcpy(sp->num,str); 36 sp->cnt = 1; 37 sp->next = carr[h]; 38 carr[h] = sp; 39 } 40 } 41 42 43 int main() { 44 int n; 45 char temp[32]; 46 char *p; 47 int i,max; 48 MyCount *sp; 49 while(scanf("%d",&n)!=EOF) { 50 for(i=0;i<NHASH;i++) 51 carr[i] = NULL; 52 max = 0; 53 while(n--) { 54 scanf("%s",temp); 55 p = temp; 56 while(*p=='0') 57 p++; 58 add(p); 59 } 60 for(i=0;i<NHASH;i++){ 61 sp = carr[i]; 62 while(sp){ 63 if(sp->cnt>max) 64 max = sp->cnt; 65 //printf("##%s %d\n",sp->num,sp->cnt); 66 sp = sp->next; 67 } 68 } 69 printf("%d\n",max); 70 } 71 return 0; 72 }