PAT电话聊天狂人 哈希表实现查找与插入 C语言实现

原题链接:https://pintia.cn/problem-sets/900290821590183936/problems/928950008090570752

原题目:
11-散列1 电话聊天狂人(25 分)

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

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

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

4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832

输出样例:

13588625832 3

有关哈希表:
哈希表首先是声明一个哈希表的结构体,然后将结构体中的list类型的Heads声明为一个结点的结构体。
为Heads开辟TableSize个空间形成数组,数组中的每个元素都是一个个链表的头结点,但是这个头结点并不存储数据,只是起一个索引的功能。
PAT电话聊天狂人 哈希表实现查找与插入 C语言实现_第1张图片

源代码:

#include 
#include 
#include 
#include 
#define KEYLENGTH 11
#define MAXTABLESIZE 1000000
typedef char ElementType[KEYLENGTH+1];
typedef int Index;

typedef struct LNode *PtrToLNode;
struct LNode{
    ElementType Data;       //存电话号码 
    PtrToLNode Next;
    int Count;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;

typedef struct TblNode *HashTable;
struct TblNode{
    int TableSize;
    List Heads;
};

int NextPrime(int N)
{
    int i,p=(N%2)?N+2:N+1;
    while(p<=MAXTABLESIZE)
    {
        for(i=(int)sqrt(p);i>2;i--)
        if(!p%i)break;//p is not a prime
        if(i==2)break;//p is a prime
        else p+=2;
    }
    return p;
}

HashTable CreateTable(int TableSize)
{
    HashTable H;
    int i;
    H=(HashTable)malloc(sizeof(struct TblNode));
    H->TableSize=NextPrime(TableSize);
    H->Heads=(List)malloc(H->TableSize*sizeof(struct LNode));
    for(i=0;iTableSize;i++)
    {
        H->Heads[i].Data[0]='\0';
        H->Heads[i].Next=NULL;
        H->Heads[i].Count=0;
    }
    return H;
}

int Hash(int Key,int p)
{//除留余数法求散列函数 
    return Key%p;
}

Position Find(HashTable H,ElementType Key)  //此时Key是一个指向字符串(电话号码)的头指针 
{
    Position P;
    Index Pos;

    Pos=Hash(atoi(Key+KEYLENGTH-5),H->TableSize);   //将电话号码的后五位转化成整数,再进行散列,后五位数相同的电话号码存放在同一个链表中 

    P=H->Heads[Pos].Next;
    while(P&&strcmp(P->Data,Key))   //注意strcmp函数是在两个字符串相等的时候返回0,前者大返回正数,否则返回负数 
    P=P->Next;
    return P; 
}

int Insert(HashTable H,ElementType Key)
{
    Position P,NewCell;
    Index Pos;

    P=Find(H,Key);
    if(!P)//the Key dose not exist,need to create a space for it;
    {
        NewCell=(Position)malloc(sizeof(struct LNode));
        strcpy(NewCell->Data,Key);
        NewCell->Count=1;
        Pos=Hash(atoi(Key+KEYLENGTH-5),H->TableSize);
        NewCell->Next=H->Heads[Pos].Next;
        H->Heads[Pos].Next=NewCell;
        return 1;
    }
    else    //Key has already exist,no need to create;
    {
        P->Count++;
        return 0;
    }
}

void ScanAndOutput(HashTable H)
{
    int i,Maxcnt=0,Pcnt=0;
    ElementType MinPhone;
    List Ptr;
    MinPhone[0]='\0';
    for(i=0;iTableSize;i++)
    {
        Ptr=H->Heads[i].Next;
        while(Ptr)
        {
            if(Ptr->Count>Maxcnt)
            {
                Maxcnt=Ptr->Count;
                strcpy(MinPhone,Ptr->Data);
                Pcnt=1;
            }
            else if(Ptr->Count==Maxcnt)
            {
                if(strcmp(MinPhone,Ptr->Data)>0)
                strcpy(MinPhone,Ptr->Data);
                Pcnt++; //狂人计数 
            }
            Ptr=Ptr->Next;
        }
    }
    printf("%s %d",MinPhone,Maxcnt);
    if(Pcnt>1)printf(" %d",Pcnt);
    printf("\n");
}

void DestroyTable(HashTable H)
{
    int i;
    List p;
    for(i=0;iTableSize;i++)
    {
        p=H->Heads[i].Next;
        while(p)
        {
            free(p);
            p=p->Next;
        }
    }
}

int main()
{
    int N,i;
    ElementType Key;        //注意:此时的ElementType类型带有[] 
    HashTable H;

    scanf("%d",&N);
    H=CreateTable(N*2);
    for(i=0;iscanf("%s",Key);Insert(H,Key);
        scanf("%s",Key);Insert(H,Key);
    }
    ScanAndOutput(H);
    DestroyTable(H);
    return 0;
} 

你可能感兴趣的:(数据结构与算法,c语言,哈希表)