- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
社团统计问题 学号:100320071 姓名:黄晞 报告时间(2010-10-22) 问题描述 FZU里有许多社团,当然,每个同学也积极的参与了自己喜欢的社团。 现在,小Z要统计学校里共里几个社团,但他又不好意思直接问每个同学“你参加了哪个社团?”,因此,他招募了一些人手,去询问N个人中的任意两个人是否属于同一个社团。最后,得到了一些数据。 对问题的理解和分析 题目的意思就是给出M行数,每行数包含2个整数,表示这2个人在同一个社团,其中每个人只能参加一个社团。 例如: 输入: 1 2 表示1号和2号参加同个社团 2 3 表示2号和3号参加同个社团 因此1、2、3在同一个社团。 输入M行数后,根据总人数N(这N个人都参加了社团)来统计出共有多少个社团。 算法与数据结构的选取 算法设计: 关键就是如何表示学生加入的社团以及如何查找某个特定学生是否在该社团中。 基本算法: 1、用一种树的结构来表示每个集合(即社团) 1 2 4 3 5 1,2在集合(社团)1中 3,4,5,6在集合4中 6 算法与数据结构的选取 2、定义一个数组set[n], set[i] = i , 则i表示本集合,并是集合对应树的根 set[i] = j, j!=i, 则 j 是 i 的父节点. 4 3 5 如左图,此集合的根结点为4, 此时,set数组为 6 i ….. 3 4 5 6 …… Set[i] ….. 4 4 4 3 …… 算法与数据结构的选取 3、对于每组输入数据x,y,分别查找出他们所在的集合的父节点,然后将这2个集合合并。 4、合并的算法就是找出x所在集合的根结点(假设是k),令set[k]=(y所在的集合的根结点)。 比如输入:2 3 则合并这2个集合 5、输入完后,遍历数组set,找出其中set[i]=i的个数,就是最终要统计的社团个数。 1 2 4 3 5 1 2 4 3 5 核心代码 int findset(int i)//找出第i个人是属于哪个集合 { if (set[i]==i) return i; set[i]=findset(set[i]);//递归找到set[i]所在的那个集合的根结点 return set[i];} int main() {…… while(m--) { cinxy; set[findset(x)]=findset(y); } //合并x,y所在的集合 …… } 算法复杂度分析 输入时间复杂度O(n) 最后遍历数组找出社团数,需要时间O(n) while(m--) { cinxy; set[findset(x)]=findset(y); } //合并x,y所在的集合 其中findset(x)是递归函数, 写成非递归形式就是: while (set[i]!=i) i=set[i]; 最差情况为O(n) 所以整个算法的时间复杂度为O(m*n) 1 2 n 最差情形 当i=n时,要查找n-1次才能找到根结点 . . . 算法的优缺点分析和改进 缺点就是最差情形时会严重影响算法的执行效率 算法的改进:避免最差情形的出现,可以在每次查找的时候,如果路径较长,则修改信息,让其直接指向根结点,以便下次更快速的查找。 Thank you
文档评论(0)