PTA 电话聊天狂人 思路分析及代码解析v1.0

  • 一、前导
    • 1. 需要掌握的知识
    • 2. 题目信息
  • 二、解题思路分析
    • 1. 题意理解
      • 1. 1 输入数据
      • 1.2 输出数据
    • 2. 思路分析
  • 三、具体实现
    • 1. 弯路和bug
    • 2. 代码框架
      • 2.1 采用的数据结构
      • 2.2 程序主体框架
      • 2.3 各分支函数
    • 3. 完整AC编码
  • 四、参考

一、前导

1. 需要掌握的知识

通过分离链接法实现Hash/哈希表

2. 题目信息

2.1 题目来源:PTA / 拼题A
2.2 题目地址: 电话聊天狂人

二、解题思路分析

1. 题意理解

对输入的通话记录进行整理,找到出现次数最多的电话号码、通话次数;若不唯一,则需要找到最小号码、通话次数和并列人数

1. 1 输入数据

4 //通话记录条数
13005711862 13588625832  //具体的通话记录
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832

1.2 输出数据

13588625832 3 // 出现次数最多的电话号码 通话次数
......

2. 思路分析

与陈越老师讲解的思路一致:首先创建Hash表(链表方式),然后将录入的数据存储在Hash表中,最后扫描Hash表找到目标数据

三、具体实现

1. 弯路和bug

Hash表编码的熟练度低

2. 代码框架

2.1 采用的数据结构

结构体、链表

typedef char ElementType[KeyLength + 1]; //关键字类型是字符串 电话号码11位+'\0'//链表定义
typedef struct LinkTableNode* PtrLinkTableNode;
typedef PtrLinkTableNode List;
struct LinkTableNode
{ElementType Data; //电话号码PtrLinkTableNode Next; //相同哈希值的下一个号码int Count; //Count用于指示电话号码出现的次数
};//散列表结点定义
typedef struct HashTableNode* HashTable;
struct HashTableNode
{int HashTableSize;//表最大长度List Heads; //指向链表头结点的数组
};

2.2 程序主体框架

               程序伪码描述
int main()
{1.创建链表形式的Hash表 2.将电话号码插入到Hash表中3.扫描Hash表找到目标数据并打印4.释放Hash表占用的内存空间
}

2.3 各分支函数

2.3.1 CreateHashTable( ) 创建Hash表,属于基本功

HashTable CreateHashTable(int HashTableSize)
{HashTable H;H = (HashTable)malloc(sizeof(HashTableNode));H->HashTableSize = NextPrime(HashTableSize); //Hash表大小:大于存储元素个数的素数//链表头结点数组H->Heads = (List)malloc(sizeof(struct LinkTableNode) * H->HashTableSize);for (int i = 0; i < H->HashTableSize; i++) //初始化 链表头结点数组各数组元素{H->Heads[i].Next = NULL;H->Heads[i].Data[0] = '\0';H->Heads[i].Count = 0;//计数}return H;
}

2.3.2 Find( ) 在Hash表中搜索元素,若为空,返回Null;若找到,返回该链接点的位置。Find函数被Insert函数调用

Position Find(HashTable H, ElementType Key)
{Position P;Index Pos;Pos = Hash(Key, H->HashTableSize); //初始化散列位置:求余
//strcmp(str1,str2),若str1=str2,返回零;若str1<str2,返回负数;若str1>str2,返回正数P = H->Heads[Pos].Next;//从链表的第一个结点开始寻找while (P && strcmp(P->Data, Key))P = P->Next;return P;
}

2.3.3 Insert( ) 在Hash表中插入元素

bool Insert(HashTable H, ElementType Key)
{Position P, NewNode;Index Pos;P = Find(H, Key);if (!P) //P=NULL 关键词未找到,直接插入{NewNode = (Position)malloc(sizeof(struct LinkTableNode));strcpy(NewNode->Data, Key);NewNode->Count = 1;Pos = Hash(Key, H->HashTableSize); //初始化散列位置NewNode->Next = H->Heads[Pos].Next;//每次在头结点后增加,若插入顺序是1 2 3,链表顺序就是 head-3-2-1H->Heads[Pos].Next = NewNode;return true;}else{P->Count++;return false;}
}

2.3.4 ScanAndOutput( ) 扫描Hash表找到目标数据并打印

void ScanAndOutput(HashTable H)
{int MaxCount = 0, PeopleCount = 0; //PeopleCount代表结果不唯一时的并列人数ElementType MinPhoneNumber;List Ptr;MinPhoneNumber[0] = '\0'; for (int i = 0; i < H->HashTableSize; i++){Ptr = H->Heads[i].Next;while (Ptr){if (Ptr->Count > MaxCount){MaxCount = Ptr->Count;strcpy(MinPhoneNumber, Ptr->Data);PeopleCount = 1;}else if (Ptr->Count == MaxCount){PeopleCount++;if (strcmp(MinPhoneNumber, Ptr->Data) > 0)//strcmp(str1,str2),若str1>str2,返回正数strcpy(MinPhoneNumber, Ptr->Data); //MinPhoneNumber=Ptr->Data}Ptr = Ptr->Next;}}cout << MinPhoneNumber << ' ' << MaxCount;if (PeopleCount > 1)cout << ' ' << PeopleCount << endl;return;
}

