您的位置:首页 > 其它

5-14 电话聊天狂人 (25分) HASH

2017-03-26 17:09 447 查看
给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人。

输入格式:

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

输出格式:

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

输入样例:

4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832

输出样例:

13588625832 3


搜索树程序:

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
typedef long long LL;
typedef struct Treenode
{
LL str;
int cnt;
struct Treenode* left;
struct Treenode* right;
}Treenode,*Tree;
Tree Newnode(LL s)
{
Tree t = (Tree)malloc(sizeof(Treenode));
t->str = s;
t->cnt = 1;
t->left = NULL;
t->right = NULL;
return t;
}
Tree Insert(Tree T,LL s)
{
if(!T)
T = Newnode(s);
else if(T->str>s)
T->left = Insert(T->left,s);
else if(T->str<s)
T->right = Insert(T->right,s);
else
T->cnt = T->cnt+1;
return T;
}
void find(Tree T,LL &mins,int &maxt,int &same)
{
if(T)
{
if(T->cnt > maxt)
{
maxt = T->cnt;
mins = T->str;
same = 1;
}
else if((T->cnt==maxt))
{
if(T->str<mins)
mins = T->str;
same++;
}
find(T->left,mins,maxt,same);
find(T->right,mins,maxt,same);
}
}
int main()
{
int n;
LL t1;
Tree T;
cin>>n;
cin>>t1;
T =Newnode(t1);
for(int i=1;i<2*n;i++)
{
cin>>t1;
T = Insert(T,t1);
}
LL ms=0;
int mt=0,num=0;
find(T,ms,mt,num);
cout<<ms<<' '<<mt;
if(num>1)
cout<<' '<<num<<endl;
else
cout<<endl;
return 0;
}


hash程序

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

/*
Hash表的使用方法//hash表size一般是大于N的第一个素数
1.嵌套定义结构体 注意在hashtable 中定义的是一个指向指针的指针(指向list结构体的指针列表)
初始化时注意分配空间!
所以在给Hshlist分配空间的时候,要注意,(list*)malloc(sizeof(list))这样才对!
2.确定hash函数,在这里使用atoi把字符串转变为数字然后对哈希表size取余数.
3.插入操作,查找操作
列表元素第一个是头节点,应该从它的next元素开始遍历
通过hash函数找到对应的在list中的位置,然后在该位置中查找元素,如果存在就计数,不存在就在列表头
加入元素.
4.destroy操作,分别对应Init一一释放空间
*/

typedef struct Listnode *Pos;
typedef struct Listnode
{
char Phonenum[12];
int cnt;
Pos next;
}*List;
typedef struct Hashtable
{
int tablesize;
List *Thelist;
} *HashTable;

int Hash(int key,int size)
{
return key%size;
}
void Insert(char key[],HashTable H);
Pos Find(char key[],HashTable H);
HashTable Init(int size);
void destroy(HashTable H);
void FindMax(HashTable H);
int NextPrime(int x);
int main()
{
int n;
scanf("%d",&n);
HashTable H = Init(2*n);
char from[12],to[12];
for(int i=0;i<n;i++)
{
scanf("%s%s",from,to);
Insert(from,H);
Insert(to,H);
}
FindMax(H);
destroy(H);
}
int NextPrime(int x)
{
int i,j;
for(i=x;;i++)
{
for(j=2;j*j<=i;j++)
if(i%j==0)
break;
if(j*j>i)
return i;
}
}
HashTable Init(int size)
{
int Tsize = NextPrime(size);
HashTable H = (HashTable)malloc(sizeof(Hashtable));
H->tablesize = Tsize;
H->Thelist = (List*)malloc(sizeof(List)*Tsize);
for(int i=0;i<Tsize;i++)
{
H->Thelist[i] = (List)malloc(sizeof(Listnode));
H->Thelist[i]->next = NULL;
}
return H;
}

void Insert(char key[],HashTable H)
{
Pos p,tmp;
List t = H->Thelist[Hash(atoi(key+6),H->tablesize)];
p = Find(key,H);
if(p==NULL)
{
tmp = (List)malloc(sizeof(Listnode));
tmp->cnt = 1;
strcpy(tmp->Phonenum,key);
tmp->next = t->next;
t->next = tmp;
}
else
(p->cnt)++;
}

Pos Find(char key[],HashTable H)
{
List t = H->Thelist[Hash(atoi(key+6),H->tablesize)];
List p = t->next;
while(p!=NULL&&strcmp(p->Phonenum,key))
p = p->next;
return p;
}

void destroy(HashTable H)
{
for(int i=0;i< H->tablesize;i++)
{
free(H->Thelist[i]);
}
free(H->Thelist);
free(H);
}

void FindMax(HashTable H)
{
char MinPhone[12];
int max = -1,same = 1;
for(int i=0;i<H->tablesize;i++)
{
List t = H->Thelist[i];
t = t->next;
while(t!=NULL)
{
if( t->cnt > max)
{
max = t->cnt;
strcpy(MinPhone,t->Phonenum);
same = 1;
}
else if(t->cnt == max)
{
if(strcmp(MinPhone,t->Phonenum)>0)
strcpy(MinPhone,t->Phonenum);
same++;
}
t =t->next;
}
}
printf("%s %d", MinPhone, max);
if (same > 1)
printf(" %d", same);
}


这题一开始用map超时,然后我试了试二叉搜索树,也无情超时,看来必须用hash

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: