PTA 哈希查找 除留取余法

本文介绍了一道名为“PTA电话聊天狂人”的编程题解决方案,通过使用哈希表来统计大量手机用户通话记录中通话次数最多的手机号码。采用除留取余法构造哈希函数,并使用分离链表法解决冲突。
PTA 电话聊天狂人(25 分)

给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人。

输入格式:

输入首先给出正整数N(105​​),为通话记录条数。随后N行,每行给出一条通话记录。简单起见,这里只列出拨出方和接收方的11位数字构成的手机号码,其中以空格分隔。

输出格式:

在一行中给出聊天狂人的手机号码及其通话次数,其间以空格分隔。如果这样的人不唯一,则输出狂人中最小的号码及其通话次数,并且附加给出并列狂人的人数。

输入样例:

4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832

输出样例:

13588625832 3

思路分析:

本题要找通话次数最多的号码,如果这样的号码不唯一,就找最小的号码,想到用哈希表进行存储。

 

代码如下:
  1 //本题采用除留取余法构造哈希函数,使用分离链表法解决冲突
  2 
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <iostream>
  7 
  8 using namespace std;
  9 #define KEYLENGTH 11                   /* 关键词字符串的最大长度 */
 10 typedef char ElementType[KEYLENGTH+1]; /* 关键词类型用字符串 */
 11 typedef int Index;                     /* 散列地址类型 */
 12 
 13 #define MAXTABLESIZE 1000000
 14 
 15 typedef struct LNode *PtrToLNode;
 16 struct LNode
 17 {
 18     ElementType Data;
 19     PtrToLNode Next;
 20     int cnt;
 21 };
 22 typedef PtrToLNode Position;
 23 typedef PtrToLNode List;
 24 
 25 typedef struct TblNode *HashTable; /* 散列表类型 */
 26 struct TblNode     /* 散列表结点定义 */
 27 {
 28     int TableSize; /* 表的最大长度 */
 29     List Heads;    /* 指向链表头结点的数组 */
 30 };
 31 
 32 Index Hash(int k, int TableSize )  //哈希函数
 33 {
 34     return k%TableSize; //除留取余法
 35 }
 36 
 37 int nextPrime(int n)  //选取一个产生冲突较少的素数,作为表长
 38 {
 39     int j=n%2?n+2:n+1;
 40     while(j<=MAXTABLESIZE)
 41     {
 42         int i=0;
 43         for(i=2; i*i<=j; i++)
 44         {
 45             if(!(j%i))
 46                 break;
 47         }
 48         if(i*i>j)
 49             return j;
 50         else
 51             j+=2;   //素数每次加2,减少循环次数
 52     }
 53 }
 54 Position Find(HashTable h,ElementType key,Index k)
 55 {
 56     Position p=h->Heads[k].Next;
 57     while(p&&strcmp(key,p->Data))
 58     {
 59         p=p->Next;
 60     }
 61     return p;
 62 }
 63 void insert(HashTable h,ElementType key)
 64 {
 65     int sum=0;
 66     for(int i=6; i<11; i++)
 67     {
 68         sum=sum*10+(key[i]-'0');   //以第七位到第11位的元素进行哈希
 69     }
 70     Index k=Hash(sum,h->TableSize);
 71     Position p=Find(h,key,k);
 72     if(!p)
 73     {
 74         //使用头插法,提高算法效率
 75         Position newPtr=(Position)malloc(sizeof(LNode));
 76         strcpy(newPtr->Data,key);
 77         newPtr->Next=NULL;
 78         newPtr->cnt=1;
 79         newPtr->Next=h->Heads[k].Next;
 80         h->Heads[k].Next=newPtr;
 81 
 82     }
 83     else
 84         p->cnt++;
 85 }
 86 HashTable BuildTable(int m)
 87 {
 88 
 89     HashTable h;
 90     h=(HashTable)malloc(sizeof(TblNode));
 91     //cout<<"111111111111"<<endl;
 92     h->TableSize=nextPrime(m);
 93     h->Heads=(List)malloc(sizeof(LNode)*h->TableSize);
 94 
 95     for(int i=0; i<h->TableSize; i++)
 96     {
 97         h->Heads[i].Next=NULL;
 98         h->Heads[i].cnt=0;
 99     }
100     return h;
101 }
102 
103 int main()
104 {
105     int n,m;
106     scanf("%d",&n);
107     m=2*n;
108     ElementType key;
109     HashTable h=BuildTable(m);
110     while(m--)
111     {
112         scanf("%s",key);
113         insert(h,key);
114     }
115     //cout<<"111111111111"<<endl;
116     int maxnum=0;
117     int ans=0;
118     for(int i=0; i<h->TableSize; i++)
119     {
120         Position p=h->Heads[i].Next;
121         while(p)
122         {
123             if(p->cnt>maxnum)
124             {
125                 maxnum=p->cnt;
126                 strcpy(key,p->Data);
127                 ans=1;
128             }
129             else if(p->cnt==maxnum)
130             {
131                 ans++;
132                 if(strcmp(key,p->Data)>0)
133                     strcpy(key,p->Data);
134             }
135             p=p->Next;
136         }
137         //cout<<"111111111111"<<endl;
138     }
139     //cout<<"111111111111"<<endl;
140     printf("%s %d",key,maxnum);
141     if(ans>1)
142         printf(" %d",ans);
143     printf("\n");
144     return 0;
145 }
146 
147 /*
148 4
149 13005711862 13588625832
150 13005711862 13088625832
151 13588625832 18087925832
152 13005711862 13588625832
153 
154 */
View Code

 

