PTA 电话聊天狂人 思路分析及代码解析
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 电话聊天狂人 思路分析及代码解析相关推荐
- PTA 树的同构 思路分析及代码解析
PTA 树的同构 思路分析及代码解析 v1.0 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 2. 思路分析(重点) 三.具体实现 1. 弯路和bug 2. 代码框 ...
- PTA 旅游规划(邻接矩阵) 思路分析及代码解析
PTA 旅游规划 思路分析及代码解析v1.0 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析(重点) 三.具体实 ...
- PTA 公路村村通 思路分析及代码解析
PTA 公路村村通 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析(重点) 三.具体实现 1. 弯路和bug 2 ...
- PTA 旅游规划(邻接表) 思路分析及代码解析
PTA 旅游规划_使用邻接表 思路分析及代码解析v1.0 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析(重点) ...
- PTA 统计工龄 思路分析及代码解析
PTA 统计工龄 思路分析及代码解析v0.6 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析 三.具体实现 1. ...
- PTA 哈利·波特的考试 思路分析及代码解析
PTA 哈利·波特的考试 思路分析及代码解析v0.9.1 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析(重点) ...
- PTA QQ帐户的申请与登陆 思路分析及代码解析
PTA QQ帐户的申请与登陆 思路分析及代码解析v1.0 一.前导 1. 需要掌握的知识 2. 题目信息 二.解题思路分析 1. 题意理解 1. 1 输入数据 1.2 输出数据 2. 思路分析 三.具 ...
- PTA - 电话聊天狂人
给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人. 输入格式: 输入首先给出正整数NN(\le 10^5≤105),为通话记录条数.随后NN行,每行给出一条通话记录.简单起见,这里只列出 ...
- PTA 11-散列1 电话聊天狂人
PTA 11-散列1 电话聊天狂人 文章目录 PTA 11-散列1 电话聊天狂人 思路 Code 给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人. 输入格式: 输入首先给出正整数N(≤10^ ...
最新文章
- 美团北京,今日起无人驾驶送外卖
- WPF 中Frame + Page 的使用
- 算法竞赛训练指南代码仓库_数据仓库综合指南
- python odoo_Odoo开发教程20-使用 Python 虚拟环境安装 Odoo第二讲
- java中Collections常用方法总结(包括sort,copy,reverse等)
- 2021国潮新消费产业洞察报告
- 滴滴出行:10月国内月活用户突破4亿
- 安装linux到服务器配置,CentOS 6.3 服务器安装配置
- 数据结构——一些小点
- 数商云汽车经销商管理系统解决方案:构建消费者、经销商企业功能体系
- 电信光猫桥接+ML固件路由器实现ipv6网站访问
- python+selenium 定位元素踩过的坑
- Error Domain=AVFoundationErrorDomain Code=-11841 (null) timeRange 和 duration 不一致
- 心知天气api PHP,心知天气API的应用实例
- 计算机网络p2p应用,【计算机网络】2.6 P2P应用(示例代码)
- 7-69 战争地图(邻接矩阵和邻接表版本) (25 分)
- 2016年的年终总结吧
- 爬虫爬取python词汇_Python爬虫入门案例:获取百词斩已学单词列表
- js 字符串截取数组常用方法总结(前端)
- linux重启和关闭系统命令
热门文章
- paddle复现pytorch踩坑(二):paddleAPI对照表(百度论文复现营活动提供)
- mysql和linux的题目_最强Linux和Mysql面试题套餐,让你的面试无懈可击!
- C语言第五章Structures Unions
- idea在mapper的xml文件中打不出‘.‘,idea在mapper的xml文件中打不出.,idea在mapper的xml文件中打不出小数点的问题
- 微信小程序上传阿里云视频文件流程及代码
- 云安全 CDN和云防护的区别
- linux trac svn,SVN+Trac版本库的创建和Trac环境设置
- rating vs nominal 额定和标称区别
- adb在小米电视上安装QQ 并使用遥控器操控部分功能
- 归一化处理的目的和意义及其MATLAB方法