PTA 数据结构与算法 7-14 电话聊天狂人

如有不对,不吝赐教
进入正题:

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

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

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

输入样例:
4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832

输出样例:
13588625832 3

这个很明显是属于查找分类统计问题,所以直接上Hash表就行了,至于存储的数据结构,我用链表法解决Hash冲突问题(其实更优的做法是把每个Hash桶的下属数据结构变成时间复杂度更低的数据结构,如树之类的),然后用long long型数据来记录电话号码。
这里要注意的就是链表的操作,还有Hash函数的编写(虽然这个题的Hash函数没啥问题,但有的Hash函数在操作过程中的key可能变为负数)

下面给代码:

#include<stdio.h>
#include<malloc.h>

struct PhoneNode{
long long phoneNumber;  //电话号码
int count;      //出现次数
struct PhoneNode *next;
};

long long phone;   //用于记录电话号
int maxCount;   //用于记录打电话最多的那个电话号
int crazyPeople=1;

struct PhoneNode *head[1<<18];

void Add(void);      //每次在添加的时候就进行比较
void Free(void);

int main(void)
{
    int N,i;
    scanf("%d",&N);

    for(i=0;i<N;i++){
      Add();
      Add();
    }

    printf("%lld %d",phone,maxCount);

    if(1!=crazyPeople)
      printf(" %d",crazyPeople);

    return 0;
}

void Add(void)
{
    long long number;
    int key;
    struct PhoneNode *cur,*newOne;
    scanf("%lld",&number);

    key=number&((1<<18)-1);
    cur=head[key];
    newOne=(struct PhoneNode *)malloc(sizeof(struct PhoneNode));
    newOne->phoneNumber=number;
    newOne->count=1;
    newOne->next=NULL;

    do{
      if(!cur){
        head[key]=newOne;
        cur=head[key];
        break;
      }       //该Hash桶为空

      while(cur->next){
        if(cur->phoneNumber==newOne->phoneNumber){
          cur->count++;
          free(newOne);
          break;
        }       //该循环不检验下一种情况
        cur=cur->next;
      }     //这里要注意到最后一个节点的时候
      if(!cur->next){
        if(cur->phoneNumber==newOne->phoneNumber){
          cur->count++;
          free(newOne);
          break;
        }
        else{
        cur->next=newOne;
        cur=newOne;
        }
    }   //如果在链表尾部 那么就接上去
    }while(0);


    if(cur->count>=maxCount){
      if(cur->count>maxCount){
        maxCount=cur->count;
        phone=cur->phoneNumber;
        crazyPeople=1;       //将狂人数目 归一
      }    //使使用次数最大
      else{
        if(phone>cur->phoneNumber)
          phone=cur->phoneNumber;   //使电话号码最小
          crazyPeople++;  //并列狂人
      }
    }

    return ;
}

void Free(void)
{
    long long i;
    struct PhoneNode *cur;

    for(i=0;i<(1<<18)-1;i++)
      while(head[i]){
        cur=head[i]->next;
        if(cur->next){
          head[i]->next=cur->next;
          free(cur);
          cur=NULL;
          cur=head[i]->next;
        }
        free(cur);
        free(head[i]);
        cur=NULL;
        head[i]=NULL;
      }

    return ;
}

结果:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值