11-散列1 电话聊天狂人

通过散列表实现高效查找通话记录中最频繁出现的手机号码及其通话次数。利用哈希函数定位元素,链地址法解决冲突。

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

输入格式:

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

输出格式:

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

输入样例:

4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832

输出样例:

13588625832 3

 

  1 #include <iostream>
  2 #include <cstdio> 
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <math.h>
  6 using namespace std;
  7 
  8 #define MAXTABLESIZE 1000000 /* 允许开辟的最大散列表长度 */
  9 #define KEYLENGTH 11                   /* 关键词字符串的最大长度 */
 10 #define MAXD 5                     /*参与散列映射计算的字符数*/
 11 typedef char ElementType[KEYLENGTH+1]; /* 关键词类型用字符串 */
 12 typedef int Index;                     /* 散列地址类型 */
 13  
 14 /******** 以下是单链表的定义 ********/
 15 typedef struct LNode *PtrToLNode;
 16 struct LNode {
 17     ElementType Data;
 18     PtrToLNode Next;
 19     int Count;
 20 };
 21 typedef PtrToLNode Position;
 22 typedef PtrToLNode List;
 23 /******** 以上是单链表的定义 ********/
 24  
 25 typedef struct TblNode *HashTable; /* 散列表类型 */
 26 struct TblNode {   /* 散列表结点定义 */
 27     int TableSize; /* 表的最大长度 */
 28     List Heads;    /* 指向链表头结点的数组 */
 29 };
 30  
 31 int NextPrime( int N )
 32 { /* 返回大于N且不超过MAXTABLESIZE的最小素数 */
 33     int i, p = (N%2)? N+2 : N+1; /*从大于N的下一个奇数开始 */
 34  
 35     while( p <= MAXTABLESIZE ) {
 36         for( i=(int)sqrt(p); i>2; i-- )
 37             if ( !(p%i) ) break; /* p不是素数 */
 38         if ( i==2 ) break; /* for正常结束,说明p是素数 */
 39         else  p += 2; /* 否则试探下一个奇数 */
 40     }
 41     return p;
 42 }
 43 
 44 HashTable CreateTable( int TableSize )
 45 {
 46     HashTable H;
 47     int i;
 48  
 49     H = (HashTable)malloc(sizeof(struct TblNode));
 50     H->TableSize = NextPrime(TableSize);/* 保证散列表最大长度是素数 */
 51     H->Heads = (List)malloc(H->TableSize*sizeof(struct LNode));/* 以下分配链表头结点数组 */
 52     
 53     /* 初始化表头结点 */
 54     for( i=0; i<H->TableSize; i++ ) {
 55          H->Heads[i].Data[0] = '\0';
 56          H->Heads[i].Next = NULL;
 57          H->Heads[i].Count = 0;
 58     }
 59  
 60     return H;
 61 }
 62 
 63 Index Hash(int Key, int TableSize )
 64 {
 65     
 66     return Key % TableSize;
 67 }
 68 
 69 
 70 Position Find( HashTable H, ElementType Key )
 71 {
 72     Position P;
 73     Index Pos;
 74      
 75     Pos = Hash(atoi(Key+KEYLENGTH-MAXD), H->TableSize ); /* 初始散列位置 */
 76     P = H->Heads[Pos].Next; /* 从该链表的第1个结点开始 */
 77     /* 当未到表尾,并且Key未找到时 */ 
 78     while( P && strcmp(P->Data, Key) )
 79         P = P->Next;
 80  
 81     return P; /* 此时P或者指向找到的结点,或者为NULL */
 82 }
 83 
 84 bool Insert( HashTable H, ElementType Key )
 85 {
 86     Position P, NewCell;
 87     Index Pos;
 88      
 89     P = Find( H, Key );
 90     if ( !P ) { /* 关键词未找到,可以插入 */
 91         NewCell = (Position)malloc(sizeof(struct LNode));
 92         strcpy(NewCell->Data, Key);
 93         NewCell->Count = 1;
 94         Pos = Hash(atoi(Key+KEYLENGTH-MAXD), H->TableSize ); /* 初始散列位置 */ 
 95         /* 将NewCell插入为H->Heads[Pos]链表的第1个结点 */
 96         NewCell->Next = H->Heads[Pos].Next;
 97         H->Heads[Pos].Next = NewCell; 
 98         return true;
 99     }
100     else { /* 关键词已存在 */
101         P->Count++;
102         return false;
103     }
104 }
105 
106 void DestroyTable( HashTable H )
107 {
108     int i;
109     Position P, Tmp;
110      
111     /* 释放每个链表的结点 */
112     for( i=0; i<H->TableSize; i++ ) {
113         P = H->Heads[i].Next;
114         while( P ) {
115             Tmp = P->Next;
116             free( P );
117             P = Tmp;
118         }
119     }
120     free( H->Heads ); /* 释放头结点数组 */
121     free( H );        /* 释放散列表结点 */
122 }
123 
124 void ScanAndOutput( HashTable H )
125 {
126     int MaxCnt = 0, PCnt = 0;    //MaxCnt最大通话次数 
127     ElementType MinPhone;
128     List Ptr;
129     MinPhone[0] = '\0';
130     
131     for(int i = 0; i < H->TableSize; i++) {    //扫描链表 
132         Ptr = H->Heads[i].Next;
133         while(Ptr) {
134             if (Ptr->Count > MaxCnt) {     //更新最大通话次数
135                 MaxCnt = Ptr->Count;
136                 strcpy(MinPhone, Ptr->Data);
137                 PCnt = 1;
138             }
139             else if (Ptr->Count == MaxCnt) {
140                 PCnt ++;     //狂人计数
141                 if ( strcmp(MinPhone, Ptr->Data)>0 )
142                     strcpy(MinPhone, Ptr->Data); /* 更新狂人的最小手机号码*/
143             }
144             Ptr = Ptr->Next;
145         }
146     }
147     printf("%s %d", MinPhone, MaxCnt);
148     if ( PCnt > 1 ) 
149         printf(" %d", PCnt);
150     printf("\n");
151 }
152 
153 int main()
154 {
155     HashTable hash;
156     ElementType Key;
157     int N;
158     scanf("%d",&N);
159     hash = CreateTable(N*2);
160     for(int i = 0; i < N; i++) {
161         scanf("%s",Key);
162         Insert(hash, Key);
163         scanf("%s",Key);
164         Insert(hash, Key);
165     }
166     
167     ScanAndOutput(hash);
168     DestroyTable(hash);
169     return 0;
170 }

 

