您的位置:首页 > 其它

并查集路径压缩与启发式合并

2014-11-04 08:44 239 查看
〖程序清单〗

初始化:

for i:=1 to n do father[i]:=i;


因为每个元素属于单独的一个集合,所以每个元素以自己作为根结点。

寻找根结点编号并压缩路径:

function getfather(v : integer) : integer;
begin
if father[v]=v then exit(v);
father[v]:=getfather(father[v]);
getfather:=father[v];
end;
//合并两个集合:
proceudre merge(x, y : integer);
begin
x:=getfather(x);
y:=getfather(y);
father[x]:=y;
end;


判断元素是否属于同一集合:

function judge(x, y : integer) : boolean;
begin
x:=getfaher(x);
y:=gefather(y);
if x=y then exit(true) else exit(false);
end;


这里有一个优化:让深度较小的树成为深度较大的树的子树,这样查找的次数就会少些。这个优化称为启发式合并。可以证明:这样做以后树的深度为O(logn)。即:在一个有n个元素的集合,我们将保证移动不超过logn次就可以找到目标。

function judge(x,y:integer):boolean;

var fx,fy : integer;

begin

fx := getfaher(x);

fy := gefather(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);


并查集的时间复杂度

并查集进行n次查找的时间复杂度是O(n)

它是阿克曼函数(Ackermann Function)的某个反函数。

它可以看作是小于5的。所以可以认为并查集的时间复杂度几乎是线性的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: