小白专场-FileTransfer-c语言实现
更新、更全的《数据结构与算法》的更新网站,更有python、go、人工智能教学等着你:https://www.cnblogs.com/nickchen121/p/11407287.html
一、集合的简化表示
在上一节 集合及运算中,我们对集合使用二叉树表示,如下图所示:

为了使用二叉树,我们在上一节中使用以下代码,构造二叉树:
/* c语言实现 */
typedef struct{
ElementType Data;
int Parent;
} SetType;
int Find(SetType S[], ElementType X)
{
// 在数组S中查找值为X的元素所属的集合
// MaxSize是全局变量,为数组S的最大长度
int i;
for (i = 0; i < MaxSize && S[i].Data != X; i++);
if (i >= MaxSize) return -1; // 未找到X,返回-1
for (; S[i].Parent >= 0; i = S[i].Parent);
return i; // 找到X所属集合,返回树根结点在数组S中的下标
}
使用二叉树构造集合,Find操作在差的情况下时间复杂度可能为\(O(n^2)\)
因此对于任何有限集合的(N个)元素都可以被一一映射为整数 0~N-1。即对于集合 {2, 5, 4, 3} 和 {6, 0, 1} 我们可以使用如下图所示的数组表示:

对于上述的数组,我们可以使用如下代码构造:
/* c语言实现 */
typedef int ElementType; // 默认元素可以用非负整数表示
typedef int SetName; //默认用根结点的下标作为集合名称
typedef ElementType SetType[MaxSize];
SetName Find(SetType S, ElementType X)
{
// 默认集合元素全部初始化为-1
for (; S[X] >= 0; X = S[X]);
return X;
}
void Union(SetType S, SetName Root1, SetName Root2)
{
// 这里默认Root1和Root2是不同集合的根节点
S[Root2] = Root1;
}
二、题意理解
根据输入样例,以此来判断计算机之间有多少个组成,如下图所示

上图动态变化如下图所示:

下图为五台计算机之间形成全连接状态,因此看成一个整体:

三、程序框架搭建
/* c语言实现 */
int main()
{
初始化集合;
do {
读入一条指令;
处理指令;
} while (没结束);
return 0;
}
int main()
{
SetType S;
int n;
char in;
scanf("%d\n", &n);
Initialization(S, n);
do {
scanf("%c", &in);
switch (in) {
case 'I': Input_connection(S); break; // Union(Find)
case 'C': Check_connection(S); break; // Find
case 'S': Check_network(S, n); break; // 数集合的根,判断计算机网络的组成个数
}
} while (in != 'S');
return 0;
}
3.1 Input_connection
/* c语言实现 */
void Input_connection(SetType S)
{
ElementType u, v;
SetName Root1, Root2;
scanf("%d %d\n", &u, &v);
Root1 = Find(S, u-1);
Root2 = Find(S, v-1);
if (Root1 != Root2)
Union(S, Root1, Root2);
}
3.2 Check_connection
/* c语言实现 */
void Check_connection(SetType S)
{
ElementType u, v;
scnaf("%d %d\n", &u, &v);
Root1 = Find(S, u-1);
Root2 = Find(S, v-1);
if (Root1 == Root2)
printf("yes\n");
else printf("no\n");
}
3.3 Check_network
/* c语言实现 */
void Check_network(SetType S, int n)
{
int i, counter = 0;
for (i = 0; i < n; i++){
if (S[i] < 0) counter++;
}
if (counter == 1)
printf("The network is connected.\n");
else
printf("There are %d components.\n", counter);
}
四、pta测试
/* c语言实现 */
typedef int ElementType; // 默认元素可以用非负整数表示
typedef int SetName; //默认用根结点的下标作为集合名称
typedef ElementType SetType[MaxSize];
SetName Find(SetType S, ElementType X)
{
// 默认集合元素全部初始化为-1
for (; S[X] >= 0; X = S[X]);
return X;
}
void Union(SetType S, SetName Root1, SetName Root2)
{
// 这里默认Root1和Root2是不同集合的根节点
S[Root2] = Root1;
}
对于上述的代码,如果我们放入pta中测试,会发现测试点6运行超时,如下图所示:

