错误记录:
1.以下两个代码等价吧,虽然我看不十分懂
char Data[KEYLENGTH+1];
//与
typedef char ElementType[KEYLENGTH + 1];//不十分理解
ElementType Data;
2.类型转换
for(i=(int)sqrt(q);i>2;–i){//wrong used sqr 另:为什么要使用双精度的q 函数原型:double sqrt(double x);
这里可以说一下类型转换的tiny知识点,当函数被调用时,声明将对参数进行强制类型转换,因此这里使用整型的p作为实参传入也是可以的,但是我运行了两次,发现直接使用p时程序运行时间比使用q变量的时间的两倍。(不知道为什么)
3. if(p%i==0) break; //%只能用于整数运算的运算符,%是求余运算符,只能适用于整数与整数运算,如果用于非整数运算,程序会报错导致无法运行。
4. H->Heads = (PtrToLNode)malloc(H->TableSize*sizeof(struct LNode));
//这是一个动态数组,H->Heads为动态数组首地址,数组中的元素为struct LNode,我当时错以为申请的动态数组中的元素是指针变量。
5. H->TableSize = NextPrime(TableSize);//wrong used TableSize = NextPrime(TableSize)
这里的目的是给哈希表H的TableSize成员赋值,但我忘记写H了。
6.p[i]与*(p+i)是相同的,都是指针p所指向的对象,而(p+i)是指针,才能使用->运算符
7.
(H->Heads+i)->Data[0] = '\0';//wrong used H->Heads[i]->Data = '\0';
//这里的Data是一个数组,还有事我没懂
//想不明白 这个H->Heads难道不是指针么,对他是一个指针,但是对指针加[]就相当于解引用,此时H->Heads[i]为指针指向的节点
H->Heads[i].Next = NULL;
H->Heads[i].cnt = 0;
8.while(*Key!=’\0’){//wrong used if(*Key!=’\0’)
我这里错把while写成了if,通过了前两个测试,第三个超时,这里的Key是一个指针,*Key++的运算顺序,间接寻址运算符和增1运算符的优先级都是二,但是结合方向为右结合,所以其实等价于 *(Key++),因此是对指针做增一运算。
9. P = H->Heads[h].Next;
//wrong used P = H->Heads+h这就是没懂散列表数据结构的表现,散列表中的列表头节点不存储数据
Index Hash(const char *Key,int TableSize){
unsigned int h=0;
while(*Key!='\0'){//wrong used if(*Key!='\0')
h += (h << 5) + *Key++;//wrong used h += (Key<<5) + Key++;
}
return h%TableSize;
}
#include<math.h>
#include<stdbool.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXTABLESIZE 1000000 //为啥
#define HASHNUM 5
#define KEYLENGTH 11
typedef char ElementType[KEYLENGTH + 1];//不十分理解
typedef int Index;
typedef struct LNode *PtrToLNode;
struct LNode{
PtrToLNode Next;
int cnt;
ElementType Data;
};
typedef PtrToLNode Position;
//散列表节点定义
typedef struct TableNode *HashTable;//不十分理解为什么这么命名
struct TableNode{
int TableSize;
PtrToLNode Heads;//这是一个数组,每个节点都是LNode
};
int NextPrime(int N){
int i,p = (N%2)? (N+2):(N+1);
double q = p;
while(q<MAXTABLESIZE){
for(i=(int)sqrt(q);i>2;--i){//wrong used sqr 另:为什么要使用双精度的q double sqrt(double x);
if(p%i==0) break; //%只能用于整数运算的运算符,%是求余运算符,只能适用于整数与整数运算,如果用于非整数运算,程序会报错导致无法运行。
}
if(i==2) break;
else p += 2;
}
return p;
}
HashTable CreateTable(int TableSize){
HashTable H;
int i;
H = (HashTable)malloc(sizeof(struct TableNode));
H->TableSize = NextPrime(TableSize);//wrong used TableSize = NextPrime(TableSize)
H->Heads = (PtrToLNode)malloc(H->TableSize*sizeof(struct LNode));
//这是一个动态数组,H->Heads为动态数组首地址,数组中的元素为struct LNode
for(i=0;i<H->TableSize;++i){
(H->Heads+i)->Data[0] = '\0';//wrong used H->Heads[i]->Data = '\0';
//这里的Data是一个数组,还有事我没懂
//想不明白 这个H->Heads难道不是指针么,对他是一个指针,但是对指针加[]就相当于解引用,此时H->Heads[i]为指针指向的节点
H->Heads[i].Next = NULL;
H->Heads[i].cnt = 0;
}
return H;
}
Index Hash(const char *Key,int TableSize){
unsigned int h=0;
while(*Key!='\0'){//wrong used if(*Key!='\0')
h += (h << 5) + *Key++;//wrong used h += (Key<<5) + Key++;
}
return h%TableSize;
}
Position Find(HashTable H,ElementType Key){
Position P;
Index h;
h = Hash(Key+KEYLENGTH-HASHNUM,H->TableSize);//wrong used h = Hash(Key-KEYLENGTH+HASHNUM,H->TableSize)
P = H->Heads[h].Next;
//wrong used P = H->Heads+h这就是没懂散列表数据结构的表现,散列表中的列表头节点不存储数据
while(P && strcmp(Key,P->Data)){
P = P->Next;
}
return P;
}
bool Insert(HashTable H,ElementType Key){
Position P,NewCell;
Index pos;
P = Find(H,Key);
if(!P){
NewCell = (PtrToLNode)malloc(sizeof(struct LNode));
strcpy(NewCell->Data,Key);//wrong used strcopy(NewCell->Data,Key);
NewCell->cnt = 1;//现在有点懵 这个cnt保存的是什么 哦想起啦了 狂人打电话次数
pos = Hash(Key+KEYLENGTH-HASHNUM,H->TableSize);
NewCell->Next = H->Heads[pos].Next;
H->Heads[pos].Next = NewCell;
return true;
}
else{
P->cnt++;
return false;
}
}
void DestroyTable(HashTable H){
int i;
PtrToLNode P,temp;
for(i=0;i<H->TableSize;++i){
P = H->Heads[i].Next;
while(P){
temp = P->Next;
free(P);
P = temp;
}
}
free(H->Heads);
free(H);
}
void ScanAndOutput(HashTable H){
int i,Mcnt=0,Pcnt=0;
ElementType MinPhone;
MinPhone[0] = '\0';//其实我不太懂为什么这样初始化
PtrToLNode P;
for(i=0;i<H->TableSize;++i){
P = H->Heads[i].Next;
while(P){
if(P->cnt>Mcnt){
Mcnt = P->cnt;
strcpy(MinPhone,P->Data);
Pcnt = 1;
}
else if(P->cnt==Mcnt){
if(strcmp(MinPhone,P->Data)>0){
strcpy(MinPhone,P->Data);
}
Pcnt++;
}
P = P->Next;//我竟然忘了这个
}
}
printf("%s %d",MinPhone,Mcnt);
if(Pcnt>1) printf(" %d",Pcnt);
printf("\n");
}
int main(){
HashTable H;
int i,N;
ElementType Key;
scanf("%d",&N);
H = CreateTable(2*N);
for(i=0;i<N;++i){
scanf("%s",Key);Insert(H,Key);
scanf("%s",Key);Insert(H,Key);
}
ScanAndOutput(H);
DestroyTable(H);
return 0;
}