1. 程式人生 > >《資料結構》11-雜湊1 電話聊天狂人

《資料結構》11-雜湊1 電話聊天狂人

題目

給定大量手機使用者通話記錄,找出其中通話次數最多的聊天狂人。

輸入格式:
輸入首先給出正整數N(≤10 5 ​^5 ​​ ),為通話記錄條數。隨後N行,每行給出一條通話記錄。簡單起見,這裡只列出撥出方和接收方的11位數字構成的手機號碼,其中以空格分隔。

輸出格式:
在一行中給出聊天狂人的手機號碼及其通話次數,其間以空格分隔。如果這樣的人不唯一,則輸出狂人中最小的號碼及其通話次數,並且附加給出並列狂人的人數。

輸入樣例:

4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832

輸出樣例:

13588625832 3

分析

考察散列表
以分離連結法(就是連結串列啦)構造出散列表,把電話號碼後五位存進去,再遍歷散列表找到符合條件的號碼
分享一些我踩過的坑:

  1. 存電話號碼用的 string 型別,初始化結構體不能用 malloc 申請記憶體,只能用 new
  2. atoi 傳進去的的引數型別必須是 const char*
    ,string 型別 substr 後還是 string 型別,要轉換成需要的引數型別格式應該為: string.c_str()
  3. 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; }