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

输入格式:

输入首先给出正整数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 }

 

posted on 2016-05-23 14:39  kuotian  阅读(772)  评论(0编辑  收藏  举报