2.3.5 DestoryHashTable( ) 释放Hash表占用的内存空间

void DestoryHashTable(HashTable H)
{Position P, Tmp;/* 释放每个链表的结点 */for (int i = 0; i < H->HashTableSize; i++){P = H->Heads[i].Next;while (P){Tmp = P->Next;free(P);P = Tmp;}}free(H->Heads); /* 释放头结点数组 */free(H);        /* 释放散列表结点 */
}

2.3.6 NextPrime( ) 和 Hash( )属于基础编码,在此不单独列出

3. 完整AC编码

如有建议或问题,欢迎留言

#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;#define MAX 300000
#define KeyLength 11 //关键字字符串最大长度typedef char ElementType[KeyLength + 1]; //关键字类型是字符串 11位+'\0'
typedef int Index;//散列地址类型/*单链表定义*/
typedef struct LinkTableNode* PtrLinkTableNode;
typedef PtrLinkTableNode List;
typedef PtrLinkTableNode Position;
struct LinkTableNode
{ElementType Data;PtrLinkTableNode Next;int Count;
};//散列表结点定义
typedef struct HashTableNode* HashTable;
struct HashTableNode
{int HashTableSize;//表最大长度List Heads; //指向链表头结点的数组
};HashTable CreateHashTable(int HashTableSize);
Position Find(HashTable H, ElementType Key);
bool Insert(HashTable H, ElementType Key);
int NextPrime(int n);
int Hash(ElementType Key, int TableSize);
void ScanAndOutput(HashTable H);
void DestoryHashTable(HashTable H);int main()
{int N; //N represent record numberElementType Key; //typedef char ElementType[KeyLength+1];HashTable H;//Define HashTable Hcin >> N;H = CreateHashTable(N * 2);//Create a Hash Tablefor (int i = 0; i < N; i++){cin >> Key; Insert(H, Key); //put Key in HashTable Hcin >> Key; Insert(H, Key); // a record contain two number}ScanAndOutput(H);DestoryHashTable(H);return 0;
}void DestoryHashTable(HashTable H)
{Position P, Tmp;/* 释放每个链表的结点 */for (int i = 0; i < H->HashTableSize; i++){P = H->Heads[i].Next;while (P){Tmp = P->Next;free(P);P = Tmp;}}free(H->Heads); /* 释放头结点数组 */free(H);        /* 释放散列表结点 */
}void ScanAndOutput(HashTable H)
{int MaxCount = 0, PeopleCount = 0;ElementType MinPhoneNumber;List Ptr;MinPhoneNumber[0] = '\0'; //MinPhoneNumber[0]for (int i = 0; i < H->HashTableSize; i++){Ptr = H->Heads[i].Next;while (Ptr){if (Ptr->Count > MaxCount){MaxCount = Ptr->Count;strcpy(MinPhoneNumber, Ptr->Data);PeopleCount = 1;}else if (Ptr->Count == MaxCount){PeopleCount++;if (strcmp(MinPhoneNumber, Ptr->Data) > 0)strcpy(MinPhoneNumber, Ptr->Data);}Ptr = Ptr->Next;}}cout << MinPhoneNumber << ' ' << MaxCount;if (PeopleCount > 1)cout << ' ' << PeopleCount << endl;return;
}HashTable CreateHashTable(int HashTableSize)
{HashTable H;H = (HashTable)malloc(sizeof(HashTableNode));H->HashTableSize = NextPrime(HashTableSize);//链表头结点数组H->Heads = (List)malloc(sizeof(struct LinkTableNode) * H->HashTableSize);for (int i = 0; i < H->HashTableSize; i++){H->Heads[i].Next = NULL;H->Heads[i].Data[0] = '\0';H->Heads[i].Count = 0;//计数}return H;
}Position Find(HashTable H, ElementType Key)
{Position P;Index Pos;Pos = Hash(Key, H->HashTableSize); //初始化散列位置P = H->Heads[Pos].Next;//从链表的第一个结点开始寻找while (P && strcmp(P->Data, Key))P = P->Next;return P;
}bool Insert(HashTable H, ElementType Key)
{Position P, NewNode;Index Pos;P = Find(H, Key);if (!P) //P=NULL 关键词未找到,直接插入{NewNode = (Position)malloc(sizeof(struct LinkTableNode));strcpy(NewNode->Data, Key);NewNode->Count = 1;Pos = Hash(Key, H->HashTableSize); //初始化散列位置NewNode->Next = H->Heads[Pos].Next;//每次在头结点后增加,若插入顺序是1 2 3,链表顺序就是 head-3-2-1H->Heads[Pos].Next = NewNode;return true;}else{P->Count++;return false;}
}int Hash(ElementType Key, int TableSize)
{int k;k = atoi(Key + KeyLength - 5); //ASCIItoInt,使用11位电话号码的后5位进行哈希return k % TableSize;
}int NextPrime(int n)//返回大于n 且 不超过MAX的最小素数
{int p, i;p = (n % 2) ? n + 2 : n + 1; //p一定是奇数且比n大while (p < MAX){for (i = (int)sqrt(p); i > 2; i--)if (!(p % i))break;if (i == 2) break;elsep += 2;}return p;
}