坚持不懈地努力才能成为大神!

转载于:https://www.cnblogs.com/yimeixiaobai1314/p/7887349.html

在 C 语言中,我们可以使用除留取余法 (也称为取模运算) 来计算哈希值,并结合链地址法处理哈希冲突。首先,让我们编写一个简单的哈希函数以及链表结构来存储元素。 ```c #include <stdio.h> #include <stdlib.h> // 定义哈希表节点结构 typedef struct Node { int key; // 存储的数据 int value; // 对应的值 struct Node* next; // 链接下一个节点 } Node; // 计算哈希值,这里我们简单地使用取模操作 int hash(int data, int size) { return data % size; } // 创建新的哈希表节点 Node* create_node(int key, int value) { Node* newNode = (Node*)malloc(sizeof(Node)); if (newNode != NULL) { newNode->key = key; newNode->value = value; newNode->next = NULL; } return newNode; } // 将数据插入哈希表,处理冲突 void insert(int data, Node** table, int size) { Node* newNode = create_node(data, 0); int index = hash(data, size); if (table[index] == NULL) { table[index] = newNode; } else { // 如果索引处已有节点,使用链地址法解决冲突 Node* temp = table[index]; while (temp->next != NULL) { temp = temp->next; } temp->next = newNode; } } // 打印链表节点 void print_hash_table(Node** table, int size) { for (int i = 0; i < size; i++) { if (table[i]) { Node* node = table[i]; printf("Key: %d, Value: %d -> ", node->key, node->value); while (node->next) { node = node->next; printf("%d -> ", node->key); } printf("NULL\n"); } else { printf("Index %d is empty.\n", i); } } } int main() { int size = 10; // 假设我们有一个大小为10的哈希表 Node** table = (Node**)calloc(size, sizeof(Node*)); // 输入数据并插入哈希表 int input_data[] = {5, 12, 37, 42, 66}; for (int i = 0; i < sizeof(input_data) / sizeof(input_data[0]); i++) { insert(input_data[i], table, size); } // 打印哈希表 print_hash_table(table, size); free(table); // 清理内存 return 0; } ``` 这个示例展示了如何使用除留取余法对数据进行哈希并应用链地址法解决冲突。当有多个元素试图插入相同的哈希位置时,它们会被链接到该位置的链表上。运行`main()`函数可以看到哈希表的最终状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值