算法熟记-并查集

本文介绍了并查集这一数据结构的基本概念与应用,包括合并两个集合、判断元素是否属于同一集合等操作,并提供了未使用路径压缩和启发式方法的伪代码示例。
转载地址:http://www.cnblogs.com/pangxiaodong/archive/2011/05/27/2059547.html

算法熟记-并查集



1. 简述

    并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。
    需要实现的操作有:合并两个集合,判断两个元素是否属于一个集合。
    这里介绍的主要是普通的并查集,很多情况下使用的并查集是需要扩展的,根据使用情况的不同,有很多差别,这里仅仅是最基本的算法。

2. 复杂度

    T=O(n*α(n)) , 其中α(x),对于x=宇宙中原子数之和,α(x)不大于4。事实上,路经压缩后的并查集的复杂度是一个很小的常数。
3. 伪代码   

    没有使用路径压缩和启发式的方法。

复制代码
// 初始化并查集
#define N 100
int father[N];
void init() {
    for(int i=0; i<N; i++)
      father[i] = i;
}
//  合并两个元素所在的集合
void  union( int  x, int  y) {
    x 
=  getfather(x);
    y 
=  getfather(y);
    
if (x != y )
       father[x]
= y;
}
//  判断两个元素是否属于同一个集合
bool  same( int  x, int  y) {
    
return  getfather(x) == getfather(y);
}
//  获取根结点
int  getfather( int  x) {
    
while (x != father[x] )
      x 
=  father[x];
    
return  x;
}
复制代码

    使用路径压缩,改进getfather。

//  获取根结点
int  getfather( int  x) {
    
if (x  !=  father[x])
      father[x] 
=  getfather(father[x]); // 路径压缩修改的是father数组
     return  father[x];
}

    另外,还可以改进union,把数量少的集合合并到数量大的集合中,不过这就要记录每个集合中的元素数量,相当于增加了O(N)的存储空间,而且在getfather中也应该保持对元素数量的维护,相对代码复杂度偏高,而且感觉性能提升不多,这里就不写了。

### CSP-S 初赛考试内容 CSP-S(Certified Software Professional – Senior)初赛是由中国计算机学会(CCF)主办的信息学奥赛选拔环节之一,主要面向高中阶段学生。其考试形式为笔试(目前多数地区已转为机考),全部为单项选择题,总时长约为2小时。 #### 考察模块构成: - **计算机基础知识** 包括但不限于数据表示、进制转换、原码反码补码、存储单位换算等内容[^1]。此类题目虽有“送分”性质,但仍需掌握基本概念与运算方法[^3]。 - **程序设计语言基础(通常基于 C++)** 涉及变量类型、控制结构(if/for/while)、函数调用机制、作用域、指针初步等语法知识点[^2]。 - **算法与数据结构核心主题** 高频考点覆盖十二大专题:语法基础、数学思维、模拟算法、排序、贪心、二分查找、前缀和与差分、DFS/BFS、动态规划、栈与队列、树与图的基础遍历及相关应用[^2]。 - **阅读程序写结果题型分析能力** 此部分要求考生理解一段给定的 C++ 程序逻辑并推导运行结果。常涉及嵌套循环、递归展开、数组操作以及边界判断等问题[^3]。 - **完善程序(完形填空式编程推理)** 提供残缺代码片段,通过上下文语义填补空白处最合适的表达式或语句。这不仅考验编码直觉,也检验对常见模板的熟悉程度[^3]。 --- ### 备考策略建议 随着近年来命题趋势向复赛靠拢,单纯依靠死记硬背难以应对当前难度提升的局面[^1]。因此备考应当注重系统训练与实战演练相结合的方式进行优化安排。 #### 时间分配推荐(以考前一个月为例) 每日投入不少于2–3小时集中复习,划分为三个阶段: - 第一周至第二周:梳理知识体系 + 分项突破; - 第三周:历年真题限时模考 + 错因归纳; - 最后一周:查漏补缺 + 强化易错点回顾。 #### 学习路径构建 可围绕如下方向建立学习框架: ```cpp // 示例:典型 DFS 枚举子集的应用场景(有助于加深理解) #include <iostream> using namespace std; int a[] = {1, 2, 3}; void dfs(int u) { if (u == 3) return; // 边界条件 cout << a[u] << endl; dfs(u + 1); // 继续探索下一层节点 } ``` 重点攻克《12大高频考点》所列条目,逐个击破各专项难点[^2]。尤其注意动态规划的状态转移建模思路、贪心策略合法性论证过程、以及搜索剪枝效率评估等方面深入思考。 #### 应试技巧提炼 面对不确定选项时可以采用排除法辅助决策: - 寻找多个备选项之间的共通特征作为线索; - 发现相互矛盾的说法则至少有一个错误; - 若完全无法判定,在统计意义上倾向于选择 B 或 C 类答案更可能命中正确率峰值[^3]。 定期完成近五年内的真实试卷练习(如 2021 年 CSP-S 初赛试题),严格计时环境下测试答题节奏与心理承受力[^2]。 --- ### 经验分享要点 高水平选手之间差距往往体现在细节处理能力和临场发挥稳定性上。以下是成功通关者的普遍做法总结: - 对于斐波那契数列、卡特兰数、杨辉三角、斯特林数等组合数学模型保持敏感度,并熟记对应递推关系式及其应用场景[^3]。 - 掌握位运算常用技巧(异或交换律、lowbit 运算实现树状数组原理雏形等)有利于快速解构底层逻辑。 - 注重调试意识培养——即使是在纸上读程也要像使用 IDE 一样逐步跟踪变量变化轨迹。 - 不盲目追求刷题数量,而是每做完一套题都做到彻底消化吸收,尤其是搞清每一个误判背后的知识盲区所在[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值