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

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

输入格式:

输入首先给出正整数NN(\le 10^5105​​),为通话记录条数。随后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

posted @ 2017-03-26 17:09  joeylee97  阅读(1245)  评论(0编辑  收藏  举报