并查集
查找一个图里面是否有环
//并查集 查询一个图里面是否有环
//作为测试这里先定义一个图graph
//现在有 ‘0 1 2 3 4 5’这6个结点,graph表示了这6个结点之间的连接情况
let graph = [[0, 1], [1, 2], [1, 3], [2, 5], [2, 4], [3, 4]];
//定义一个数组存放每个结点的父结点 parent[i]存放第i个结点的父结点,初始值为-1
let parent = [];
for (let i = 0; i < 6; i ++) {
parent.push(-1);
}
//为了避免生成的并集树的高度太高导致查找根结点的时候耗费太多性能 设置rank数组
//rank[i]存放以i为根结点的时候树的高度 初始高度都为0
let rank = [];
for (let i = 0; i < 6; i ++) {
rank.push(0);
}
//查找一个结点的根结点
const findRoot = (i, parent) => {
let root = i;
while (parent[root] !== -1) {
root = parent[root];
}
return root;
}
//如果两个结点能够有相同的根结点 就代表这两个结点相互联通 在一个集合里
//合并相连的结点:将这两个点的根结点相连
const union_vertices = (x, y, parent, rank) => {
let root_x = findRoot(x, parent);
let root_y = findRoot(y, parent);
if (root_x === root_y) {
//如果发现x和y的根结点 root_x 和 root_y 是同一个点 就说明该图已经成环
return 1;
} else {
//看以root_x 和 以 root_y 为根结点的树谁的高度高,高度高的作为新树的根结点 新树的高度不变
if (rank[root_x] > rank[root_y]) {
parent[root_y] = root_x;
} else if (rank[root_x] < rank[root_y]) {
parent[root_x] = root_y;
} else {
//如果以root_x 和 以 root_y 为根结点的树的高度相同,那么这里规定把root_y放在root_x上 rank[root_x]的高度加1
parent[root_y] = root_x;
rank[root_x] ++;
}
return -1;
}
}
const findCircle = (graph, parent, rank) => {
for (let i = 0; i < graph.length; i ++) {
if(union_vertices(graph[i][0], graph[i][1], parent, rank) === 1) {
console.log('Find Circle')
return 1;
}
}
console.log('No Circle Find');
return -1;
}
findCircle(graph, parent, rank);
ref:
https://www.youtube.com/watch?v=YKE4Vd1ysPI
https://www.youtube.com/watch?v=gpmOaSBcbYA
https://www.youtube.com/watch?v=zos–xohLT0