并查集 [维基百科]
来源:互联网 发布:外贸360软件 编辑:程序博客网 时间:2024/06/05 23:50
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。
目录
[隐藏]- 1 主要操作
- 1.1 合并两个不相交集合
- 1.2 判断两个元素是否属于同一集合
- 2 并查集的优化
- 2.1 路径压缩
- 2.2 Rank合并
- 3 源代码
- 4 时间及空间复杂度
- 5 应用
[编辑]主要操作
需要注意的是,一开始我们假设元素都是分别属于一个独立的集合里的。
[编辑]合并两个不相交集合
操作很简单:先设置一个数组Father[x],表示x的“父亲”的编号。 那么,合并两个不相交集合的方法就是,找到其中一个集合最父亲的父亲(也就是最久远的祖先),将另外一个集合的最久远的祖先的父亲指向它。
Pascal代码:
function Union(x,y:integer):boolean;{其中GetFather是下面将讲到的操作} var fx,fy : integer; begin fx := getfather(x); fy := getfather(y); If fx=fy then exit(false) else Union:= true; father[fx] := fy;{指向最祖先的祖先} end;
C语言代码表示形式:
void Union(int x,int y){ fx = getfather(x); fy = getfather(y); if(fy!=fx) father[fx]=fy;}
[编辑]判断两个元素是否属于同一集合
仍然使用上面的数组。则本操作即可转换为寻找两个元素的最久远祖先是否相同。可以采用递归实现。
Pascal代码:
Function Same(x,y:integer):boolean;begin if GetFather(x)=GetFather(y) then exit(true) else exit(false);end;
C代码:
bool same(int x,int y){ return getfather(x)==getfather(y);}/*返回true 表示相同根结点,返回false不相同*/
[编辑]并查集的优化
[编辑]路径压缩
刚才我们说过,寻找祖先时采用递归,但是一旦元素一多起来,或退化成一条链,每次GetFather都将会使用O(n)的复杂度,这显然不是我们想要的。
对此,我们必须要进行路径压缩,即我们找到最久远的祖先时“顺便”把它的子孙直接连接到它上面。这就是路径压缩了。使用路径压缩的代码如下:
Function getfather(v:integer):integer; begin if (father[v]=v) then getfather:=v else begin father[v]:=getfather(father[v]);{路径压缩} getfather:=father[v]; end; end;
int getfather(int v){ if (father[v]==v) return v; else { father[v]=getfather(father[v]);//路径压缩 return father[v]; }}
Procedure Initialize;var i:integer;begin for i:=1 to maxv do Father[i]:=i;end; Function GetFather(v:integer):integer;begin if Father[v]=v then exit(v) else Father[v]:=getfather(father[v]);{路径压缩} exit(Father[v]);end;
[编辑]Rank合并
合并时将元素所在深度低的集合合并到元素所在深度高的集合。
function judge(x,y:integer):boolean; var fx,fy : integer; begin fx := getfather(x); fy := getfather(y); If fx=fy then exit(true) else judge := false; if rank[fx]>rank[fy] then father[fy] := fx else begin father[fx] := fy; if rank[fx]=rank[fy] then inc(rank[fy]); end; end;
初始化:
fillchar(rank,sizeof(rank),0);
C语言代码: 合并时将元素所在深度低的集合合并到元素所在深度深的集合。
void judge(int x ,int y) { fx = getfather(x); fy = getfather(y); if (rank[fx]>rank[fy]) father[fy] = fx; else { father[fx] = fy; if(rank[fx]==rank[fy]) ++rank[fy]; }}
初始化:
memset(rank,0,sizeof(rank));
[编辑]源代码
加了所有优化的代码框架:
function getfather(v:longint):longint;begin if father[v]=v then exit(v) else father[v]:=getfather(father[v]); exit(father[v]);end;
[编辑]时间及空间复杂度
它使用的空间(为元素数量),单次操作的均摊时间为。其中是的反函数,而是阿克曼函数。
[编辑]应用
Kruskal算法的优化
- 并查集 [维基百科]
- 获取并处理中文维基百科语料
- HDU3938 并查集 并查集
- 并查集(集并查)
- 维基百科
- 维基百科
- 马尔可夫链-维基百科
- 决策树 维基百科
- RSA--维基百科
- PNG维基百科
- GCompris -- 维基百科
- 维基百科
- AIX - 维基百科
- YUV--维基百科
- SOAP维基百科
- REST维基百科
- 维基百科-Android
- YUV--维基百科
- 奥运奖牌榜的小调用,是新浪的。
- symbol
- Linux系统中软件简单License的实现
- tomcat 启动内存设置
- CorePlot1.0:安装
- 并查集 [维基百科]
- mongodb数据库---本地集合拷贝克隆、筛选剔除
- velocity + struts2.0调用.vm文件
- Android中ExpandableListView控件基本使用
- django学习之----参考书籍
- ASPWebPack在线压缩,算是比较有用的工具
- #if #else #endif 的应用
- GPU(CUDA)学习日记(二)续------ VS2010 不同工程之间调用DLL
- Handler+Looper+MessageQueue深入详解