Geeks Union-Find Algorithm Union By Rank and Path Compression 图环算法

同样是查找一个图是否有环的算法,但是这个算法很牛逼,构造树的时候可以达到O(lgn)时间效率。n代表顶点数

原因是根据需要缩减了树的高度,也叫压缩路径(Path compression),名字很高深,不过其实不难理解,简单来说就是每次查找一个节点的时候,都把这一路径中的所有节点都赋予根节点作为路径。

原文没指出的地方:

也因为需要压缩,所以初始化的时候注意,不能如前面简单实用Union Find的算法那样初始化所有顶点的父母节点为-1,应该是初始化所有节点的父母节点为本身(自己繁殖自己?),然后就方便递归的时候一律可以返回这个跟节点了。

当然其实初始化为-1也是可以的,不过需要额外代码处理一下,也不难。

最后可以参考原文:http://www.geeksforgeeks.org/union-find-algorithm-set-2-union-by-rank/

#pragma once
#include <iostream>

class UnionFindUnionByRank
{
	struct Edge
	{
		int src, des;
	};

	struct Graph
	{
		int V, E;
		Edge *edges;
		Graph(int v, int e) : V(v), E(e)
		{
			edges = new Edge[e];
		}
		~Graph()
		{
			if (edges) delete [] edges;
		}
	};

	struct subSet
	{
		int parent, rank;
	};

	int find(subSet *subs, int i)
	{
		//因为要压缩,所以不能使用-1作为根的标志了
		if (subs[i].parent != i)
		{
			//Union by rank: attach smaller rank tree to high rank tree. It is so simple, but very hard to create it totally by ourself, so it's good to stand on the shoulder of the giant.
			subs[i].parent = find(subs, subs[i].parent);
		}
		return subs[i].parent;//因为如果-1作为根标志,那么这里就要返回i,就达不到压缩的效果了,而是应该返回parent,一层一层递归回上一层。
	}

	void unionTwo(subSet *subs, int x, int y)
	{
		int xroot = find(subs, x);
		int yroot = find(subs, y);

		if (subs[xroot].rank < subs[yroot].rank)
		{
			subs[xroot].parent = yroot;
		}
		else if (subs[xroot].rank > subs[yroot].rank)
		{
			subs[yroot].parent = xroot;
		}
		else
		{
			//only need to increment its rank when ther are equal rank
			subs[yroot].parent = xroot;
			subs[xroot].rank++;
		}
	}

	bool isCycle(Graph *gra)
	{
		subSet *subs = new subSet[gra->V];
		for (int i = 0; i < gra->V; i++)
		{
			subs[i].parent = i;//parent不能初始化为-1
			subs[i].rank = 0;
		}

		for (int e = 0; e < gra->E; e++)
		{
			int x = find(subs, gra->edges[e].src);
			int y = find(subs, gra->edges[e].des);

			if (x == y) return true;

			unionTwo(subs, x, y);
		}

		return false;
	}
public:
	UnionFindUnionByRank()
	{
		int V = 3, E = 3;
		struct Graph* graph = new Graph(V, E);

		// add edge 0-1
		graph->edges[0].src = 0;
		graph->edges[0].des = 1;

		// add edge 1-2
		graph->edges[1].src = 1;
		graph->edges[1].des = 2;

		// add edge 0-2
		graph->edges[2].src = 0;
		graph->edges[2].des = 2;

		if (isCycle(graph))
			printf( "Union By Rank found graph contains cycle \n" );
		else
			printf( "Union By Rank found graph doesn't contain cycle \n" );
	}
};

Geeks Union-Find Algorithm Union By Rank and Path Compression 图环算法,布布扣,bubuko.com

时间: 2024-10-09 07:22:28

Geeks Union-Find Algorithm Union By Rank and Path Compression 图环算法的相关文章

关于UNION ALL与 UNION 用法和区别

(转自:http://www.cnblogs.com/EricaMIN1987_IT/archive/2011/01/20/1940188.html) UNION指令的目的是将两个SQL语句的结果合并起来.从这个角度来看, 我们会产生这样的感觉,UNION跟JOIN似乎有些许类似,因为这两个指令都可以由多个表格中撷取资料. UNION的一个限制是两个SQL语句所产生的栏位需要是同样的资料种类.另外,当我们用 UNION这个指令时,我们只会看到不同的资料值 (类似 SELECT DISTINCT)

Geeks : Dijkstra’s Algorithm for Adjacency List Representation 最短路径

最短路径的O(ElgV)的解法. 使用邻接表存储图,使用堆操作选取下一个最小路径点. 本题的难度并不在最短路径本身这个算法,而是在于堆的操作: 1 使用双重指针操作堆的节点,可以省去直接复制操作堆节点,提高效率,并且这才是有效操作动态地址数据的方法,不用双重指针,我思考了下,觉得更加不好做. 2 使用一个数组记录当前顶点在堆中的位置,相当于一个hash表了,可以需要的时候,直接从表中查找表示顶点的堆节点在堆中的位置,要记得更新节点时维护好这个表. 3 释放内存的时候注意,弹出堆的节点可以马上释放

SQL Union和SQL Union All用法

SQL Union和SQL Union All用法SQL Union和SQL Union All用法SQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时,每条 SELECT 语句中的列的顺序必须相同. SQL UNION 语法SELECT column_name(s) FROM table_name1UNIONSELECT column_name(s)

转 SQL Union和SQL Union All两者用法区别效率以及与order by 和 group by配合问题

SQL Union和SQL Union All两者用法区别效率以及与order by 和 group by配合问题 SQL Union和SQL Union All用法 SQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时,每条 SELECT 语句中的列的顺序必须相同. SQL UNION 语法 SELECT column_name(s) FROM tab

union 和 all union

sql union用法和sql union all用法,sql union效率 1.sql union用法 sql union在查询中可以将两个SQL 语句的结果合并起来.如果这样看的话, UNION 跟 JOIN 是相似的,两个指令都可以由多个表格中撷取资料. sql union的一个限制是两个 SQL 语句所产生的栏位需要是同样的资料种类.另外,当我们用 UNION这个指令时,我们只会看到不同的资料值 (类似 SELECT DISTINCT). sql union只是将两个结果联结起来一起显

Algorithm One Day One -- 判断链表是否有环(上)

 Is a loop ? Question descrip as follows : Assume that wehave a head pointer to a link-list. Also assumethat we know the list is single-linked. Can you come up an algorithm to checkwhether this link list includes a loop by using O(n) time and O(1)

Havel–Hakimi algorithm(判断度数序列是否可图)

问题 J: Degree Sequence of Graph G 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Wang Haiyang is a strong and optimistic Chinese youngster. Although born and brought up in the northern inland city Harbin, he has deep love and yearns for the boundless oceans. After gr

AlgorithmsI Exercises: UnionFind

Question1 Give the id[] array that results from the following sequence of 6 unionoperations on a set of 10 items using the quick-find algorithm. 6-3 2-3 5-3 5-1 9-3 3-0 Your answer should be a sequence of 10 integers, separated by whitespace.Recall:

disjoint set

MAKE-SET.x/ creates a new set whose only member (and thus representative) is x. Since the sets are disjoint, we require that x not already be in some other set. UNION.x; y/ unites the dynamic sets that contain x and y, say Sx and Sy, into a new set t