转载于:https://www.cnblogs.com/kuotian/p/5519897.html

### 电话聊天 C语言 示例代码 为了实现基于C语言的电话聊天功能,可以采用简单的TCP/IP协议栈来建立客户端和服务端之间的通信。下面提供了一个简化版的服务端和客户端示例。 #### 客户端代码 此部分展示了如何创建一个基本的客户端应用程序,用于向服务端发送消息并接收响应: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") //加载 ws2_32.dll void initWinsock() { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); } SOCKET connectToServer(const char* ipAddr) { struct sockaddr_in server_addr; SOCKET connfd; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8888); /* 使用固定端口 */ inet_pton(AF_INET, ipAddr, &(server_addr.sin_addr)); if ((connfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){ perror("socket"); exit(EXIT_FAILURE); } if (connect(connfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr))<0){ perror("connect"); closesocket(connfd); exit(EXIT_FAILURE); } return connfd; } int main(){ initWinsock(); SOCKET client = connectToServer("127.0.0.1"); printf("连接成功,请等待...\n"); while (true) { char buffer[BUFSIZ]; fgets(buffer, BUFSIZ, stdin); send(client, buffer,strlen(buffer)+1 , 0 ); recv(client,buffer,BUFSIZ,0 ); fputs(buffer,stdout); } closesocket(client); WSACleanup(); return 0; } ``` #### 服务端代码 以下是对应的服务端程序,负责监听来自客户端的消息请求,并作出回应: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") void initWinsock() { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); } void startListening(int port) { int sockfd, new_sock; struct sockaddr_in address; int addrlen = sizeof(address); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == INVALID_SOCKET) { perror("Unable to create socket"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(port); bind(sockfd, (struct sockaddr *)&address, sizeof(address)); listen(sockfd, 3); puts("Waiting for incoming connections..."); while((new_sock = accept(sockfd, (struct sockaddr *)&address, (socklen_t*)&addrlen))) { puts("Connection accepted"); while(true) { char message[BUFSIZ] = {0}; recv(new_sock,message,BUFSIZ,0); if(strcmp(message,"exit")==0){break;} printf("Client : %s\n",message); fflush(stdout); fgets(message, BUFSIZ,stdin); send(new_sock,message,strlen(message)+1 , 0 ); } closesocket(new_sock); } closesocket(sockfd); WSACleanup(); } int main(void) { initWinsock(); startListening(8888); return 0; } ``` 上述代码实现了基础的双向通讯机制,在实际应用中可能还需要考虑更多的异常处理逻辑以及更复杂的交互流程设计[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值