因此,我们会考虑是不是因为出现了某种情况,导致Root2为根结点的树过大了,因此我们修改代码为:
/* c语言实现 */
typedef int ElementType; // 默认元素可以用非负整数表示
typedef int SetName; //默认用根结点的下标作为集合名称
typedef ElementType SetType[MaxSize];
SetName Find(SetType S, ElementType X)
{
// 默认集合元素全部初始化为-1
for (; S[X] >= 0; X = S[X]);
return X;
}
void Union(SetType S, SetName Root1, SetName Root2)
{
// 这里默认Root1和Root2是不同集合的根节点
// S[Root2] = Root1;
S[Root1] = Root2;
}

发现更换代码后,测试点5却运行超时了,为了解决上述问题,我们可以使用下面将要讲到了按秩归并的思想修改代码。
五、按秩归并
为什么需要按秩归并呢?因为我们使用pta测试程序,发现代码总是超时,因此我们可以考虑是否出现这种情况——我们再不断地往一颗树上累加子树,如下图所示:
/* c语言实现 */
Union(Find(2), Find(1));
Union(Find(3), Find(1));
……;
Union(Find(n), Find(1));

从上图可以看出,此过程的时间复杂度为:\(T(n) = O(n^2)\)
除了上述这种情况,会导致树的高度越来越高,如果我们把高树贴在矮树上,那么树高也会快速增长,因此我们应该考虑把矮树贴在高数上。

对于上述问题的解决,我们给出以下两个解决方法,这两种方法统称为按秩归并。
5.1 方法一:树高替代
为了解决上述问题,我们可以把根结点从-1替代为-树高,代码如下:
/* c语言实现 */
if ( Root2高度 > Root1高度 )
S[Root1] = Root2;
else {
if ( 两者等高 ) 树高++;
S[Root2] = Root1;
}
if ( S[Root2] < S[Root1] )
S[Root1] = Root2;
else {
if ( S[Root1]==S[Root2] ) S[Root1]--;
S[Root2] = Root1;
}
5.2 方法二:规模替代
为了解决上述问题,我们也可以把根结点从**-1替代为-元素个数(把小树贴到大树上),代码如下:
/* c语言实现 */
void Union( SetType S, SetName Root1, SetName Root2 )
{
if ( S[Root2]<S[Root1] ){
S[Root2] += S[Root1];
S[Root1] = Root2;
} else {
S[Root1] += S[Root2];
S[Root2] = Root1;
}
}
六、路径压缩
对于上述代码超时的问题,我们也可以使用路径压缩的方法优化代,即压缩给定元素到集合根元素路径中的所有元素,详细情况如下图所示:

上图代码可表示为:
/* c语言实现 */
SetName Find(SetType S, ElementType X)
{
// 找到集合的根
if (S[X] < 0)
return X;
else
return S[X] = Find(S, S[X]);
}
总之上述代码干了这三件事:
- 先找到根;
- 把根变成X的父结点;
- 再返回根
因此,路径压缩第一次执行的时间比较长,但是如果频繁使用查找命令,第一次将路径压缩,大大减小树的高度,后续查找速度将大大增加
6.1 路径压缩时间复杂度计算
由于pta并没有严格控制时间限制,使用java这种语言,不使用路径压缩,问题不大,我写这个也只是为了回顾算法,来放松放松,不是为了折腾自己,因此。
给你一个眼神自己体会,给你一个网址亲自体会https://www.icourse163.org/learn/ZJU-93001?tid=1206471203#/learn/content?type=detail&id=1211167097&sm=1,我是懒得研究下图所示了。

