《資料結構》11-雜湊1 電話聊天狂人
阿新 • • 發佈:2018-11-25
題目
給定大量手機使用者通話記錄,找出其中通話次數最多的聊天狂人。
輸入格式:
輸入首先給出正整數N(≤10
),為通話記錄條數。隨後N行,每行給出一條通話記錄。簡單起見,這裡只列出撥出方和接收方的11位數字構成的手機號碼,其中以空格分隔。
輸出格式:
在一行中給出聊天狂人的手機號碼及其通話次數,其間以空格分隔。如果這樣的人不唯一,則輸出狂人中最小的號碼及其通話次數,並且附加給出並列狂人的人數。
輸入樣例:
4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832
輸出樣例:
13588625832 3
分析
考察散列表
以分離連結法(就是連結串列啦)構造出散列表,把電話號碼後五位存進去,再遍歷散列表找到符合條件的號碼
分享一些我踩過的坑:
- 存電話號碼用的 string 型別,初始化結構體不能用 malloc 申請記憶體,只能用 new
- atoi 傳進去的的引數型別必須是
const char*
string.c_str()
- string 型別可直接比大小
#include<iostream>
#include<stdlib.h>
#include<string>
#include<cmath>
#define MAXTABLESIZE 1000000
using namespace std;
typedef string ElementType;
typedef struct LNode *List;
struct LNode{ // 單鏈表
ElementType number; // 電話號碼
int Count; // 計數
List Next;
};
typedef struct HashTbl *HashTable;
struct HashTbl{ // 雜湊表
int TableSize; // 雜湊表大小
List Heads; // 頭結點
};
// 除留餘數法雜湊函式
int Hash(int key,int p){
return key%p;
}
int NextPrime(int N){
int p = (N%2)?N+2:N+1;
int i;
while(p <= MAXTABLESIZE){
for(i = (int)sqrt(1.0*p);i>2;i--)
if(!(p%i)) // 不是素數
break;
if(i==2) // 找到了
break;
p += 2; // 去找下個素數
}
return p;
}
// 初始化雜湊表
HashTable CreateTable(int TableSize){
HashTable H;
H = (HashTable)malloc(sizeof(struct HashTbl));
H->TableSize = NextPrime(TableSize);
// 結構體中含字串必須動態分配地址空間
H->Heads = new LNode[H->TableSize];
for(int i=0;i<H->TableSize;i++){
H->Heads[i].Next = NULL;
H->Heads[i].Count = 0;
}
return H;
}
// 查詢
List Find(HashTable H,ElementType key){
List p;
int pos;
// 以電話號碼最後五位雜湊
pos = Hash(atoi(key.substr(6,5).c_str()),H->TableSize);
p = H->Heads[pos].Next;
while(p && key != p->number)
p = p->Next;
return p;
}
// 插入
bool Insert(HashTable H,ElementType key){
List p,NewCell;
int pos;
p = Find(H,key);
if(!p){ // p為空
NewCell = new LNode();
NewCell->number = key;
NewCell->Count = 1;
pos = Hash(atoi(key.substr(6,5).c_str()),H->TableSize); // 找到雜湊地址
// 將新結點插入到連結串列頭
NewCell->Next = H->Heads[pos].Next;
H->Heads[pos].Next = NewCell;
return true;
}else{
p->Count++; // 已經存在,計數+1
return false;
}
}
void ScanAndOutput(HashTable H){
List p;
int MaxCnt=0; // 最大通話次數
string Minphone; // 最小號碼
int PCnt=0; // 並列人數
// 掃描連結串列
for(int i=0;i<H->TableSize;i++){
p = H->Heads[i].Next;
while(p){
if(MaxCnt < p->Count){
MaxCnt = p->Count;
Minphone = p->number;
PCnt = 1;
}else if( p->Count == MaxCnt ){
if(p->number < Minphone )
Minphone = p->number;
PCnt++;
}
p = p->Next;
}
}
cout<<Minphone<<" "<<MaxCnt;
if(1 < PCnt)
cout<<" "<<PCnt;
}
int main(){
HashTable H;
int N;
ElementType key;
cin>>N;
H = CreateTable(2*N);
for(int i=0;i<N;i++){
cin>>key; Insert(H,key);
cin>>key; Insert(H,key);
}
ScanAndOutput(H);
return 0;
}