四、参考

浙江大学 陈越、何钦铭老师主讲的数据结构

PTA 电话聊天狂人 思路分析及代码解析相关推荐

  1. PTA 树的同构 思路分析及代码解析

    PTA 树的同构 思路分析及代码解析 v1.0 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 2. 思路分析(重点) 三.具体实现 1. 弯路和bug 2. 代码框 ...

  2. PTA 旅游规划(邻接矩阵) 思路分析及代码解析

    PTA 旅游规划 思路分析及代码解析v1.0 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析(重点) 三.具体实 ...

  3. PTA 公路村村通 思路分析及代码解析

    PTA 公路村村通 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析(重点) 三.具体实现 1. 弯路和bug 2 ...

  4. PTA 旅游规划(邻接表) 思路分析及代码解析

    PTA 旅游规划_使用邻接表 思路分析及代码解析v1.0 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析(重点) ...

  5. PTA 统计工龄 思路分析及代码解析

    PTA 统计工龄 思路分析及代码解析v0.6 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析 三.具体实现 1. ...

  6. PTA 哈利·波特的考试 思路分析及代码解析

    PTA 哈利·波特的考试 思路分析及代码解析v0.9.1 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析(重点) ...

  7. PTA QQ帐户的申请与登陆 思路分析及代码解析

    PTA QQ帐户的申请与登陆 思路分析及代码解析v1.0 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析 三.具 ...

  8. PTA - 电话聊天狂人

    给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人. 输入格式: 输入首先给出正整数NN(\le 10^5≤10​5​​),为通话记录条数.随后NN行,每行给出一条通话记录.简单起见,这里只列出 ...

  9. PTA 11-散列1 电话聊天狂人

    PTA 11-散列1 电话聊天狂人 文章目录 PTA 11-散列1 电话聊天狂人 思路 Code 给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人. 输入格式: 输入首先给出正整数N(≤10^ ...

最新文章

  1. 美团北京,今日起无人驾驶送外卖
  2. WPF 中Frame + Page 的使用
  3. 算法竞赛训练指南代码仓库_数据仓库综合指南
  4. python odoo_Odoo开发教程20-使用 Python 虚拟环境安装 Odoo第二讲
  5. java中Collections常用方法总结(包括sort,copy,reverse等)
  6. 2021国潮新消费产业洞察报告
  7. 滴滴出行:10月国内月活用户突破4亿
  8. 安装linux到服务器配置,CentOS 6.3 服务器安装配置
  9. 数据结构——一些小点
  10. 数商云汽车经销商管理系统解决方案:构建消费者、经销商企业功能体系
  11. 电信光猫桥接+ML固件路由器实现ipv6网站访问
  12. python+selenium 定位元素踩过的坑
  13. Error Domain=AVFoundationErrorDomain Code=-11841 (null) timeRange 和 duration 不一致
  14. 心知天气api PHP,心知天气API的应用实例
  15. 计算机网络p2p应用,【计算机网络】2.6 P2P应用(示例代码)
  16. 7-69 战争地图(邻接矩阵和邻接表版本) (25 分)
  17. 2016年的年终总结吧
  18. 爬虫爬取python词汇_Python爬虫入门案例:获取百词斩已学单词列表
  19. js 字符串截取数组常用方法总结(前端)
  20. linux重启和关闭系统命令

热门文章

  1. paddle复现pytorch踩坑(二):paddleAPI对照表(百度论文复现营活动提供)
  2. mysql和linux的题目_最强Linux和Mysql面试题套餐,让你的面试无懈可击!
  3. C语言第五章Structures Unions
  4. idea在mapper的xml文件中打不出‘.‘,idea在mapper的xml文件中打不出.,idea在mapper的xml文件中打不出小数点的问题
  5. 微信小程序上传阿里云视频文件流程及代码
  6. 云安全 CDN和云防护的区别
  7. linux trac svn,SVN+Trac版本库的创建和Trac环境设置
  8. rating vs nominal 额定和标称区别
  9. adb在小米电视上安装QQ 并使用遥控器操控部分功能
  10. 归一化处理的目的和意义及其MATLAB方法