1. 程式人生 > >雜湊演算法 C語言 (陣列實現)

雜湊演算法 C語言 (陣列實現)

7-17 電話聊天狂人(25 分)

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

輸入格式:

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

輸出格式:

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

輸入樣例:

4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832

輸出樣例:

13588625832 3

這次來陣列實現,大體思路還是處理資料 然後插入。雜湊 用來大資料處理真的不錯。

/**根據同學的提醒 發現一個小BUG 在插入函式的 平方查詢合適位置的那個地方,現在已修改**/

程式碼:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 400000  /** 定義 最大 陣列 大小 **///(感覺沒啥用 但是最好儘可能開大點,但是不要太大,不要超出系統可建造範圍)
typedef struct Node *Hash; /**新的路程又開始了 這次準備用陣列來做雜湊 還有雙向平方處理衝突**/
struct Node{
    char phone[15];
    int num;
};
int max(int x,int y)
{
    if(x>y) return x;
    else return y;
}
char* minstr(char *x,char *y)
{
    if(strcmp(x,y)>0) return y;
    else return x;
}
int nextprime(const int n)
{
    int p =(n%2==1)? n+2:n+1; /**先找一個大於N的奇數**/
    int i;
    while(p<MAX)
    {
        for(i=(int)sqrt(p);i>=2;i--)   /**然後再判斷是不是素數**/
            if(p%i==0) break;
        if(i<2) return p;        /**是 那就返回這個數**/
        else p+=2;/**不是 那就下一個奇數**/
    }
}
int deal(char *s,int p) /**然後把字串對映成下標 (對映的方式很多很多,隨便猜一個靠譜的就行了)**/
{
    int index = (atoi(s+2))%p;
    return index;
}
int insert(Hash h,int pos,char *s,int p,int Max) /**雜湊查詢的插入實現 ,分別是雜湊陣列,陣列位置,身份證號,陣列最大大小, MAX 看到程式碼最後就明白了**/
{
    int i,posb=pos;             /**備份pos值方便雙向平方查詢**/
    for(i=1;;i++)
    {
        if(strcmp(h[pos].phone,"")==0) /**如果為pos的值空直接插入**/
        {
            strcpy(h[pos].phone,s);
            h[pos].num++;
            Max=max(Max,h[pos].num);
            break;
        }
        else
        {
            if(strcmp(h[pos].phone,s)==0) /**不為空的話,就看看身份證號是不是想等**/
            {
                h[pos].num++;
                Max=max(Max,h[pos].num);
                break;
            }
            else
            { //原p%2==1
                if(i%2==1) pos=(posb+(i*i))%p;  /**不相等 就找下一個位置 ,分別向後找一次和往前找一次,如此迴圈**/
                else
                {              //原i*i
                    pos = posb-((i-1)*(i-1));
                    while(pos<0)
                        pos+=p;
                }
            }
        }
    }
    return Max;
}
void initial(Hash h, int p) /**把雜湊陣列初始化 (初始化的動詞英文忘記咋寫了。。。。)**/
{
    int i;
    for(i=0;i<p;i++)
    {
        h[i].phone[0]='\0';
        h[i].num=0;
    }
}
int main(){


    int Max=0;
    int n;  /**總數 N 然後就開始找 大於N的最小素數了**/
    scanf("%d",&n); /**輸出中把\n也輸入進去 避免下面輸入會出現奇葩的事情**/
    int p = nextprime(2*n); /**突然想起來 每次輸入的都是倆電話號碼,所以 電話號碼最大數是2*n**/
    Hash h =(Hash)malloc(p*sizeof(struct Node));/**建立雜湊陣列**/
    initial(h,p);
    char phone[15];
    char phone1[15];
    while(n--)
    {
        /*for(int i=0;i<p;i++)
        {
            printf("->>>%s %d\n",h[i].phone,h[i].num);
        }
        printf("the max is %d\n",Max);*/
        scanf("%s %s",phone,phone1);
        Max=insert(h,deal(phone,p),phone,p,Max);
        Max=insert(h,deal(phone1,p),phone1,p,Max);
    }
        /*for(int i=0;i<p;i++)
        {
            printf("->>>%s %d\n",h[i].phone,h[i].num);
        }
        printf("the max is %d\n",Max);*/
    int i,num=0;
    char *Minstr=NULL;
    for(i=0;i<p;i++)
    {
        if(h[i].num==Max)
        {
            if(Minstr==NULL) Minstr=h[i].phone;
            else Minstr=minstr(Minstr,h[i].phone);
            num++;
        }
    }
    printf("%s %d",Minstr,Max);
    if(num>1) printf(" %d",num);
return 0;
}