作用: 判断两个节点是否 连通

union-find 连通性 - 图2

quick-find

思路: 通过类似传染的 方法 把相通的结点都变成同一个值

union-find 连通性 - 图3

  1. const arr = [0,1,2,3,4,5,6,7,8,9];
  2. const length = arr.length;
  3. const union = (p, q) => {
  4. if(arr[p] === arr[q]) {
  5. return ;
  6. }
  7. const tempNum = arr[p];
  8. for(let i = 0; i < length; i++) {
  9. if(arr[i] === tempNum) {
  10. arr[i] = arr[q]
  11. }
  12. }
  13. }
  14. const params = [
  15. [4, 3],
  16. [3, 8],
  17. [6, 5],
  18. [9, 4],
  19. [2, 1],
  20. [8, 9],
  21. [5, 0],
  22. [7, 2],
  23. [6, 1],
  24. [1, 0],
  25. [6, 7],
  26. ]
  27. params.forEach(v => {
  28. union(...v);
  29. })
  30. console.log(arr);

quick-union

思路: 通过 树形的方法 让新加入的节点的根节点 总是指向 另一个的根节点

与quick-find 的区别: quick-find需要每次都遍历数组所有值 quick-union 只需要在自己树进行查找就可以了 但是quick-union 的速度比较依赖输入的数据

union-find 连通性 - 图4

const arr = [0,1,2,3,4,5,6,7,8,9];
const length = arr.length;
const union = (p, q) => {
    // 查出根节点 p
    const pRoot = findRoot(p);
    const qRoot = findRoot(q);
    if(pRoot === qRoot) {
        return
    } else {
        arr[pRoot] = qRoot
    }
}

const findRoot = (k)=> {
    while(arr[k] !== k) {
        k = arr[k]
    }
    return k
}

const params = [
    [4, 3],
    [3, 8],
    [6, 5],
    [9, 4],
    [2, 1],
    [8, 9],
    [5, 0],
    [7, 2],
    [6, 1],
    [1, 0],
    [6, 7],
]
params.forEach(v => {
    union(...v);
})
console.log(arr);

加权quick-union

思路:给每个节点 设置一个值 来告知 这个节点树的深度, 两个树连接时候会 将浅的树加入到深的树中

union-find 连通性 - 图5

与不加权的quick-union的区别:quick-nuion总是 将后面的加入的节点拼接到 根节点去 而不给树加权, 让 深度浅的树 加到 深度深的树中 从而让 整体树的深度不会越变越深, 让树的深度均衡 解决了不加权时候算法的稳定性

image.png

const arr = [0,1,2,3,4,5,6,7,8,9];
const deepArr = [1,1,1,1,1,1,1,1,1,1]; //记录树深度
const length = arr.length;
const union = (p, q) => {
    // 查出根节点 p
    const pRoot = findRoot(p);
    const qRoot = findRoot(q);
    if(pRoot === qRoot) {
        return
    } else {
        if(deepArr[pRoot] >= deepArr[qRoot] ) {
            // 根深度相加
            arr[qRoot] = pRoot;
            deepArr[pRoot] += deepArr[qRoot];
        } else {
            arr[pRoot] = qRoot;
            deepArr[qRoot] += deepArr[pRoot];
        }

    }
}

const findRoot = (k)=> {
    while(arr[k] !== k) {
        k = arr[k]
    }
    return k
}

const params = [
    [4, 3],
    [3, 8],
    [6, 5],
    [9, 4],
    [2, 1],
    [8, 9],
    [5, 0],
    [7, 2],
    [6, 1],
    [1, 0],
    [6, 7],
]
params.forEach(v => {
    union(...v);
})
console.log(arr);