小白专场-FileTransfer-c语言实现的更多相关文章
- 小白专场-多项式乘法与加法运算-c语言实现
目录 一.题意理解 二.求解思路 三.多项式的表示 3.1 数组 3.2 链表 四.程序框架搭建 五.如何读入多项式 六.如何将两个多项式相加 七.如何将两个多项式相乘 八.如何将多项式输出 一.题意 ...
- 小白专场-多项式乘法与加法运算-python语言实现
目录 题意理解 解题思路 多项式加法 多项式乘法 完整代码 题意理解 题目: 设计函数分别求两个一元多项式的乘积与和. 输入格式: 输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一 ...
- 小白专场-树的同构-c语言实现.md
目录 一.题意理解 二.求解思路 2.1 二叉树表示 2.2 程序框架搭建 2.3 如何建二叉树 2.4 如何判别两二叉树同构 更新.更全的<数据结构与算法>的更新网站,更有python. ...
- 小白专场-是否同一颗二叉搜索树-python语言实现
目录 一.二叉搜索树的相同判断 二.问题引入 三.举例分析 四.方法探讨 4.1 中序遍历 4.2 层序遍历 4.3 先序遍历 4.4 后序遍历 五.总结 六.代码实现 一.二叉搜索树的相同判断 二叉 ...
- 小白专场-树的同构-python语言实现
目录 一.题意理解 二.求解思路 更新.更全的<数据结构与算法>的更新网站,更有python.go.人工智能教学等着你:<https://www.cnblogs.com/nickch ...
- 小白专场-是否同一颗二叉搜索树-c语言实现
目录 一.题意理解 二.求解思路 三.搜索树表示 程序框架搭建 3.1 如何建搜索树 3.2 如何判别 3.3 清空树 更新.更全的<数据结构与算法>的更新网站,更有python.go.人 ...
- 小白专场-堆中的路径-c语言实现
目录 一.题意理解 二.堆的表示及其操作 三.主程序 更新.更全的<数据结构与算法>的更新网站,更有python.go.人工智能教学等着你:https://www.cnblogs.com/ ...
- 小白专场-堆中的路径-python语言实现
目录 更新.更全的<数据结构与算法>的更新网站,更有python.go.人工智能教学等着你:https://www.cnblogs.com/nickchen121/p/11407287.h ...
- 小白专场-FileTransfer-python语言实现
目录 更新.更全的<数据结构与算法>的更新网站,更有python.go.人工智能教学等着你:https://www.cnblogs.com/nickchen121/p/11407287.h ...
随机推荐
- CentOS7配置网络ip地址
CentOS7配置网络ip地址 CentOS 7.x版本中没有ifcfg-eth0文件 只有ifcfg-ens33文件(为了符合日常习惯) (1)将文件ifcfg-ens33重命名为ifcfg-eth ...
- Git随身手册
Git随身手册 本文是关于Git探索的一篇文章,阐述了Git的大部分命令和使用方式,并列举了几个典型的使用场景以供参考和体会. 对于Git这个分布式的VCS,从链表的角度来看待是最容易理解的: 一次c ...
- java短信验证和注册
最近公司需要用到短信验证注册,所以申请了阿里云的短信服务.我的项目是分布式的spring boot 原理: 利用第三方发送短信 获取回执消息,然后存入缓存里面 将用户填写的验证码与缓存里面的验证码对比 ...
- Contour 学习笔记(一):使用 Contour 接管 Kubernetes 的南北流量
原文链接:Contour 学习笔记(一):使用 Contour 接管 Kubernetes 的南北流量 在 Kubernetes 中运行大规模以 Web 为中心的工作负载,最关键的需求之一就是在 L7 ...
- CentOS 7下安装配置搭建jdk+tomcat+MariaDB环境
1.JDK安装 注意:rpm与软件相关命令 相当于window下的软件助手 管理软件 步骤: 1)查看当前Linux系统是否已经安装java 输入 rpm -qa | grep java 2)卸载两个 ...
- Java集合框架之HashMap浅析
Java集合框架之HashMap浅析 一.HashMap综述: 1.1.HashMap概述 位于java.util包下的HashMap是Java集合框架的重要成员,它在jdk1.8中定义如下: pub ...
- CAD数据分块,偏移校准,加载到百度地图、高德地图、谷歌等地图上
前面分享过一篇如何将CAD海量数据显示在百度地图上(百度地图Canvas实现十万CAD数据秒级加载),但是很多开发者在CAD数据提取时遇到了问题,所以接下来的文章将介绍如何将CAD数据提取. 准备软件 ...
- ElasticSearch专栏
1.es的分布式架构原理(es是如何实现分布式)? elasticsearch设计的理念就是分布式搜索引擎,底层其实还是基于lucene的.核心思想就是在多台机器上启动多个es进程实例,组成了一个es ...
- CentOS 源码安装MySQL5.7
一.安装方式源码安装,源码包名称mysql-boost-5.7.27.tar.gz,此版本包含boost库,在解压后的boost路径下.安装时,可以-DDOWNLOAD_BOOST=1 -DWITH_ ...
- TK图形界面
import tkinter 1.使用tkinter模块前 一般先要建立一个tkinter的对象 例: window = tkinter.TK() 2.建立完对象设置好窗口属性以及所有功能 ...